From 0adceabe137fb4647f27916733124599b913a750 Mon Sep 17 00:00:00 2001 From: Aaron Griffin Date: Wed, 31 Jan 2007 06:48:06 +0000 Subject: Fix corrupt DB entry handling when loading package entries. * scan loops no longer abort on corrupt entries * reloading a cache package (and discovering it corrupt) no longer prints 2 messages and uses the pre-build "remove from package cache" function NOTE: The TODOs in there are important for later w.r.t. cleaning up corrupt DB entries but there are some logical complexities with doing so, so I'm holding off for now. --- lib/libalpm/be_files.c | 111 ++++++++++++++++++++++++++----------------------- lib/libalpm/cache.c | 5 +-- 2 files changed, 61 insertions(+), 55 deletions(-) diff --git a/lib/libalpm/be_files.c b/lib/libalpm/be_files.c index 5b54c79c..4de86523 100644 --- a/lib/libalpm/be_files.c +++ b/lib/libalpm/be_files.c @@ -114,7 +114,7 @@ pmpkg_t *_alpm_db_scan(pmdb_t *db, char *target, pmdbinfrq_t inforeq) char name[PKG_FULLNAME_LEN]; char *ptr = NULL; int found = 0; - pmpkg_t *pkg; + pmpkg_t *pkg = NULL; ALPM_LOG_FUNC; @@ -122,64 +122,71 @@ pmpkg_t *_alpm_db_scan(pmdb_t *db, char *target, pmdbinfrq_t inforeq) RET_ERR(PM_ERR_DB_NULL, NULL); } - if(target != NULL) { - /* search for a specific package (by name only) */ - rewinddir(db->handle); - while(!found && (ent = readdir(db->handle)) != NULL) { - if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) { - continue; - } - /* stat the entry, make sure it's a directory */ - snprintf(path, PATH_MAX, "%s/%s", db->path, ent->d_name); - if(stat(path, &sbuf) || !S_ISDIR(sbuf.st_mode)) { - continue; - } - STRNCPY(name, ent->d_name, PKG_FULLNAME_LEN); - /* truncate the string at the second-to-last hyphen, */ - /* which will give us the package name */ - if((ptr = rindex(name, '-'))) { - *ptr = '\0'; + /* We loop here until we read a valid package. When an iteration of this loop + * fails, it means alpm_db_read failed to read a valid package, so we'll read + * the next so as not to abort whole-db operations early + */ + while(!pkg) { + if(target != NULL) { + /* search for a specific package (by name only) */ + rewinddir(db->handle); + while(!found && (ent = readdir(db->handle)) != NULL) { + if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) { + continue; + } + /* stat the entry, make sure it's a directory */ + snprintf(path, PATH_MAX, "%s/%s", db->path, ent->d_name); + if(stat(path, &sbuf) || !S_ISDIR(sbuf.st_mode)) { + continue; + } + STRNCPY(name, ent->d_name, PKG_FULLNAME_LEN); + /* truncate the string at the second-to-last hyphen, */ + /* which will give us the package name */ + if((ptr = rindex(name, '-'))) { + *ptr = '\0'; + } + if((ptr = rindex(name, '-'))) { + *ptr = '\0'; + } + if(!strcmp(name, target)) { + found = 1; + } } - if((ptr = rindex(name, '-'))) { - *ptr = '\0'; + if(!found) { + return(NULL); } - if(!strcmp(name, target)) { - found = 1; + } else { + /* normal iteration */ + int isdir = 0; + while(!isdir) { + ent = readdir(db->handle); + if(ent == NULL) { + return(NULL); + } + if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) { + isdir = 0; + continue; + } + /* stat the entry, make sure it's a directory */ + snprintf(path, PATH_MAX, "%s/%s", db->path, ent->d_name); + if(!stat(path, &sbuf) && S_ISDIR(sbuf.st_mode)) { + isdir = 1; + } } } - if(!found) { + + pkg = _alpm_pkg_new(NULL, NULL); + if(pkg == NULL) { return(NULL); } - } else { - /* normal iteration */ - int isdir = 0; - while(!isdir) { - ent = readdir(db->handle); - if(ent == NULL) { - return(NULL); - } - if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) { - isdir = 0; - continue; - } - /* stat the entry, make sure it's a directory */ - snprintf(path, PATH_MAX, "%s/%s", db->path, ent->d_name); - if(!stat(path, &sbuf) && S_ISDIR(sbuf.st_mode)) { - isdir = 1; - } + if(_alpm_pkg_splitname(ent->d_name, pkg->name, pkg->version, 0) == -1) { + _alpm_log(PM_LOG_ERROR, _("invalid name for dabatase entry '%s'"), ent->d_name); + return(NULL); + } + if(_alpm_db_read(db, inforeq, pkg) == -1) { + /* TODO removed corrupt entry from the FS here */ + FREEPKG(pkg); } - } - - pkg = _alpm_pkg_new(NULL, NULL); - if(pkg == NULL) { - return(NULL); - } - if(_alpm_pkg_splitname(ent->d_name, pkg->name, pkg->version, 0) == -1) { - _alpm_log(PM_LOG_ERROR, _("invalid name for dabatase entry '%s'"), ent->d_name); - return(NULL); - } - if(_alpm_db_read(db, inforeq, pkg) == -1) { - FREEPKG(pkg); } return(pkg); diff --git a/lib/libalpm/cache.c b/lib/libalpm/cache.c index 41b23c36..e7c58a19 100644 --- a/lib/libalpm/cache.c +++ b/lib/libalpm/cache.c @@ -121,9 +121,8 @@ int _alpm_db_ensure_pkgcache(pmdb_t *db, pmdbinfrq_t infolevel) pmpkg_t *pkg = (pmpkg_t *)p->data; if(infolevel != INFRQ_NONE && !(pkg->infolevel & infolevel)) { if(_alpm_db_read(db, infolevel, pkg) == -1) { - _alpm_log(PM_LOG_ERROR, _("failed to read package '%s-%s', removing from package cache"), - pkg->name, pkg->version); - p = alpm_list_remove_node(p); + /* TODO should we actually remove from the filesystem here as well? */ + _alpm_db_remove_pkgfromcache(db, pkg); } else { reloaded = 1; } -- cgit v1.2.3-70-g09d2