index : pacman | |
Archlinux32 fork of pacman | gitolite user |
summaryrefslogtreecommitdiff |
-rw-r--r-- | lib/libalpm/be_local.c | 601 |
diff --git a/lib/libalpm/be_local.c b/lib/libalpm/be_local.c index d5edf34c..5d136c9e 100644 --- a/lib/libalpm/be_local.c +++ b/lib/libalpm/be_local.c @@ -1,5 +1,5 @@ /* - * be_local.c + * be_local.c : backend for the local database * * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> @@ -31,10 +31,6 @@ #include <time.h> #include <limits.h> /* PATH_MAX */ -/* libarchive */ -#include <archive.h> -#include <archive_entry.h> - /* libalpm */ #include "db.h" #include "alpm_list.h" @@ -43,18 +39,14 @@ #include "alpm.h" #include "handle.h" #include "package.h" -#include "group.h" #include "deps.h" -#include "dload.h" +static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq); #define LAZY_LOAD(info, errret) \ do { \ - ALPM_LOG_FUNC; \ - ASSERT(handle != NULL, return(errret)); \ - ASSERT(pkg != NULL, return(errret)); \ - if(pkg->origin != PKG_FROM_FILE && !(pkg->infolevel & info)) { \ - _alpm_local_db_read(pkg->origin_data.db, pkg, info); \ + if(!(pkg->infolevel & info)) { \ + local_db_read(pkg, info); \ } \ } while(0) @@ -65,173 +57,135 @@ * initialized. */ -static const char *_cache_get_filename(pmpkg_t *pkg) +static const char *_cache_get_filename(alpm_pkg_t *pkg) { LAZY_LOAD(INFRQ_DESC, NULL); return pkg->filename; } -static const char *_cache_get_name(pmpkg_t *pkg) -{ - ASSERT(pkg != NULL, return(NULL)); - return pkg->name; -} - -static const char *_cache_get_version(pmpkg_t *pkg) -{ - ASSERT(pkg != NULL, return(NULL)); - return pkg->version; -} - -static const char *_cache_get_desc(pmpkg_t *pkg) +static const char *_cache_get_desc(alpm_pkg_t *pkg) { LAZY_LOAD(INFRQ_DESC, NULL); return pkg->desc; } -static const char *_cache_get_url(pmpkg_t *pkg) +static const char *_cache_get_url(alpm_pkg_t *pkg) { LAZY_LOAD(INFRQ_DESC, NULL); return pkg->url; } -static time_t _cache_get_builddate(pmpkg_t *pkg) +static time_t _cache_get_builddate(alpm_pkg_t *pkg) { LAZY_LOAD(INFRQ_DESC, 0); return pkg->builddate; } -static time_t _cache_get_installdate(pmpkg_t *pkg) +static time_t _cache_get_installdate(alpm_pkg_t *pkg) { LAZY_LOAD(INFRQ_DESC, 0); return pkg->installdate; } -static const char *_cache_get_packager(pmpkg_t *pkg) +static const char *_cache_get_packager(alpm_pkg_t *pkg) { LAZY_LOAD(INFRQ_DESC, NULL); return pkg->packager; } -static const char *_cache_get_md5sum(pmpkg_t *pkg) +static const char *_cache_get_md5sum(alpm_pkg_t *pkg) { LAZY_LOAD(INFRQ_DESC, NULL); return pkg->md5sum; } -static const char *_cache_get_arch(pmpkg_t *pkg) +static const char *_cache_get_arch(alpm_pkg_t *pkg) { LAZY_LOAD(INFRQ_DESC, NULL); return pkg->arch; } -static off_t _cache_get_size(pmpkg_t *pkg) +static off_t _cache_get_size(alpm_pkg_t *pkg) { LAZY_LOAD(INFRQ_DESC, -1); return pkg->size; } -static off_t _cache_get_isize(pmpkg_t *pkg) +static off_t _cache_get_isize(alpm_pkg_t *pkg) { LAZY_LOAD(INFRQ_DESC, -1); return pkg->isize; } -static pmpkgreason_t _cache_get_reason(pmpkg_t *pkg) +static alpm_pkgreason_t _cache_get_reason(alpm_pkg_t *pkg) { LAZY_LOAD(INFRQ_DESC, -1); return pkg->reason; } -static alpm_list_t *_cache_get_licenses(pmpkg_t *pkg) +static alpm_list_t *_cache_get_licenses(alpm_pkg_t *pkg) { LAZY_LOAD(INFRQ_DESC, NULL); return pkg->licenses; } -static alpm_list_t *_cache_get_groups(pmpkg_t *pkg) +static alpm_list_t *_cache_get_groups(alpm_pkg_t *pkg) { LAZY_LOAD(INFRQ_DESC, NULL); return pkg->groups; } -static int _cache_has_scriptlet(pmpkg_t *pkg) +static int _cache_has_scriptlet(alpm_pkg_t *pkg) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(-1)); - ASSERT(pkg != NULL, return(-1)); - - if(!(pkg->infolevel & INFRQ_SCRIPTLET)) { - _alpm_local_db_read(pkg->origin_data.db, pkg, INFRQ_SCRIPTLET); - } + LAZY_LOAD(INFRQ_SCRIPTLET, NULL); return pkg->scriptlet; } -static alpm_list_t *_cache_get_depends(pmpkg_t *pkg) +static alpm_list_t *_cache_get_depends(alpm_pkg_t *pkg) { LAZY_LOAD(INFRQ_DESC, NULL); return pkg->depends; } -static alpm_list_t *_cache_get_optdepends(pmpkg_t *pkg) +static alpm_list_t *_cache_get_optdepends(alpm_pkg_t *pkg) { LAZY_LOAD(INFRQ_DESC, NULL); return pkg->optdepends; } -static alpm_list_t *_cache_get_conflicts(pmpkg_t *pkg) +static alpm_list_t *_cache_get_conflicts(alpm_pkg_t *pkg) { LAZY_LOAD(INFRQ_DESC, NULL); return pkg->conflicts; } -static alpm_list_t *_cache_get_provides(pmpkg_t *pkg) +static alpm_list_t *_cache_get_provides(alpm_pkg_t *pkg) { LAZY_LOAD(INFRQ_DESC, NULL); return pkg->provides; } -static alpm_list_t *_cache_get_replaces(pmpkg_t *pkg) +static alpm_list_t *_cache_get_replaces(alpm_pkg_t *pkg) { LAZY_LOAD(INFRQ_DESC, NULL); return pkg->replaces; } /* local packages can not have deltas */ -static alpm_list_t *_cache_get_deltas(pmpkg_t *pkg) +static alpm_list_t *_cache_get_deltas(alpm_pkg_t UNUSED *pkg) { return NULL; } -static alpm_list_t *_cache_get_files(pmpkg_t *pkg) +static alpm_filelist_t *_cache_get_files(alpm_pkg_t *pkg) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(pkg != NULL, return(NULL)); - - if(pkg->origin == PKG_FROM_LOCALDB - && !(pkg->infolevel & INFRQ_FILES)) { - _alpm_local_db_read(pkg->origin_data.db, pkg, INFRQ_FILES); - } - return pkg->files; + LAZY_LOAD(INFRQ_FILES, NULL); + return &(pkg->files); } -static alpm_list_t *_cache_get_backup(pmpkg_t *pkg) +static alpm_list_t *_cache_get_backup(alpm_pkg_t *pkg) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(pkg != NULL, return(NULL)); - - if(pkg->origin == PKG_FROM_LOCALDB - && !(pkg->infolevel & INFRQ_FILES)) { - _alpm_local_db_read(pkg->origin_data.db, pkg, INFRQ_FILES); - } + LAZY_LOAD(INFRQ_FILES, NULL); return pkg->backup; } @@ -241,17 +195,11 @@ static alpm_list_t *_cache_get_backup(pmpkg_t *pkg) * @param pkg the package (from db) to read the changelog * @return a 'file stream' to the package changelog */ -static void *_cache_changelog_open(pmpkg_t *pkg) +static void *_cache_changelog_open(alpm_pkg_t *pkg) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(pkg != NULL, return(NULL)); - char clfile[PATH_MAX]; snprintf(clfile, PATH_MAX, "%s/%s/%s-%s/changelog", - alpm_option_get_dbpath(), + alpm_option_get_dbpath(pkg->handle), alpm_db_get_name(alpm_pkg_get_db(pkg)), alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg)); @@ -268,18 +216,11 @@ static void *_cache_changelog_open(pmpkg_t *pkg) * @return the number of characters read, or 0 if there is no more data */ static size_t _cache_changelog_read(void *ptr, size_t size, - const pmpkg_t *pkg, const void *fp) + const alpm_pkg_t UNUSED *pkg, const void *fp) { - return ( fread(ptr, 1, size, (FILE*)fp) ); + return fread(ptr, 1, size, (FILE *)fp); } -/* -static int _cache_changelog_feof(const pmpkg_t *pkg, void *fp) -{ - return( feof((FILE*)fp) ); -} -*/ - /** * Close a package changelog for reading. Similar to fclose in functionality, * except that the 'file stream' is from the database. @@ -287,9 +228,14 @@ static int _cache_changelog_feof(const pmpkg_t *pkg, void *fp) * @param fp a 'file stream' to the package changelog * @return whether closing the package changelog stream was successful */ -static int _cache_changelog_close(const pmpkg_t *pkg, void *fp) +static int _cache_changelog_close(const alpm_pkg_t UNUSED *pkg, void *fp) { - return( fclose((FILE*)fp) ); + return fclose((FILE *)fp); +} + +static int _cache_force_load(alpm_pkg_t *pkg) +{ + return local_db_read(pkg, INFRQ_ALL); } @@ -299,8 +245,6 @@ static int _cache_changelog_close(const pmpkg_t *pkg, void *fp) */ static struct pkg_operations local_pkg_ops = { .get_filename = _cache_get_filename, - .get_name = _cache_get_name, - .get_version = _cache_get_version, .get_desc = _cache_get_desc, .get_url = _cache_get_url, .get_builddate = _cache_get_builddate, @@ -326,33 +270,35 @@ static struct pkg_operations local_pkg_ops = { .changelog_open = _cache_changelog_open, .changelog_read = _cache_changelog_read, .changelog_close = _cache_changelog_close, + + .force_load = _cache_force_load, }; -static int checkdbdir(pmdb_t *db) +static int checkdbdir(alpm_db_t *db) { struct stat buf; const char *path = _alpm_db_path(db); if(stat(path, &buf) != 0) { - _alpm_log(PM_LOG_DEBUG, "database dir '%s' does not exist, creating it\n", + _alpm_log(db->handle, ALPM_LOG_DEBUG, "database dir '%s' does not exist, creating it\n", path); if(_alpm_makepath(path) != 0) { - RET_ERR(PM_ERR_SYSTEM, -1); + RET_ERR(db->handle, ALPM_ERR_SYSTEM, -1); } } else if(!S_ISDIR(buf.st_mode)) { - _alpm_log(PM_LOG_WARNING, _("removing invalid database: %s\n"), path); + _alpm_log(db->handle, ALPM_LOG_WARNING, _("removing invalid database: %s\n"), path); if(unlink(path) != 0 || _alpm_makepath(path) != 0) { - RET_ERR(PM_ERR_SYSTEM, -1); + RET_ERR(db->handle, ALPM_ERR_SYSTEM, -1); } } - return(0); + return 0; } static int is_dir(const char *path, struct dirent *entry) { #ifdef HAVE_STRUCT_DIRENT_D_TYPE if(entry->d_type != DT_UNKNOWN) { - return(entry->d_type == DT_DIR); + return (entry->d_type == DT_DIR); } #endif { @@ -361,15 +307,71 @@ static int is_dir(const char *path, struct dirent *entry) snprintf(buffer, PATH_MAX, "%s/%s", path, entry->d_name); - if (!stat(buffer, &sbuf)) { - return(S_ISDIR(sbuf.st_mode)); + if(!stat(buffer, &sbuf)) { + return S_ISDIR(sbuf.st_mode); } } - return(0); + return 0; } -static int local_db_populate(pmdb_t *db) +static int local_db_validate(alpm_db_t *db) +{ + struct dirent *ent = NULL; + const char *dbpath; + 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, ALPM_ERR_DB_OPEN, -1); + } + dbdir = opendir(dbpath); + if(dbdir == NULL) { + if(errno == ENOENT) { + /* database dir doesn't exist yet */ + db->status |= DB_STATUS_VALID; + return 0; + } else { + RET_ERR(db->handle, ALPM_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 = ALPM_ERR_DB_VERSION; + goto done; + } + } + /* we found no depends file after full scan */ + db->status |= DB_STATUS_VALID; + ret = 0; + +done: + if(dbdir) { + closedir(dbdir); + } + + return ret; +} + +static int local_db_populate(alpm_db_t *db) { size_t est_count; int count = 0; @@ -378,25 +380,22 @@ static int local_db_populate(pmdb_t *db) const char *dbpath; DIR *dbdir; - ALPM_LOG_FUNC; - - ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); - dbpath = _alpm_db_path(db); if(dbpath == NULL) { /* pm_errno set in _alpm_db_path() */ return -1; } + dbdir = opendir(dbpath); if(dbdir == NULL) { if(errno == ENOENT) { /* no database existing yet is not an error */ - return(0); + return 0; } - RET_ERR(PM_ERR_DB_OPEN, -1); + RET_ERR(db->handle, ALPM_ERR_DB_OPEN, -1); } if(fstat(dirfd(dbdir), &buf) != 0) { - RET_ERR(PM_ERR_DB_OPEN, -1); + RET_ERR(db->handle, ALPM_ERR_DB_OPEN, -1); } if(buf.st_nlink >= 2) { est_count = buf.st_nlink; @@ -420,13 +419,13 @@ static int local_db_populate(pmdb_t *db) db->pkgcache = _alpm_pkghash_create(est_count * 2); if(db->pkgcache == NULL){ closedir(dbdir); - RET_ERR(PM_ERR_MEMORY, -1); + RET_ERR(db->handle, ALPM_ERR_MEMORY, -1); } while((ent = readdir(dbdir)) != NULL) { const char *name = ent->d_name; - pmpkg_t *pkg; + alpm_pkg_t *pkg; if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { continue; @@ -438,11 +437,12 @@ static int local_db_populate(pmdb_t *db) pkg = _alpm_pkg_new(); if(pkg == NULL) { closedir(dbdir); - RET_ERR(PM_ERR_MEMORY, -1); + RET_ERR(db->handle, ALPM_ERR_MEMORY, -1); } /* split the db entry name */ - if(_alpm_splitname(name, pkg) != 0) { - _alpm_log(PM_LOG_ERROR, _("invalid name for database entry '%s'\n"), + if(_alpm_splitname(name, &(pkg->name), &(pkg->version), + &(pkg->name_hash)) != 0) { + _alpm_log(db->handle, ALPM_LOG_ERROR, _("invalid name for database entry '%s'\n"), name); _alpm_pkg_free(pkg); continue; @@ -450,7 +450,7 @@ static int local_db_populate(pmdb_t *db) /* duplicated database entries are not allowed */ if(_alpm_pkghash_find(db->pkgcache, pkg->name)) { - _alpm_log(PM_LOG_ERROR, _("duplicated database entry '%s'\n"), pkg->name); + _alpm_log(db->handle, ALPM_LOG_ERROR, _("duplicated database entry '%s'\n"), pkg->name); _alpm_pkg_free(pkg); continue; } @@ -458,16 +458,17 @@ static int local_db_populate(pmdb_t *db) pkg->origin = PKG_FROM_LOCALDB; pkg->origin_data.db = db; pkg->ops = &local_pkg_ops; + pkg->handle = db->handle; /* explicitly read with only 'BASE' data, accessors will handle the rest */ - if(_alpm_local_db_read(db, pkg, INFRQ_BASE) == -1) { - _alpm_log(PM_LOG_ERROR, _("corrupted database entry '%s'\n"), name); + if(local_db_read(pkg, INFRQ_BASE) == -1) { + _alpm_log(db->handle, ALPM_LOG_ERROR, _("corrupted database entry '%s'\n"), name); _alpm_pkg_free(pkg); continue; } /* add to the collection */ - _alpm_log(PM_LOG_DEBUG, "adding '%s' to package cache for db '%s'\n", + _alpm_log(db->handle, ALPM_LOG_FUNCTION, "adding '%s' to package cache for db '%s'\n", pkg->name, db->treename); db->pkgcache = _alpm_pkghash_add(db->pkgcache, pkg); count++; @@ -477,11 +478,14 @@ static int local_db_populate(pmdb_t *db) if(count > 0) { db->pkgcache->list = alpm_list_msort(db->pkgcache->list, (size_t)count, _alpm_pkg_cmp); } - return(count); + _alpm_log(db->handle, ALPM_LOG_DEBUG, "added %d packages to package cache for db '%s'\n", + count, db->treename); + + return count; } /* Note: the return value must be freed by the caller */ -static char *get_pkgpath(pmdb_t *db, pmpkg_t *info) +static char *get_pkgpath(alpm_db_t *db, alpm_pkg_t *info) { size_t len; char *pkgpath; @@ -489,36 +493,36 @@ static char *get_pkgpath(pmdb_t *db, pmpkg_t *info) dbpath = _alpm_db_path(db); len = strlen(dbpath) + strlen(info->name) + strlen(info->version) + 3; - MALLOC(pkgpath, len, RET_ERR(PM_ERR_MEMORY, NULL)); + MALLOC(pkgpath, len, RET_ERR(db->handle, ALPM_ERR_MEMORY, NULL)); sprintf(pkgpath, "%s%s-%s/", dbpath, info->name, info->version); - return(pkgpath); + return pkgpath; } +#define READ_NEXT() do { \ + if(fgets(line, sizeof(line), fp) == NULL && !feof(fp)) goto error; \ + _alpm_strip_newline(line); \ +} while(0) + +#define READ_AND_STORE(f) do { \ + READ_NEXT(); \ + STRDUP(f, line, goto error); \ +} while(0) + +#define READ_AND_STORE_ALL(f) do { \ + char *linedup; \ + if(fgets(line, sizeof(line), fp) == NULL && !feof(fp)) goto error; \ + if(_alpm_strip_newline(line) == 0) break; \ + STRDUP(linedup, line, goto error); \ + f = alpm_list_add(f, linedup); \ +} while(1) /* note the while(1) and not (0) */ -int _alpm_local_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) +static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq) { FILE *fp = NULL; char path[PATH_MAX]; char line[1024]; char *pkgpath = NULL; - - ALPM_LOG_FUNC; - - if(db == NULL) { - RET_ERR(PM_ERR_DB_NULL, -1); - } - - if(info == NULL || info->name == NULL || info->version == NULL) { - _alpm_log(PM_LOG_DEBUG, "invalid package entry provided to _alpm_local_db_read, skipping\n"); - return(-1); - } - - if(info->origin != PKG_FROM_LOCALDB) { - _alpm_log(PM_LOG_DEBUG, - "request to read info for a non-local package '%s', skipping...\n", - info->name); - return(-1); - } + alpm_db_t *db = info->origin_data.db; /* bitmask logic here: * infolevel: 00001111 @@ -527,9 +531,16 @@ int _alpm_local_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) * == to inforeq? nope, we need to load more info. */ if((info->infolevel & inforeq) == inforeq) { /* already loaded all of this info, do nothing */ - return(0); + return 0; + } + + if(info->infolevel & INFRQ_ERROR) { + /* We've encountered an error loading this package before. Don't attempt + * repeated reloads, just give up. */ + return -1; } - _alpm_log(PM_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); /* clear out 'line', to be certain - and to make valgrind happy */ @@ -539,7 +550,7 @@ int _alpm_local_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) if(access(pkgpath, F_OK)) { /* directory doesn't exist or can't be opened */ - _alpm_log(PM_LOG_DEBUG, "cannot find '%s-%s' in db '%s'\n", + _alpm_log(db->handle, ALPM_LOG_DEBUG, "cannot find '%s-%s' in db '%s'\n", info->name, info->version, db->treename); goto error; } @@ -548,151 +559,129 @@ int _alpm_local_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) if(inforeq & INFRQ_DESC && !(info->infolevel & INFRQ_DESC)) { snprintf(path, PATH_MAX, "%sdesc", pkgpath); if((fp = fopen(path, "r")) == NULL) { - _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno)); + _alpm_log(db->handle, ALPM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno)); goto error; } while(!feof(fp)) { - if(fgets(line, sizeof(line), fp) == NULL) { - break; - } - _alpm_strtrim(line); + READ_NEXT(); if(strcmp(line, "%NAME%") == 0) { - if(fgets(line, sizeof(line), fp) == NULL) { - goto error; - } - if(strcmp(_alpm_strtrim(line), info->name) != 0) { - _alpm_log(PM_LOG_ERROR, _("%s database is inconsistent: name " + READ_NEXT(); + if(strcmp(line, info->name) != 0) { + _alpm_log(db->handle, ALPM_LOG_ERROR, _("%s database is inconsistent: name " "mismatch on package %s\n"), db->treename, info->name); } } else if(strcmp(line, "%VERSION%") == 0) { - if(fgets(line, sizeof(line), fp) == NULL) { - goto error; - } - if(strcmp(_alpm_strtrim(line), info->version) != 0) { - _alpm_log(PM_LOG_ERROR, _("%s database is inconsistent: version " + READ_NEXT(); + if(strcmp(line, info->version) != 0) { + _alpm_log(db->handle, ALPM_LOG_ERROR, _("%s database is inconsistent: version " "mismatch on package %s\n"), db->treename, info->name); } } else if(strcmp(line, "%DESC%") == 0) { - if(fgets(line, sizeof(line), fp) == NULL) { - goto error; - } - STRDUP(info->desc, _alpm_strtrim(line), goto error); + READ_AND_STORE(info->desc); } else if(strcmp(line, "%GROUPS%") == 0) { - while(fgets(line, sizeof(line), fp) && strlen(_alpm_strtrim(line))) { - char *linedup; - STRDUP(linedup, line, goto error); - info->groups = alpm_list_add(info->groups, linedup); - } + READ_AND_STORE_ALL(info->groups); } else if(strcmp(line, "%URL%") == 0) { - if(fgets(line, sizeof(line), fp) == NULL) { - goto error; - } - STRDUP(info->url, _alpm_strtrim(line), goto error); + READ_AND_STORE(info->url); } else if(strcmp(line, "%LICENSE%") == 0) { - while(fgets(line, sizeof(line), fp) && strlen(_alpm_strtrim(line))) { - char *linedup; - STRDUP(linedup, line, goto error); - info->licenses = alpm_list_add(info->licenses, linedup); - } + READ_AND_STORE_ALL(info->licenses); } else if(strcmp(line, "%ARCH%") == 0) { - if(fgets(line, sizeof(line), fp) == NULL) { - goto error; - } - STRDUP(info->arch, _alpm_strtrim(line), goto error); + READ_AND_STORE(info->arch); } else if(strcmp(line, "%BUILDDATE%") == 0) { - if(fgets(line, sizeof(line), fp) == NULL) { - goto error; - } - _alpm_strtrim(line); + READ_NEXT(); info->builddate = _alpm_parsedate(line); } else if(strcmp(line, "%INSTALLDATE%") == 0) { - if(fgets(line, sizeof(line), fp) == NULL) { - goto error; - } - _alpm_strtrim(line); + READ_NEXT(); info->installdate = _alpm_parsedate(line); } else if(strcmp(line, "%PACKAGER%") == 0) { - if(fgets(line, sizeof(line), fp) == NULL) { - goto error; - } - STRDUP(info->packager, _alpm_strtrim(line), goto error); + READ_AND_STORE(info->packager); } else if(strcmp(line, "%REASON%") == 0) { - if(fgets(line, sizeof(line), fp) == NULL) { - goto error; - } - info->reason = (pmpkgreason_t)atol(_alpm_strtrim(line)); + READ_NEXT(); + info->reason = (alpm_pkgreason_t)atol(line); } else if(strcmp(line, "%SIZE%") == 0) { /* NOTE: the CSIZE and SIZE fields both share the "size" field * in the pkginfo_t struct. This can be done b/c CSIZE * is currently only used in sync databases, and SIZE is * only used in local databases. */ - if(fgets(line, sizeof(line), fp) == NULL) { - goto error; - } - info->size = atol(_alpm_strtrim(line)); + READ_NEXT(); + info->size = atol(line); /* also store this value to isize */ info->isize = info->size; } else if(strcmp(line, "%REPLACES%") == 0) { - while(fgets(line, sizeof(line), fp) && strlen(_alpm_strtrim(line))) { - char *linedup; - STRDUP(linedup, line, goto error); - info->replaces = alpm_list_add(info->replaces, linedup); - } + READ_AND_STORE_ALL(info->replaces); } else if(strcmp(line, "%DEPENDS%") == 0) { - while(fgets(line, sizeof(line), fp) && strlen(_alpm_strtrim(line))) { - pmdepend_t *dep = _alpm_splitdep(line); - info->depends = alpm_list_add(info->depends, dep); + /* Different than the rest because of the _alpm_splitdep call. */ + while(1) { + READ_NEXT(); + if(strlen(line) == 0) break; + info->depends = alpm_list_add(info->depends, _alpm_splitdep(line)); } } else if(strcmp(line, "%OPTDEPENDS%") == 0) { - while(fgets(line, sizeof(line), fp) && strlen(_alpm_strtrim(line))) { - char *linedup; - STRDUP(linedup, line, goto error); - info->optdepends = alpm_list_add(info->optdepends, linedup); - } + READ_AND_STORE_ALL(info->optdepends); } else if(strcmp(line, "%CONFLICTS%") == 0) { - while(fgets(line, sizeof(line), fp) && strlen(_alpm_strtrim(line))) { - char *linedup; - STRDUP(linedup, line, goto error); - info->conflicts = alpm_list_add(info->conflicts, linedup); - } + READ_AND_STORE_ALL(info->conflicts); } else if(strcmp(line, "%PROVIDES%") == 0) { - while(fgets(line, sizeof(line), fp) && strlen(_alpm_strtrim(line))) { - char *linedup; - STRDUP(linedup, line, goto error); - info->provides = alpm_list_add(info->provides, linedup); - } + READ_AND_STORE_ALL(info->provides); } } fclose(fp); fp = NULL; + info->infolevel |= INFRQ_DESC; } /* FILES */ if(inforeq & INFRQ_FILES && !(info->infolevel & INFRQ_FILES)) { snprintf(path, PATH_MAX, "%sfiles", pkgpath); if((fp = fopen(path, "r")) == NULL) { - _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno)); + _alpm_log(db->handle, ALPM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno)); goto error; } while(fgets(line, sizeof(line), fp)) { - _alpm_strtrim(line); + _alpm_strip_newline(line); if(strcmp(line, "%FILES%") == 0) { - while(fgets(line, sizeof(line), fp) && strlen(_alpm_strtrim(line))) { - char *linedup; - STRDUP(linedup, line, goto error); - info->files = alpm_list_add(info->files, linedup); + size_t files_count = 0, files_size = 0; + alpm_file_t *files = NULL; + + while(fgets(line, sizeof(line), fp) && _alpm_strip_newline(line)) { + if(files_count >= files_size) { + size_t old_size = files_size; + if(files_size == 0) { + files_size = 8; + } else { + files_size *= 2; + } + files = realloc(files, sizeof(alpm_file_t) * files_size); + if(!files) { + ALLOC_FAIL(sizeof(alpm_file_t) * files_size); + goto error; + } + /* ensure all new memory is zeroed out, in both the initial + * allocation and later reallocs */ + 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 */ + files_count++; } + /* attempt to hand back any memory we don't need */ + files = realloc(files, sizeof(alpm_file_t) * files_count); + info->files.count = files_count; + info->files.files = files; } else if(strcmp(line, "%BACKUP%") == 0) { - while(fgets(line, sizeof(line), fp) && strlen(_alpm_strtrim(line))) { - char *linedup; - STRDUP(linedup, line, goto error); - info->backup = alpm_list_add(info->backup, linedup); + while(fgets(line, sizeof(line), fp) && _alpm_strip_newline(line)) { + alpm_backup_t *backup; + CALLOC(backup, 1, sizeof(alpm_backup_t), goto error); + if(_alpm_split_backup(line, &backup)) { + goto error; + } + info->backup = alpm_list_add(info->backup, backup); } } } fclose(fp); fp = NULL; + info->infolevel |= INFRQ_FILES; } /* INSTALL */ @@ -701,47 +690,46 @@ int _alpm_local_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) if(access(path, F_OK) == 0) { info->scriptlet = 1; } + info->infolevel |= INFRQ_SCRIPTLET; } - /* internal */ - info->infolevel |= inforeq; - free(pkgpath); - return(0); + return 0; error: + info->infolevel |= INFRQ_ERROR; free(pkgpath); if(fp) { fclose(fp); } - return(-1); + return -1; } -int _alpm_local_db_prepare(pmdb_t *db, pmpkg_t *info) +int _alpm_local_db_prepare(alpm_db_t *db, alpm_pkg_t *info) { mode_t oldmask; int retval = 0; char *pkgpath = NULL; if(checkdbdir(db) != 0) { - return(-1); + return -1; } oldmask = umask(0000); pkgpath = get_pkgpath(db, info); if((retval = mkdir(pkgpath, 0755)) != 0) { - _alpm_log(PM_LOG_ERROR, _("could not create directory %s: %s\n"), + _alpm_log(db->handle, ALPM_LOG_ERROR, _("could not create directory %s: %s\n"), pkgpath, strerror(errno)); } free(pkgpath); umask(oldmask); - return(retval); + return retval; } -int _alpm_local_db_write(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) +int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, alpm_dbinfrq_t inforeq) { FILE *fp = NULL; char path[PATH_MAX]; @@ -750,10 +738,8 @@ int _alpm_local_db_write(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) int retval = 0; char *pkgpath = NULL; - ALPM_LOG_FUNC; - if(db == NULL || info == NULL) { - return(-1); + return -1; } pkgpath = get_pkgpath(db, info); @@ -762,16 +748,17 @@ int _alpm_local_db_write(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) oldmask = umask(0022); if(strcmp(db->treename, "local") != 0) { - return(-1); + return -1; } /* DESC */ if(inforeq & INFRQ_DESC) { - _alpm_log(PM_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); snprintf(path, PATH_MAX, "%sdesc", pkgpath); if((fp = fopen(path, "w")) == NULL) { - _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno)); + _alpm_log(db->handle, ALPM_LOG_ERROR, _("could not open file %s: %s\n"), + path, strerror(errno)); retval = -1; goto cleanup; } @@ -868,25 +855,29 @@ int _alpm_local_db_write(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) /* FILES */ if(inforeq & INFRQ_FILES) { - _alpm_log(PM_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); snprintf(path, PATH_MAX, "%sfiles", pkgpath); if((fp = fopen(path, "w")) == NULL) { - _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno)); + _alpm_log(db->handle, ALPM_LOG_ERROR, _("could not open file %s: %s\n"), + path, strerror(errno)); retval = -1; goto cleanup; } - if(info->files) { + if(info->files.count) { + size_t i; fprintf(fp, "%%FILES%%\n"); - for(lp = info->files; lp; lp = lp->next) { - fprintf(fp, "%s\n", (char *)lp->data); + for(i = 0; i < info->files.count; i++) { + const alpm_file_t *file = info->files.files + i; + fprintf(fp, "%s\n", file->name); } fprintf(fp, "\n"); } if(info->backup) { fprintf(fp, "%%BACKUP%%\n"); for(lp = info->backup; lp; lp = lp->next) { - fprintf(fp, "%s\n", (char *)lp->data); + const alpm_backup_t *backup = lp->data; + fprintf(fp, "%s\t%s\n", backup->name, backup->hash); } fprintf(fp, "\n"); } @@ -905,20 +896,14 @@ cleanup: fclose(fp); } - return(retval); + return retval; } -int _alpm_local_db_remove(pmdb_t *db, pmpkg_t *info) +int _alpm_local_db_remove(alpm_db_t *db, alpm_pkg_t *info) { int ret = 0; char *pkgpath = NULL; - ALPM_LOG_FUNC; - - if(db == NULL || info == NULL) { - RET_ERR(PM_ERR_DB_NULL, -1); - } - pkgpath = get_pkgpath(db, info); ret = _alpm_rmrf(pkgpath); @@ -926,83 +911,37 @@ int _alpm_local_db_remove(pmdb_t *db, pmpkg_t *info) if(ret != 0) { ret = -1; } - 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(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(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(PM_LOG_DEBUG, "local database version %d\n", version); - return(version); + return ret; } struct db_operations local_db_ops = { + .validate = local_db_validate, .populate = local_db_populate, .unregister = _alpm_db_unregister, - .version = local_db_version, }; -pmdb_t *_alpm_db_register_local(void) +alpm_db_t *_alpm_db_register_local(alpm_handle_t *handle) { - pmdb_t *db; - - ALPM_LOG_FUNC; + alpm_db_t *db; - _alpm_log(PM_LOG_DEBUG, "registering local database\n"); + _alpm_log(handle, ALPM_LOG_DEBUG, "registering local database\n"); db = _alpm_db_new("local", 1); if(db == NULL) { - RET_ERR(PM_ERR_DB_CREATE, NULL); + handle->pm_errno = ALPM_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); + return db; } /* vim: set ts=2 sw=2 noet: */ |