From db3b86e7f34f4c3ccb42e98465f2069aa642a85f Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Tue, 7 Jun 2011 17:29:55 -0500 Subject: Do database signature checking at load time This is the ideal place to do it as all clients should be checking the return value and ensuring there are no errors. This is similar to pkg_load(). We also add an additional step of validation after we download a new database; a subsequent '-y' operation can potentially invalidate the original check at registration time. Note that this implementation is still a bit naive; if a signature is invalid it is currently impossible to refresh and re-download the file without manually deleting it first. Similarly, if one downloads a database and the check fails, the database object is still there and can be used. These shortcomings will be addressed in a future commit. Signed-off-by: Dan McGee --- src/pacman/conf.c | 16 +++------------- src/util/cleanupdelta.c | 2 +- src/util/testdb.c | 2 +- 3 files changed, 5 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/pacman/conf.c b/src/pacman/conf.c index 081cdd5e..5c2a11d3 100644 --- a/src/pacman/conf.c +++ b/src/pacman/conf.c @@ -460,7 +460,7 @@ static int setup_libalpm(void) ret = alpm_option_set_logfile(handle, config->logfile); if(ret != 0) { pm_printf(PM_LOG_ERROR, _("problem setting logfile '%s' (%s)\n"), - config->logfile, alpm_strerror(alpm_errno(config->handle))); + config->logfile, alpm_strerror(alpm_errno(handle))); return ret; } @@ -470,7 +470,7 @@ static int setup_libalpm(void) ret = alpm_option_set_gpgdir(handle, config->gpgdir); if(ret != 0) { pm_printf(PM_LOG_ERROR, _("problem setting gpgdir '%s' (%s)\n"), - config->gpgdir, alpm_strerror(alpm_errno(config->handle))); + config->gpgdir, alpm_strerror(alpm_errno(handle))); return ret; } @@ -542,7 +542,7 @@ static int finish_section(struct section_t *section, int parse_options) } /* if we are not looking at options sections only, register a db */ - db = alpm_db_register_sync(config->handle, section->name); + db = alpm_db_register_sync(config->handle, section->name, section->sigverify); if(db == NULL) { pm_printf(PM_LOG_ERROR, _("could not register '%s' database (%s)\n"), section->name, alpm_strerror(alpm_errno(config->handle))); @@ -550,16 +550,6 @@ static int finish_section(struct section_t *section, int parse_options) goto cleanup; } - if(section->sigverify) { - if(alpm_db_set_pgp_verify(db, section->sigverify)) { - pm_printf(PM_LOG_ERROR, - _("could not set verify option for database '%s' (%s)\n"), - section->name, alpm_strerror(alpm_errno(config->handle))); - ret = 1; - goto cleanup; - } - } - for(i = section->servers; i; i = alpm_list_next(i)) { char *value = alpm_list_getdata(i); if(_add_mirror(db, value) != 0) { diff --git a/src/util/cleanupdelta.c b/src/util/cleanupdelta.c index 98291706..5ee59dbb 100644 --- a/src/util/cleanupdelta.c +++ b/src/util/cleanupdelta.c @@ -75,7 +75,7 @@ static void checkdbs(const char *dbpath, alpm_list_t *dbnames) { for(i = dbnames; i; i = alpm_list_next(i)) { char *dbname = alpm_list_getdata(i); snprintf(syncdbpath, PATH_MAX, "%s/sync/%s", dbpath, dbname); - db = alpm_db_register_sync(handle, dbname); + db = alpm_db_register_sync(handle, dbname, PM_PGP_VERIFY_OPTIONAL); if(db == NULL) { fprintf(stderr, "error: could not register sync database (%s)\n", alpm_strerror(alpm_errno(handle))); diff --git a/src/util/testdb.c b/src/util/testdb.c index 4937480d..af5007e2 100644 --- a/src/util/testdb.c +++ b/src/util/testdb.c @@ -151,7 +151,7 @@ static int check_syncdbs(alpm_list_t *dbnames) { for(i = dbnames; i; i = alpm_list_next(i)) { char *dbname = alpm_list_getdata(i); - db = alpm_db_register_sync(handle, dbname); + db = alpm_db_register_sync(handle, dbname, PM_PGP_VERIFY_OPTIONAL); if(db == NULL) { fprintf(stderr, "error: could not register sync database (%s)\n", alpm_strerror(alpm_errno(handle))); -- cgit v1.2.3-70-g09d2 From 1150d9e15aaea2ae1f259995d11442f491ef0af7 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Wed, 20 Apr 2011 19:54:01 -0500 Subject: Move database 'version' check to registration time This is another step toward doing both local database validation (ensuring we don't have depends files) and sync database validation (via signatures if present) when the database is registered. Signed-off-by: Dan McGee --- lib/libalpm/alpm.c | 2 +- lib/libalpm/be_local.c | 111 ++++++++++++++++++++++++++----------------------- lib/libalpm/be_sync.c | 6 --- lib/libalpm/db.c | 13 ------ lib/libalpm/db.h | 1 - lib/libalpm/trans.c | 12 ------ src/pacman/conf.c | 3 ++ src/pacman/util.c | 3 -- 8 files changed, 62 insertions(+), 89 deletions(-) (limited to 'src') diff --git a/lib/libalpm/alpm.c b/lib/libalpm/alpm.c index 9b9719d1..b0bbbe8c 100644 --- a/lib/libalpm/alpm.c +++ b/lib/libalpm/alpm.c @@ -70,7 +70,7 @@ pmhandle_t SYMEXPORT *alpm_initialize(const char *root, const char *dbpath, snprintf(myhandle->lockfile, lockfilelen, "%s%s", myhandle->dbpath, lf); if(_alpm_db_register_local(myhandle) == NULL) { - myerr = PM_ERR_DB_CREATE; + myerr = myhandle->pm_errno; goto cleanup; } diff --git a/lib/libalpm/be_local.c b/lib/libalpm/be_local.c index 4b2a3017..0ff51deb 100644 --- a/lib/libalpm/be_local.c +++ b/lib/libalpm/be_local.c @@ -314,6 +314,56 @@ static int is_dir(const char *path, struct dirent *entry) return 0; } +static int local_db_validate(pmdb_t *db) +{ + struct dirent *ent = NULL; + const char *dbpath; + DIR *dbdir; + int ret = -1; + + dbpath = _alpm_db_path(db); + if(dbpath == NULL) { + RET_ERR(db->handle, PM_ERR_DB_OPEN, -1); + } + dbdir = opendir(dbpath); + if(dbdir == NULL) { + if(errno == ENOENT) { + /* database dir doesn't exist yet */ + return 0; + } else { + RET_ERR(db->handle, PM_ERR_DB_OPEN, -1); + } + } + + while((ent = readdir(dbdir)) != NULL) { + const char *name = ent->d_name; + char path[PATH_MAX]; + + if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { + continue; + } + if(!is_dir(dbpath, ent)) { + continue; + } + + snprintf(path, PATH_MAX, "%s%s/depends", dbpath, name); + if(access(path, F_OK) == 0) { + /* we found a depends file- bail */ + db->handle->pm_errno = PM_ERR_DB_VERSION; + goto done; + } + } + /* we found no depends file after full scan */ + ret = 0; + +done: + if(dbdir) { + closedir(dbdir); + } + + return ret; +} + static int local_db_populate(pmdb_t *db) { size_t est_count; @@ -328,6 +378,7 @@ static int local_db_populate(pmdb_t *db) /* pm_errno set in _alpm_db_path() */ return -1; } + dbdir = opendir(dbpath); if(dbdir == NULL) { if(errno == ENOENT) { @@ -867,62 +918,9 @@ int _alpm_local_db_remove(pmdb_t *db, pmpkg_t *info) return ret; } -static int local_db_version(pmdb_t *db) -{ - struct dirent *ent = NULL; - const char *dbpath; - DIR *dbdir; - int version; - - dbpath = _alpm_db_path(db); - if(dbpath == NULL) { - RET_ERR(db->handle, PM_ERR_DB_OPEN, -1); - } - dbdir = opendir(dbpath); - if(dbdir == NULL) { - if(errno == ENOENT) { - /* database dir doesn't exist yet */ - version = 2; - goto done; - } else { - RET_ERR(db->handle, PM_ERR_DB_OPEN, -1); - } - } - - while((ent = readdir(dbdir)) != NULL) { - const char *name = ent->d_name; - char path[PATH_MAX]; - - if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { - continue; - } - if(!is_dir(dbpath, ent)) { - continue; - } - - snprintf(path, PATH_MAX, "%s%s/depends", dbpath, name); - if(access(path, F_OK) == 0) { - /* we found a depends file- bail */ - version = 1; - goto done; - } - } - /* we found no depends file after full scan */ - version = 2; - -done: - if(dbdir) { - closedir(dbdir); - } - - _alpm_log(db->handle, PM_LOG_DEBUG, "local database version %d\n", version); - return version; -} - struct db_operations local_db_ops = { .populate = local_db_populate, .unregister = _alpm_db_unregister, - .version = local_db_version, }; pmdb_t *_alpm_db_register_local(pmhandle_t *handle) @@ -933,11 +931,18 @@ pmdb_t *_alpm_db_register_local(pmhandle_t *handle) db = _alpm_db_new("local", 1); if(db == NULL) { + handle->pm_errno = PM_ERR_DB_CREATE; return NULL; } db->ops = &local_db_ops; db->handle = handle; + if(local_db_validate(db)) { + /* pm_errno set in local_db_validate() */ + _alpm_db_free(db); + return NULL; + } + handle->db_local = db; return db; } diff --git a/lib/libalpm/be_sync.c b/lib/libalpm/be_sync.c index 2cf90544..1a434f24 100644 --- a/lib/libalpm/be_sync.c +++ b/lib/libalpm/be_sync.c @@ -559,15 +559,9 @@ error: return -1; } -static int sync_db_version(pmdb_t UNUSED *db) -{ - return 2; -} - struct db_operations sync_db_ops = { .populate = sync_db_populate, .unregister = _alpm_db_unregister, - .version = sync_db_version, }; pmdb_t *_alpm_db_register_sync(pmhandle_t *handle, const char *treename, diff --git a/lib/libalpm/db.c b/lib/libalpm/db.c index 2b50c064..820261a1 100644 --- a/lib/libalpm/db.c +++ b/lib/libalpm/db.c @@ -370,14 +370,6 @@ const char *_alpm_db_path(pmdb_t *db) return db->_path; } -int _alpm_db_version(pmdb_t *db) -{ - if(!db) { - return -1; - } - return db->ops->version(db); -} - char *_alpm_db_sig_path(pmdb_t *db) { char *sigpath; @@ -522,11 +514,6 @@ pmpkghash_t *_alpm_db_get_pkgcache_hash(pmdb_t *db) _alpm_db_load_pkgcache(db); } - /* hmmm, still NULL ?*/ - if(!db->pkgcache) { - _alpm_log(db->handle, PM_LOG_DEBUG, "warning: pkgcache is NULL for db '%s'\n", db->treename); - } - return db->pkgcache; } diff --git a/lib/libalpm/db.h b/lib/libalpm/db.h index c5fcd5f0..4541c258 100644 --- a/lib/libalpm/db.h +++ b/lib/libalpm/db.h @@ -46,7 +46,6 @@ typedef enum _pmdbinfrq_t { struct db_operations { int (*populate) (pmdb_t *); void (*unregister) (pmdb_t *); - int (*version) (pmdb_t *); }; /* Database */ diff --git a/lib/libalpm/trans.c b/lib/libalpm/trans.c index f0744937..b4bdccfb 100644 --- a/lib/libalpm/trans.c +++ b/lib/libalpm/trans.c @@ -101,8 +101,6 @@ int SYMEXPORT alpm_trans_init(pmhandle_t *handle, pmtransflag_t flags, alpm_trans_cb_progress progress) { pmtrans_t *trans; - const int required_db_version = 2; - int db_version; /* Sanity checks */ CHECK_HANDLE(handle, return -1); @@ -122,16 +120,6 @@ int SYMEXPORT alpm_trans_init(pmhandle_t *handle, pmtransflag_t flags, trans->cb_progress = progress; trans->state = STATE_INITIALIZED; - /* check database version */ - db_version = _alpm_db_version(handle->db_local); - if(db_version < required_db_version) { - _alpm_log(handle, PM_LOG_ERROR, - _("%s database version is too old\n"), handle->db_local->treename); - remove_lock(handle); - _alpm_trans_free(trans); - RET_ERR(handle, PM_ERR_DB_VERSION, -1); - } - handle->trans = trans; return 0; diff --git a/src/pacman/conf.c b/src/pacman/conf.c index 5c2a11d3..c5f78d40 100644 --- a/src/pacman/conf.c +++ b/src/pacman/conf.c @@ -449,6 +449,9 @@ static int setup_libalpm(void) if(!handle) { pm_printf(PM_LOG_ERROR, _("failed to initialize alpm library (%s)\n"), alpm_strerror(err)); + if(err == PM_ERR_DB_VERSION) { + fprintf(stderr, _(" try running pacman-db-upgrade\n")); + } return -1; } config->handle = handle; diff --git a/src/pacman/util.c b/src/pacman/util.c index 66f127c6..77a7e56c 100644 --- a/src/pacman/util.c +++ b/src/pacman/util.c @@ -68,9 +68,6 @@ int trans_init(pmtransflag_t flags) " running, you can remove %s\n"), alpm_option_get_lockfile(config->handle)); } - else if(err == PM_ERR_DB_VERSION) { - fprintf(stderr, _(" try running pacman-db-upgrade\n")); - } return -1; } -- cgit v1.2.3-70-g09d2 From 79e98316ea89486d107466858543e965bcfbb0a9 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Tue, 7 Jun 2011 20:42:15 -0500 Subject: Add a 'valid' flag to the database object Start by converting all of our flags to a 'status' bitmask (pkgcache status, grpcache status). Add a new 'valid' flag as well. This will let us keep track if the database itself has been marked valid in whatever fashion. For local databases at the moment we ensure there are no depends files; for sync databases we ensure the PGP signature is valid if required/requested. The loading of the pkgcache is prohibited if the database is invalid. Signed-off-by: Dan McGee --- lib/libalpm/alpm.h | 1 + lib/libalpm/be_local.c | 6 ++++++ lib/libalpm/be_sync.c | 12 ++++++++++- lib/libalpm/db.c | 49 ++++++++++++++++++++++-------------------- lib/libalpm/db.h | 14 +++++++----- lib/libalpm/error.c | 2 ++ lib/libalpm/trans.c | 8 +++++++ src/pacman/conf.c | 2 +- test/pacman/tests/ignore007.py | 2 +- 9 files changed, 65 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index eb2eff88..579b45f2 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -1002,6 +1002,7 @@ enum _pmerrno_t { PM_ERR_DB_NULL, PM_ERR_DB_NOT_NULL, PM_ERR_DB_NOT_FOUND, + PM_ERR_DB_INVALID, PM_ERR_DB_VERSION, PM_ERR_DB_WRITE, PM_ERR_DB_REMOVE, diff --git a/lib/libalpm/be_local.c b/lib/libalpm/be_local.c index 0ff51deb..96f04c51 100644 --- a/lib/libalpm/be_local.c +++ b/lib/libalpm/be_local.c @@ -321,6 +321,10 @@ static int local_db_validate(pmdb_t *db) DIR *dbdir; int ret = -1; + if(db->status & DB_STATUS_VALID) { + return 0; + } + dbpath = _alpm_db_path(db); if(dbpath == NULL) { RET_ERR(db->handle, PM_ERR_DB_OPEN, -1); @@ -329,6 +333,7 @@ static int local_db_validate(pmdb_t *db) if(dbdir == NULL) { if(errno == ENOENT) { /* database dir doesn't exist yet */ + db->status |= DB_STATUS_VALID; return 0; } else { RET_ERR(db->handle, PM_ERR_DB_OPEN, -1); @@ -354,6 +359,7 @@ static int local_db_validate(pmdb_t *db) } } /* we found no depends file after full scan */ + db->status |= DB_STATUS_VALID; ret = 0; done: diff --git a/lib/libalpm/be_sync.c b/lib/libalpm/be_sync.c index 1a434f24..c1703ffe 100644 --- a/lib/libalpm/be_sync.c +++ b/lib/libalpm/be_sync.c @@ -69,9 +69,15 @@ static char *get_sync_dir(pmhandle_t *handle) static int sync_db_validate(pmdb_t *db) { + pgp_verify_t check_sig; + + if(db->status & DB_STATUS_VALID) { + return 0; + } + /* this takes into account the default verification level if UNKNOWN * was assigned to this db */ - pgp_verify_t check_sig = _alpm_db_get_sigverify_level(db); + check_sig = _alpm_db_get_sigverify_level(db); if(check_sig != PM_PGP_VERIFY_NEVER) { int ret; @@ -83,6 +89,7 @@ static int sync_db_validate(pmdb_t *db) /* we can skip any validation if the database doesn't exist */ if(access(dbpath, R_OK) != 0 && errno == ENOENT) { + goto valid; return 0; } @@ -95,6 +102,8 @@ static int sync_db_validate(pmdb_t *db) } } +valid: + db->status |= DB_STATUS_VALID; return 0; } @@ -215,6 +224,7 @@ int SYMEXPORT alpm_db_update(int force, pmdb_t *db) /* Cache needs to be rebuilt */ _alpm_db_free_pkgcache(db); + db->status &= ~DB_STATUS_VALID; if(sync_db_validate(db)) { /* pm_errno should be set */ ret = -1; diff --git a/lib/libalpm/db.c b/lib/libalpm/db.c index 820261a1..b20421a3 100644 --- a/lib/libalpm/db.c +++ b/lib/libalpm/db.c @@ -468,11 +468,8 @@ alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles) /* Returns a new package cache from db. * It frees the cache if it already exists. */ -int _alpm_db_load_pkgcache(pmdb_t *db) +static int load_pkgcache(pmdb_t *db) { - if(db == NULL) { - return -1; - } _alpm_db_free_pkgcache(db); _alpm_log(db->handle, PM_LOG_DEBUG, "loading package cache for repository '%s'\n", @@ -483,23 +480,23 @@ int _alpm_db_load_pkgcache(pmdb_t *db) return -1; } - db->pkgcache_loaded = 1; + db->status |= DB_STATUS_PKGCACHE; return 0; } void _alpm_db_free_pkgcache(pmdb_t *db) { - if(db == NULL || !db->pkgcache_loaded) { + if(db == NULL || !(db->status & DB_STATUS_PKGCACHE)) { return; } - _alpm_log(db->handle, PM_LOG_DEBUG, "freeing package cache for repository '%s'\n", - db->treename); + _alpm_log(db->handle, PM_LOG_DEBUG, + "freeing package cache for repository '%s'\n", db->treename); alpm_list_free_inner(_alpm_db_get_pkgcache(db), (alpm_list_fn_free)_alpm_pkg_free); _alpm_pkghash_free(db->pkgcache); - db->pkgcache_loaded = 0; + db->status &= ~DB_STATUS_PKGCACHE; _alpm_db_free_grpcache(db); } @@ -510,8 +507,12 @@ pmpkghash_t *_alpm_db_get_pkgcache_hash(pmdb_t *db) return NULL; } - if(!db->pkgcache_loaded) { - _alpm_db_load_pkgcache(db); + if(!(db->status & DB_STATUS_VALID)) { + RET_ERR(db->handle, PM_ERR_DB_INVALID, NULL); + } + + if(!(db->status & DB_STATUS_PKGCACHE)) { + load_pkgcache(db); } return db->pkgcache; @@ -533,7 +534,7 @@ int _alpm_db_add_pkgincache(pmdb_t *db, pmpkg_t *pkg) { pmpkg_t *newpkg; - if(db == NULL || !db->pkgcache_loaded || pkg == NULL) { + if(db == NULL || pkg == NULL || !(db->status & DB_STATUS_PKGCACHE)) { return -1; } @@ -555,7 +556,7 @@ int _alpm_db_remove_pkgfromcache(pmdb_t *db, pmpkg_t *pkg) { pmpkg_t *data = NULL; - if(db == NULL || !db->pkgcache_loaded || pkg == NULL) { + if(db == NULL || pkg == NULL || !(db->status & DB_STATUS_PKGCACHE)) { return -1; } @@ -585,8 +586,6 @@ pmpkg_t *_alpm_db_get_pkgfromcache(pmdb_t *db, const char *target) pmpkghash_t *pkgcache = _alpm_db_get_pkgcache_hash(db); if(!pkgcache) { - _alpm_log(db->handle, PM_LOG_DEBUG, "warning: failed to get '%s' from NULL pkgcache\n", - target); return NULL; } @@ -595,7 +594,7 @@ pmpkg_t *_alpm_db_get_pkgfromcache(pmdb_t *db, const char *target) /* Returns a new group cache from db. */ -int _alpm_db_load_grpcache(pmdb_t *db) +static int load_grpcache(pmdb_t *db) { alpm_list_t *lp; @@ -641,7 +640,7 @@ int _alpm_db_load_grpcache(pmdb_t *db) } } - db->grpcache_loaded = 1; + db->status |= DB_STATUS_GRPCACHE; return 0; } @@ -649,19 +648,19 @@ void _alpm_db_free_grpcache(pmdb_t *db) { alpm_list_t *lg; - if(db == NULL || !db->grpcache_loaded) { + if(db == NULL || !(db->status & DB_STATUS_GRPCACHE)) { return; } - _alpm_log(db->handle, PM_LOG_DEBUG, "freeing group cache for repository '%s'\n", - db->treename); + _alpm_log(db->handle, PM_LOG_DEBUG, + "freeing group cache for repository '%s'\n", db->treename); for(lg = db->grpcache; lg; lg = lg->next) { _alpm_grp_free(lg->data); lg->data = NULL; } FREELIST(db->grpcache); - db->grpcache_loaded = 0; + db->status &= ~DB_STATUS_GRPCACHE; } alpm_list_t *_alpm_db_get_grpcache(pmdb_t *db) @@ -670,8 +669,12 @@ alpm_list_t *_alpm_db_get_grpcache(pmdb_t *db) return NULL; } - if(!db->grpcache_loaded) { - _alpm_db_load_grpcache(db); + if(!(db->status & DB_STATUS_VALID)) { + RET_ERR(db->handle, PM_ERR_DB_INVALID, NULL); + } + + if(!(db->status & DB_STATUS_GRPCACHE)) { + load_grpcache(db); } return db->grpcache; diff --git a/lib/libalpm/db.h b/lib/libalpm/db.h index 4541c258..03187342 100644 --- a/lib/libalpm/db.h +++ b/lib/libalpm/db.h @@ -43,6 +43,13 @@ typedef enum _pmdbinfrq_t { INFRQ_ALL = 0x1F } pmdbinfrq_t; +/** Database status. Bitflags. */ +enum _pmdbstatus_t { + DB_STATUS_VALID = (1 << 0), + DB_STATUS_PKGCACHE = (1 << 1), + DB_STATUS_GRPCACHE = (1 << 2) +}; + struct db_operations { int (*populate) (pmdb_t *); void (*unregister) (pmdb_t *); @@ -54,10 +61,10 @@ struct __pmdb_t { char *treename; /* do not access directly, use _alpm_db_path(db) for lazy access */ char *_path; - int pkgcache_loaded; - int grpcache_loaded; /* also indicates whether we are RO or RW */ int is_local; + /* flags determining validity, loaded caches, etc. */ + enum _pmdbstatus_t status; pmpkghash_t *pkgcache; alpm_list_t *grpcache; alpm_list_t *servers; @@ -72,7 +79,6 @@ pmdb_t *_alpm_db_new(const char *treename, int is_local); void _alpm_db_free(pmdb_t *db); const char *_alpm_db_path(pmdb_t *db); char *_alpm_db_sig_path(pmdb_t *db); -int _alpm_db_version(pmdb_t *db); int _alpm_db_cmp(const void *d1, const void *d2); alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles); pmdb_t *_alpm_db_register_local(pmhandle_t *handle); @@ -88,7 +94,6 @@ int _alpm_local_db_remove(pmdb_t *db, pmpkg_t *info); /* cache bullshit */ /* packages */ -int _alpm_db_load_pkgcache(pmdb_t *db); void _alpm_db_free_pkgcache(pmdb_t *db); int _alpm_db_add_pkgincache(pmdb_t *db, pmpkg_t *pkg); int _alpm_db_remove_pkgfromcache(pmdb_t *db, pmpkg_t *pkg); @@ -97,7 +102,6 @@ alpm_list_t *_alpm_db_get_pkgcache(pmdb_t *db); int _alpm_db_ensure_pkgcache(pmdb_t *db, pmdbinfrq_t infolevel); pmpkg_t *_alpm_db_get_pkgfromcache(pmdb_t *db, const char *target); /* groups */ -int _alpm_db_load_grpcache(pmdb_t *db); void _alpm_db_free_grpcache(pmdb_t *db); alpm_list_t *_alpm_db_get_grpcache(pmdb_t *db); pmgrp_t *_alpm_db_get_grpfromcache(pmdb_t *db, const char *target); diff --git a/lib/libalpm/error.c b/lib/libalpm/error.c index d893f866..1e4e705b 100644 --- a/lib/libalpm/error.c +++ b/lib/libalpm/error.c @@ -70,6 +70,8 @@ const char SYMEXPORT *alpm_strerror(enum _pmerrno_t err) return _("database already registered"); case PM_ERR_DB_NOT_FOUND: return _("could not find database"); + case PM_ERR_DB_INVALID: + return _("invalid or corrupted database"); case PM_ERR_DB_VERSION: return _("database is incorrect version"); case PM_ERR_DB_WRITE: diff --git a/lib/libalpm/trans.c b/lib/libalpm/trans.c index b4bdccfb..11a28e5c 100644 --- a/lib/libalpm/trans.c +++ b/lib/libalpm/trans.c @@ -101,11 +101,19 @@ int SYMEXPORT alpm_trans_init(pmhandle_t *handle, pmtransflag_t flags, alpm_trans_cb_progress progress) { pmtrans_t *trans; + alpm_list_t *i; /* Sanity checks */ CHECK_HANDLE(handle, return -1); ASSERT(handle->trans == NULL, RET_ERR(handle, PM_ERR_TRANS_NOT_NULL, -1)); + for(i = handle->dbs_sync; i; i = i->next) { + const pmdb_t *db = i->data; + if(!(db->status & DB_STATUS_VALID)) { + RET_ERR(handle, PM_ERR_DB_INVALID, -1); + } + } + /* lock db */ if(!(flags & PM_TRANS_FLAG_NOLOCK)) { if(make_lock(handle)) { diff --git a/src/pacman/conf.c b/src/pacman/conf.c index c5f78d40..076e854d 100644 --- a/src/pacman/conf.c +++ b/src/pacman/conf.c @@ -450,7 +450,7 @@ static int setup_libalpm(void) pm_printf(PM_LOG_ERROR, _("failed to initialize alpm library (%s)\n"), alpm_strerror(err)); if(err == PM_ERR_DB_VERSION) { - fprintf(stderr, _(" try running pacman-db-upgrade\n")); + pm_printf(PM_LOG_ERROR, _(" try running pacman-db-upgrade\n")); } return -1; } diff --git a/test/pacman/tests/ignore007.py b/test/pacman/tests/ignore007.py index 90ff4ef6..7670e770 100644 --- a/test/pacman/tests/ignore007.py +++ b/test/pacman/tests/ignore007.py @@ -18,4 +18,4 @@ self.args = "--ask=1 -S grp" self.addrule("PACMAN_RETCODE=0") self.addrule("!PKG_EXIST=%s" % pkg1.name) self.addrule("PKG_EXIST=%s" % pkg2.name) -self.addrule("PACMAN_OUTPUT=is in IgnorePkg") +self.addrule("PKG_EXIST=%s" % pkg3.name) -- cgit v1.2.3-70-g09d2 From 4f8ae2bab61c8fc678589c6840d44977c82d4cc2 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Fri, 24 Jun 2011 04:11:38 -0500 Subject: Don't require a transaction for sync DB updates Instead, just do the required locking directly in the backend in calls to alpm_db_update(). Signed-off-by: Dan McGee --- lib/libalpm/be_sync.c | 42 ++++++++++++++++++++++++------------------ src/pacman/sync.c | 7 ------- 2 files changed, 24 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/lib/libalpm/be_sync.c b/lib/libalpm/be_sync.c index c1703ffe..f51ab97a 100644 --- a/lib/libalpm/be_sync.c +++ b/lib/libalpm/be_sync.c @@ -113,26 +113,22 @@ valid: * \a force is true, the update will only be performed if the remote * database was modified since the last update. * - * A transaction is necessary for this operation, in order to obtain a - * database lock. During this transaction the front-end will be informed - * of the download progress of the database via the download callback. + * This operation requires a database lock, and will return an applicable error + * if the lock could not be obtained. * * Example: * @code * alpm_list_t *syncs = alpm_option_get_syncdbs(); - * if(alpm_trans_init(0, NULL, NULL, NULL) == 0) { - * for(i = syncs; i; i = alpm_list_next(i)) { - * pmdb_t *db = alpm_list_getdata(i); - * result = alpm_db_update(0, db); - * alpm_trans_release(); + * for(i = syncs; i; i = alpm_list_next(i)) { + * pmdb_t *db = alpm_list_getdata(i); + * result = alpm_db_update(0, db); * - * if(result < 0) { - * printf("Unable to update database: %s\n", alpm_strerrorlast()); - * } else if(result == 1) { - * printf("Database already up to date\n"); - * } else { - * printf("Database updated\n"); - * } + * if(result < 0) { + * printf("Unable to update database: %s\n", alpm_strerrorlast()); + * } else if(result == 1) { + * printf("Database already up to date\n"); + * } else { + * printf("Database updated\n"); * } * } * @endcode @@ -162,15 +158,21 @@ int SYMEXPORT alpm_db_update(int force, pmdb_t *db) ASSERT(db != handle->db_local, RET_ERR(handle, PM_ERR_WRONG_ARGS, -1)); ASSERT(db->servers != NULL, RET_ERR(handle, PM_ERR_SERVER_NONE, -1)); - /* make sure we have a sane umask */ - oldmask = umask(0022); - syncpath = get_sync_dir(handle); if(!syncpath) { return -1; } + + /* make sure we have a sane umask */ + oldmask = umask(0022); + check_sig = _alpm_db_get_sigverify_level(db); + /* attempt to grab a lock */ + if(_alpm_handle_lock(handle)) { + RET_ERR(handle, PM_ERR_HANDLE_LOCK, -1); + } + for(i = db->servers; i; i = i->next) { const char *server = i->data; char *fileurl; @@ -232,6 +234,10 @@ int SYMEXPORT alpm_db_update(int force, pmdb_t *db) cleanup: + if(_alpm_handle_unlock(handle)) { + _alpm_log(handle, PM_LOG_WARNING, _("could not remove lock file %s\n"), + alpm_option_get_lockfile(handle)); + } free(syncpath); umask(oldmask); return ret; diff --git a/src/pacman/sync.c b/src/pacman/sync.c index 6c86bd10..f242c827 100644 --- a/src/pacman/sync.c +++ b/src/pacman/sync.c @@ -283,10 +283,6 @@ static int sync_synctree(int level, alpm_list_t *syncs) alpm_list_t *i; int success = 0, ret; - if(trans_init(0) == -1) { - return 0; - } - for(i = syncs; i; i = alpm_list_next(i)) { pmdb_t *db = alpm_list_getdata(i); @@ -302,9 +298,6 @@ static int sync_synctree(int level, alpm_list_t *syncs) } } - if(trans_release() == -1) { - return 0; - } /* We should always succeed if at least one DB was upgraded - we may possibly * fail later with unresolved deps, but that should be rare, and would be * expected -- cgit v1.2.3-70-g09d2 From e06586ceb49a0dc7e59996ae3a1483337d2ada05 Mon Sep 17 00:00:00 2001 From: Dave Reisner Date: Tue, 21 Jun 2011 13:42:17 -0400 Subject: pactree: carry a list of databases for dep resolution Declare an alpm_list which, for now, only holds our local database. walk_deps and walk_reverse_deps are refactored to account for this, and a helper function is added to wrap alpm_db_get_pkg for traversing a list. This is groundwork for letting pactree walk the sync DBs. Signed-off-by: Dave Reisner Signed-off-by: Dan McGee --- src/util/pactree.c | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/util/pactree.c b/src/util/pactree.c index 6b29d935..87bac6d1 100644 --- a/src/util/pactree.c +++ b/src/util/pactree.c @@ -75,7 +75,6 @@ static struct color_choices no_color = { /* globals */ pmhandle_t *handle = NULL; -pmdb_t *db_local; alpm_list_t *walked = NULL; alpm_list_t *provisions = NULL; @@ -241,15 +240,27 @@ static void print_end(void) } } +static pmpkg_t *get_pkg_from_dbs(alpm_list_t *dbs, const char *needle) { + alpm_list_t *i; + pmpkg_t *ret; + + for(i = dbs; i; i = alpm_list_next(i)) { + ret = alpm_db_get_pkg(alpm_list_getdata(i), needle); + if(ret) { + return ret; + } + } + return NULL; +} /** * walk dependencies in reverse, showing packages which require the target */ -static void walk_reverse_deps(pmpkg_t *pkg, int depth) +static void walk_reverse_deps(alpm_list_t *dblist, pmpkg_t *pkg, int depth) { alpm_list_t *required_by, *i; - if((max_depth >= 0) && (depth == max_depth + 1)) { + if(!pkg || ((max_depth >= 0) && (depth == max_depth + 1))) { return; } @@ -267,7 +278,7 @@ static void walk_reverse_deps(pmpkg_t *pkg, int depth) } } else { print(alpm_pkg_get_name(pkg), pkgname, NULL, depth); - walk_reverse_deps(alpm_db_get_pkg(db_local, pkgname), depth + 1); + walk_reverse_deps(dblist, get_pkg_from_dbs(dblist, pkgname), depth + 1); } } @@ -277,7 +288,7 @@ static void walk_reverse_deps(pmpkg_t *pkg, int depth) /** * walk dependencies, showing dependencies of the target */ -static void walk_deps(pmpkg_t *pkg, int depth) +static void walk_deps(alpm_list_t *dblist, pmpkg_t *pkg, int depth) { alpm_list_t *i; @@ -289,8 +300,7 @@ static void walk_deps(pmpkg_t *pkg, int depth) for(i = alpm_pkg_get_depends(pkg); i; i = alpm_list_next(i)) { pmdepend_t *depend = alpm_list_getdata(i); - pmpkg_t *provider = alpm_find_satisfier(alpm_db_get_pkgcache(db_local), - depend->name); + pmpkg_t *provider = alpm_find_dbs_satisfier(handle, dblist, depend->name); if(provider) { const char *provname = alpm_pkg_get_name(provider); @@ -303,7 +313,7 @@ static void walk_deps(pmpkg_t *pkg, int depth) } } else { print(alpm_pkg_get_name(pkg), provname, depend->name, depth); - walk_deps(provider, depth + 1); + walk_deps(dblist, provider, depth + 1); } } else { /* unresolvable package */ @@ -318,6 +328,7 @@ int main(int argc, char *argv[]) enum _pmerrno_t err; const char *target_name; pmpkg_t *pkg; + alpm_list_t *dblist = NULL; if(parse_options(argc, argv) != 0) { usage(); @@ -333,12 +344,12 @@ int main(int argc, char *argv[]) goto finish; } - db_local = alpm_option_get_localdb(handle); + dblist = alpm_list_add(dblist, alpm_option_get_localdb(handle)); /* we only care about the first non option arg for walking */ target_name = argv[optind]; - pkg = alpm_find_satisfier(alpm_db_get_pkgcache(db_local), target_name); + pkg = alpm_find_dbs_satisfier(handle, dblist, target_name); if(!pkg) { fprintf(stderr, "error: package '%s' not found\n", target_name); ret = 1; @@ -348,13 +359,15 @@ int main(int argc, char *argv[]) print_start(alpm_pkg_get_name(pkg), target_name); if(reverse) { - walk_reverse_deps(pkg, 1); + walk_reverse_deps(dblist, pkg, 1); } else { - walk_deps(pkg, 1); + walk_deps(dblist, pkg, 1); } print_end(); + alpm_list_free(dblist); + finish: cleanup(); return ret; -- cgit v1.2.3-70-g09d2