diff options
Diffstat (limited to 'lib/libalpm/be_local.c')
-rw-r--r-- | lib/libalpm/be_local.c | 278 |
1 files changed, 179 insertions, 99 deletions
diff --git a/lib/libalpm/be_local.c b/lib/libalpm/be_local.c index 56cf38bb..a8c8468b 100644 --- a/lib/libalpm/be_local.c +++ b/lib/libalpm/be_local.c @@ -1,7 +1,7 @@ /* * be_local.c : backend for the local database * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify @@ -18,8 +18,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include <unistd.h> #include <stdio.h> #include <stdlib.h> @@ -28,7 +26,6 @@ #include <stdint.h> /* intmax_t */ #include <sys/stat.h> #include <dirent.h> -#include <time.h> #include <limits.h> /* PATH_MAX */ /* libalpm */ @@ -69,13 +66,13 @@ static const char *_cache_get_url(alpm_pkg_t *pkg) return pkg->url; } -static time_t _cache_get_builddate(alpm_pkg_t *pkg) +static alpm_time_t _cache_get_builddate(alpm_pkg_t *pkg) { LAZY_LOAD(INFRQ_DESC, 0); return pkg->builddate; } -static time_t _cache_get_installdate(alpm_pkg_t *pkg) +static alpm_time_t _cache_get_installdate(alpm_pkg_t *pkg) { LAZY_LOAD(INFRQ_DESC, 0); return pkg->installdate; @@ -105,6 +102,12 @@ static alpm_pkgreason_t _cache_get_reason(alpm_pkg_t *pkg) return pkg->reason; } +static alpm_pkgvalidation_t _cache_get_validation(alpm_pkg_t *pkg) +{ + LAZY_LOAD(INFRQ_DESC, -1); + return pkg->validation; +} + static alpm_list_t *_cache_get_licenses(alpm_pkg_t *pkg) { LAZY_LOAD(INFRQ_DESC, NULL); @@ -226,6 +229,7 @@ static struct pkg_operations local_pkg_ops = { .get_arch = _cache_get_arch, .get_isize = _cache_get_isize, .get_reason = _cache_get_reason, + .get_validation = _cache_get_validation, .has_scriptlet = _cache_has_scriptlet, .get_licenses = _cache_get_licenses, .get_groups = _cache_get_groups, @@ -401,12 +405,11 @@ static int local_db_populate(alpm_db_t *db) rewinddir(dbdir); } if(est_count >= 2) { - /* subtract the two extra pointers to get # of children */ + /* subtract the '.' and '..' pointers to get # of children */ est_count -= 2; } - /* initialize hash at 50% full */ - db->pkgcache = _alpm_pkghash_create(est_count * 2); + db->pkgcache = _alpm_pkghash_create(est_count); if(db->pkgcache == NULL){ closedir(dbdir); RET_ERR(db->handle, ALPM_ERR_MEMORY, -1); @@ -445,7 +448,7 @@ static int local_db_populate(alpm_db_t *db) continue; } - pkg->origin = PKG_FROM_LOCALDB; + pkg->origin = ALPM_PKG_FROM_LOCALDB; pkg->origin_data.db = db; pkg->ops = &local_pkg_ops; pkg->handle = db->handle; @@ -475,7 +478,8 @@ static int local_db_populate(alpm_db_t *db) } /* Note: the return value must be freed by the caller */ -char *_alpm_local_db_pkgpath(alpm_db_t *db, alpm_pkg_t *info, const char *filename) +char *_alpm_local_db_pkgpath(alpm_db_t *db, alpm_pkg_t *info, + const char *filename) { size_t len; char *pkgpath; @@ -492,7 +496,7 @@ char *_alpm_local_db_pkgpath(alpm_db_t *db, alpm_pkg_t *info, const char *filena #define READ_NEXT() do { \ if(fgets(line, sizeof(line), fp) == NULL && !feof(fp)) goto error; \ - _alpm_strip_newline(line); \ + _alpm_strip_newline(line, 0); \ } while(0) #define READ_AND_STORE(f) do { \ @@ -505,7 +509,7 @@ char *_alpm_local_db_pkgpath(alpm_db_t *db, alpm_pkg_t *info, const char *filena if(fgets(line, sizeof(line), fp) == NULL) {\ if(!feof(fp)) goto error; else break; \ } \ - if(_alpm_strip_newline(line) == 0) break; \ + if(_alpm_strip_newline(line, 0) == 0) break; \ STRDUP(linedup, line, goto error); \ f = alpm_list_add(f, linedup); \ } while(1) /* note the while(1) and not (0) */ @@ -514,7 +518,7 @@ char *_alpm_local_db_pkgpath(alpm_db_t *db, alpm_pkg_t *info, const char *filena if(fgets(line, sizeof(line), fp) == NULL) {\ if(!feof(fp)) goto error; else break; \ } \ - if(_alpm_strip_newline(line) == 0) break; \ + if(_alpm_strip_newline(line, 0) == 0) break; \ f = alpm_list_add(f, _alpm_splitdep(line)); \ } while(1) /* note the while(1) and not (0) */ @@ -522,7 +526,6 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq) { FILE *fp = NULL; char line[1024]; - char *pkgpath; alpm_db_t *db = info->origin_data.db; /* bitmask logic here: @@ -541,18 +544,10 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq) return -1; } - _alpm_log(db->handle, ALPM_LOG_FUNCTION, "loading package data for %s : level=0x%x\n", + _alpm_log(db->handle, ALPM_LOG_FUNCTION, + "loading package data for %s : level=0x%x\n", info->name, inforeq); - pkgpath = _alpm_local_db_pkgpath(db, info, NULL); - if(!pkgpath || access(pkgpath, F_OK)) { - /* directory doesn't exist or can't be opened */ - _alpm_log(db->handle, ALPM_LOG_DEBUG, "cannot find '%s-%s' in db '%s'\n", - info->name, info->version, db->treename); - goto error; - } - free(pkgpath); - /* clear out 'line', to be certain - and to make valgrind happy */ memset(line, 0, sizeof(line)); @@ -569,7 +564,7 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq) if(fgets(line, sizeof(line), fp) == NULL && !feof(fp)) { goto error; } - if(_alpm_strip_newline(line) == 0) { + if(_alpm_strip_newline(line, 0) == 0) { /* length of stripped line was zero */ continue; } @@ -606,6 +601,26 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq) } else if(strcmp(line, "%REASON%") == 0) { READ_NEXT(); info->reason = (alpm_pkgreason_t)atoi(line); + } else if(strcmp(line, "%VALIDATION%") == 0) { + alpm_list_t *i, *v = NULL; + READ_AND_STORE_ALL(v); + for(i = v; i; i = alpm_list_next(i)) + { + if(strcmp(i->data, "none") == 0) { + info->validation |= ALPM_PKG_VALIDATION_NONE; + } else if(strcmp(i->data, "md5") == 0) { + info->validation |= ALPM_PKG_VALIDATION_MD5SUM; + } else if(strcmp(i->data, "sha256") == 0) { + info->validation |= ALPM_PKG_VALIDATION_SHA256SUM; + } else if(strcmp(i->data, "pgp") == 0) { + info->validation |= ALPM_PKG_VALIDATION_SIGNATURE; + } else { + _alpm_log(db->handle, ALPM_LOG_WARNING, + _("unknown validation type for package %s: %s\n"), + info->name, (const char *)i->data); + } + } + FREELIST(v); } else if(strcmp(line, "%SIZE%") == 0) { READ_NEXT(); info->isize = _alpm_strtoofft(line); @@ -614,7 +629,7 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq) } else if(strcmp(line, "%DEPENDS%") == 0) { READ_AND_SPLITDEP(info->depends); } else if(strcmp(line, "%OPTDEPENDS%") == 0) { - READ_AND_STORE_ALL(info->optdepends); + READ_AND_SPLITDEP(info->optdepends); } else if(strcmp(line, "%CONFLICTS%") == 0) { READ_AND_SPLITDEP(info->conflicts); } else if(strcmp(line, "%PROVIDES%") == 0) { @@ -636,12 +651,13 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq) } free(path); while(fgets(line, sizeof(line), fp)) { - _alpm_strip_newline(line); + _alpm_strip_newline(line, 0); if(strcmp(line, "%FILES%") == 0) { - size_t files_count = 0, files_size = 0; + size_t files_count = 0, files_size = 0, len; alpm_file_t *files = NULL; - while(fgets(line, sizeof(line), fp) && _alpm_strip_newline(line)) { + while(fgets(line, sizeof(line), fp) && + (len = _alpm_strip_newline(line, 0))) { if(files_count >= files_size) { size_t old_size = files_size; if(files_size == 0) { @@ -651,7 +667,7 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq) } files = realloc(files, sizeof(alpm_file_t) * files_size); if(!files) { - ALLOC_FAIL(sizeof(alpm_file_t) * files_size); + _alpm_alloc_fail(sizeof(alpm_file_t) * files_size); goto error; } /* ensure all new memory is zeroed out, in both the initial @@ -659,16 +675,25 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq) memset(files + old_size, 0, sizeof(alpm_file_t) * (files_size - old_size)); } - STRDUP(files[files_count].name, line, goto error); - /* TODO: lstat file, get mode/size */ + /* since we know the length of the file string already, + * we can do malloc + memcpy rather than strdup */ + len += 1; + files[files_count].name = malloc(len); + if(files[files_count].name == NULL) { + _alpm_alloc_fail(len); + goto error; + } + memcpy(files[files_count].name, line, len); files_count++; } /* attempt to hand back any memory we don't need */ files = realloc(files, sizeof(alpm_file_t) * files_count); + /* make sure the list is sorted */ + qsort(files, files_count, sizeof(alpm_file_t), _alpm_files_cmp); info->files.count = files_count; info->files.files = files; } else if(strcmp(line, "%BACKUP%") == 0) { - while(fgets(line, sizeof(line), fp) && _alpm_strip_newline(line)) { + while(fgets(line, sizeof(line), fp) && _alpm_strip_newline(line, 0)) { alpm_backup_t *backup; CALLOC(backup, 1, sizeof(alpm_backup_t), goto error); if(_alpm_split_backup(line, &backup)) { @@ -727,6 +752,23 @@ int _alpm_local_db_prepare(alpm_db_t *db, alpm_pkg_t *info) return retval; } +static void write_deps(FILE *fp, const char *header, alpm_list_t *deplist) +{ + alpm_list_t *lp; + if(!deplist) { + return; + } + fputs(header, fp); + fputc('\n', fp); + for(lp = deplist; lp; lp = lp->next) { + char *depstring = alpm_dep_compute_string(lp->data); + fputs(depstring, fp); + fputc('\n', fp); + free(depstring); + } + fputc('\n', fp); +} + int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, alpm_dbinfrq_t inforeq) { FILE *fp = NULL; @@ -744,7 +786,8 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, alpm_dbinfrq_t inforeq /* DESC */ if(inforeq & INFRQ_DESC) { char *path; - _alpm_log(db->handle, ALPM_LOG_DEBUG, "writing %s-%s DESC information back to db\n", + _alpm_log(db->handle, ALPM_LOG_DEBUG, + "writing %s-%s DESC information back to db\n", info->name, info->version); path = _alpm_local_db_pkgpath(db, info, "desc"); if(!path || (fp = fopen(path, "w")) == NULL) { @@ -761,44 +804,21 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, alpm_dbinfrq_t inforeq fprintf(fp, "%%DESC%%\n" "%s\n\n", info->desc); } - if(info->groups) { - fputs("%GROUPS%\n", fp); - for(lp = info->groups; lp; lp = lp->next) { - fprintf(fp, "%s\n", (char *)lp->data); - } - fprintf(fp, "\n"); - } - if(info->replaces) { - fputs("%REPLACES%\n", fp); - for(lp = info->replaces; lp; lp = lp->next) { - char *depstring = alpm_dep_compute_string(lp->data); - fprintf(fp, "%s\n", depstring); - free(depstring); - } - fprintf(fp, "\n"); - } if(info->url) { fprintf(fp, "%%URL%%\n" "%s\n\n", info->url); } - if(info->licenses) { - fputs("%LICENSE%\n", fp); - for(lp = info->licenses; lp; lp = lp->next) { - fprintf(fp, "%s\n", (char *)lp->data); - } - fprintf(fp, "\n"); - } if(info->arch) { fprintf(fp, "%%ARCH%%\n" "%s\n\n", info->arch); } if(info->builddate) { fprintf(fp, "%%BUILDDATE%%\n" - "%ld\n\n", info->builddate); + "%jd\n\n", (intmax_t)info->builddate); } if(info->installdate) { fprintf(fp, "%%INSTALLDATE%%\n" - "%ld\n\n", info->installdate); + "%jd\n\n", (intmax_t)info->installdate); } if(info->packager) { fprintf(fp, "%%PACKAGER%%\n" @@ -813,41 +833,45 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, alpm_dbinfrq_t inforeq fprintf(fp, "%%REASON%%\n" "%u\n\n", info->reason); } - if(info->depends) { - fputs("%DEPENDS%\n", fp); - for(lp = info->depends; lp; lp = lp->next) { - char *depstring = alpm_dep_compute_string(lp->data); - fprintf(fp, "%s\n", depstring); - free(depstring); + if(info->groups) { + fputs("%GROUPS%\n", fp); + for(lp = info->groups; lp; lp = lp->next) { + fputs(lp->data, fp); + fputc('\n', fp); + } + fputc('\n', fp); + } + if(info->licenses) { + fputs("%LICENSE%\n", fp); + for(lp = info->licenses; lp; lp = lp->next) { + fputs(lp->data, fp); + fputc('\n', fp); } - fprintf(fp, "\n"); + fputc('\n', fp); } - if(info->optdepends) { - fputs("%OPTDEPENDS%\n", fp); - for(lp = info->optdepends; lp; lp = lp->next) { - fprintf(fp, "%s\n", (char *)lp->data); + if(info->validation) { + fputs("%VALIDATION%\n", fp); + if(info->validation & ALPM_PKG_VALIDATION_NONE) { + fputs("none\n", fp); + } + if(info->validation & ALPM_PKG_VALIDATION_MD5SUM) { + fputs("md5\n", fp); } - fprintf(fp, "\n"); - } - if(info->conflicts) { - fputs("%CONFLICTS%\n", fp); - for(lp = info->conflicts; lp; lp = lp->next) { - char *depstring = alpm_dep_compute_string(lp->data); - fprintf(fp, "%s\n", depstring); - free(depstring); + if(info->validation & ALPM_PKG_VALIDATION_SHA256SUM) { + fputs("sha256\n", fp); } - fprintf(fp, "\n"); - } - if(info->provides) { - fputs("%PROVIDES%\n", fp); - for(lp = info->provides; lp; lp = lp->next) { - char *depstring = alpm_dep_compute_string(lp->data); - fprintf(fp, "%s\n", depstring); - free(depstring); + if(info->validation & ALPM_PKG_VALIDATION_SIGNATURE) { + fputs("pgp\n", fp); } - fprintf(fp, "\n"); + fputc('\n', fp); } + write_deps(fp, "%REPLACES%", info->replaces); + write_deps(fp, "%DEPENDS%", info->depends); + write_deps(fp, "%OPTDEPENDS%", info->optdepends); + write_deps(fp, "%CONFLICTS%", info->conflicts); + write_deps(fp, "%PROVIDES%", info->provides); + fclose(fp); fp = NULL; } @@ -855,7 +879,8 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, alpm_dbinfrq_t inforeq /* FILES */ if(inforeq & INFRQ_FILES) { char *path; - _alpm_log(db->handle, ALPM_LOG_DEBUG, "writing %s-%s FILES information back to db\n", + _alpm_log(db->handle, ALPM_LOG_DEBUG, + "writing %s-%s FILES information back to db\n", info->name, info->version); path = _alpm_local_db_pkgpath(db, info, "files"); if(!path || (fp = fopen(path, "w")) == NULL) { @@ -868,20 +893,21 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, alpm_dbinfrq_t inforeq free(path); if(info->files.count) { size_t i; - fprintf(fp, "%%FILES%%\n"); + fputs("%FILES%\n", fp); for(i = 0; i < info->files.count; i++) { const alpm_file_t *file = info->files.files + i; - fprintf(fp, "%s\n", file->name); + fputs(file->name, fp); + fputc('\n', fp); } - fprintf(fp, "\n"); + fputc('\n', fp); } if(info->backup) { - fprintf(fp, "%%BACKUP%%\n"); + fputs("%BACKUP%\n", fp); for(lp = info->backup; lp; lp = lp->next) { const alpm_backup_t *backup = lp->data; fprintf(fp, "%s\t%s\n", backup->name, backup->hash); } - fprintf(fp, "\n"); + fputc('\n', fp); } fclose(fp); fp = NULL; @@ -903,17 +929,71 @@ cleanup: int _alpm_local_db_remove(alpm_db_t *db, alpm_pkg_t *info) { int ret = 0; - char *pkgpath = _alpm_local_db_pkgpath(db, info, NULL); + DIR *dirp; + struct dirent *dp; + char *pkgpath; + size_t pkgpath_len; - /* TODO explicit file removes and then an rmdir? */ - ret = _alpm_rmrf(pkgpath); - free(pkgpath); - if(ret != 0) { + pkgpath = _alpm_local_db_pkgpath(db, info, NULL); + if(!pkgpath) { + return -1; + } + pkgpath_len = strlen(pkgpath); + + dirp = opendir(pkgpath); + if(!dirp) { + return -1; + } + /* go through the local DB entry, removing the files within, which we know + * are not nested directories of any kind. */ + for(dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { + if(strcmp(dp->d_name, "..") != 0 && strcmp(dp->d_name, ".") != 0) { + char name[PATH_MAX]; + if(pkgpath_len + strlen(dp->d_name) + 2 > PATH_MAX) { + /* file path is too long to remove, hmm. */ + ret = -1; + } else { + sprintf(name, "%s/%s", pkgpath, dp->d_name); + if(unlink(name)) { + ret = -1; + } + } + } + } + closedir(dirp); + + /* after removing all enclosed files, we can remove the directory itself. */ + if(rmdir(pkgpath)) { ret = -1; } + free(pkgpath); return ret; } +int SYMEXPORT alpm_pkg_set_reason(alpm_pkg_t *pkg, alpm_pkgreason_t reason) +{ + ASSERT(pkg != NULL, return -1); + ASSERT(pkg->origin == ALPM_PKG_FROM_LOCALDB, + RET_ERR(pkg->handle, ALPM_ERR_WRONG_ARGS, -1)); + ASSERT(pkg->origin_data.db == pkg->handle->db_local, + RET_ERR(pkg->handle, ALPM_ERR_WRONG_ARGS, -1)); + + _alpm_log(pkg->handle, ALPM_LOG_DEBUG, + "setting install reason %u for %s\n", reason, pkg->name); + if(alpm_pkg_get_reason(pkg) == reason) { + /* we are done */ + return 0; + } + /* set reason (in pkgcache) */ + pkg->reason = reason; + /* write DESC */ + if(_alpm_local_db_write(pkg->handle->db_local, pkg, INFRQ_DESC)) { + RET_ERR(pkg->handle, ALPM_ERR_DB_WRITE, -1); + } + + return 0; +} + struct db_operations local_db_ops = { .validate = local_db_validate, .populate = local_db_populate, |