Date: Wednesday, January 31, 2007 @ 01:48:06 Author: aaron Path: /home/cvs-pacman/pacman-lib/lib/libalpm Modified: be_files.c (1.24 -> 1.25) cache.c (1.29 -> 1.30) 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. ------------+ be_files.c | 111 +++++++++++++++++++++++++++++++---------------------------- cache.c | 5 +- 2 files changed, 61 insertions(+), 55 deletions(-) Index: pacman-lib/lib/libalpm/be_files.c diff -u pacman-lib/lib/libalpm/be_files.c:1.24 pacman-lib/lib/libalpm/be_files.c:1.25 --- pacman-lib/lib/libalpm/be_files.c:1.24 Wed Jan 31 01:10:21 2007 +++ pacman-lib/lib/libalpm/be_files.c Wed Jan 31 01:48:06 2007 @@ -114,7 +114,7 @@ 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 @@ 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); Index: pacman-lib/lib/libalpm/cache.c diff -u pacman-lib/lib/libalpm/cache.c:1.29 pacman-lib/lib/libalpm/cache.c:1.30 --- pacman-lib/lib/libalpm/cache.c:1.29 Tue Jan 30 03:14:10 2007 +++ pacman-lib/lib/libalpm/cache.c Wed Jan 31 01:48:06 2007 @@ -121,9 +121,8 @@ 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; }