diff options
Diffstat (limited to 'lib')
78 files changed, 6780 insertions, 4958 deletions
diff --git a/lib/libalpm/Makefile.am b/lib/libalpm/Makefile.am index 1bda5714..c863fa9b 100644 --- a/lib/libalpm/Makefile.am +++ b/lib/libalpm/Makefile.am @@ -35,13 +35,15 @@ libalpm_la_SOURCES = \ diskspace.h diskspace.c \ dload.h dload.c \ error.c \ - graph.h \ + graph.h graph.c \ group.h group.c \ handle.h handle.c \ log.h log.c \ package.h package.c \ pkghash.h pkghash.c \ + rawstr.c \ remove.h remove.c \ + signing.c signing.h \ sync.h sync.c \ trans.h trans.c \ util.h util.c \ @@ -52,7 +54,12 @@ libalpm_la_SOURCES += \ md5.h md5.c endif -libalpm_la_LDFLAGS = -no-undefined -version-info $(LIB_VERSION_INFO) +if HAVE_LIBGPGME +libalpm_la_SOURCES += \ + base64.h base64.c +endif + +libalpm_la_LDFLAGS = -no-undefined -version-info $(LIB_VERSION_INFO) @LIBCURL@ libalpm_la_LIBADD = $(LTLIBINTL) # vim:set ts=2 sw=2 noet: diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c index ad6ef17e..5e1bb8da 100644 --- a/lib/libalpm/add.c +++ b/lib/libalpm/add.c @@ -37,82 +37,76 @@ /* libalpm */ #include "add.h" +#include "alpm.h" #include "alpm_list.h" +#include "handle.h" #include "trans.h" #include "util.h" #include "log.h" #include "backup.h" #include "package.h" #include "db.h" -#include "conflict.h" -#include "deps.h" #include "remove.h" #include "handle.h" -/** Add a package to the transaction. - * @param pkg the package to add - * @return 0 on success, -1 on error (pm_errno is set accordingly) - */ -int SYMEXPORT alpm_add_pkg(pmpkg_t *pkg) +/** Add a package to the transaction. */ +int SYMEXPORT alpm_add_pkg(alpm_handle_t *handle, alpm_pkg_t *pkg) { const char *pkgname, *pkgver; - pmtrans_t *trans; - pmdb_t *db_local; - pmpkg_t *local; - - ALPM_LOG_FUNC; + alpm_trans_t *trans; + alpm_pkg_t *local; /* Sanity checks */ - ASSERT(pkg != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + CHECK_HANDLE(handle, return -1); + ASSERT(pkg != NULL, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1)); + ASSERT(handle == pkg->handle, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1)); trans = handle->trans; - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1)); - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - db_local = handle->db_local; + ASSERT(trans != NULL, RET_ERR(handle, ALPM_ERR_TRANS_NULL, -1)); + ASSERT(trans->state == STATE_INITIALIZED, + RET_ERR(handle, ALPM_ERR_TRANS_NOT_INITIALIZED, -1)); - pkgname = alpm_pkg_get_name(pkg); - pkgver = alpm_pkg_get_version(pkg); + pkgname = pkg->name; + pkgver = pkg->version; - _alpm_log(PM_LOG_DEBUG, "adding package '%s'\n", pkgname); + _alpm_log(handle, ALPM_LOG_DEBUG, "adding package '%s'\n", pkgname); if(_alpm_pkg_find(trans->add, pkgname)) { - RET_ERR(PM_ERR_TRANS_DUP_TARGET, -1); + RET_ERR(handle, ALPM_ERR_TRANS_DUP_TARGET, -1); } - local = _alpm_db_get_pkgfromcache(db_local, pkgname); + local = _alpm_db_get_pkgfromcache(handle->db_local, pkgname); if(local) { const char *localpkgname = alpm_pkg_get_name(local); const char *localpkgver = alpm_pkg_get_version(local); int cmp = _alpm_pkg_compare_versions(pkg, local); if(cmp == 0) { - if(trans->flags & PM_TRANS_FLAG_NEEDED) { + if(trans->flags & ALPM_TRANS_FLAG_NEEDED) { /* with the NEEDED flag, packages up to date are not reinstalled */ - _alpm_log(PM_LOG_WARNING, _("%s-%s is up to date -- skipping\n"), + _alpm_log(handle, ALPM_LOG_WARNING, _("%s-%s is up to date -- skipping\n"), localpkgname, localpkgver); - return(0); - } else if(!(trans->flags & PM_TRANS_FLAG_DOWNLOADONLY)) { - _alpm_log(PM_LOG_WARNING, _("%s-%s is up to date -- reinstalling\n"), + return 0; + } else if(!(trans->flags & ALPM_TRANS_FLAG_DOWNLOADONLY)) { + _alpm_log(handle, ALPM_LOG_WARNING, _("%s-%s is up to date -- reinstalling\n"), localpkgname, localpkgver); } } else if(cmp < 0) { /* local version is newer */ - _alpm_log(PM_LOG_WARNING, _("downgrading package %s (%s => %s)\n"), + _alpm_log(handle, ALPM_LOG_WARNING, _("downgrading package %s (%s => %s)\n"), localpkgname, localpkgver, pkgver); } } /* add the package to the transaction */ - pkg->reason = PM_PKG_REASON_EXPLICIT; - _alpm_log(PM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n", + pkg->reason = ALPM_PKG_REASON_EXPLICIT; + _alpm_log(handle, ALPM_LOG_DEBUG, "adding package %s-%s to the transaction add list\n", pkgname, pkgver); trans->add = alpm_list_add(trans->add, pkg); - return(0); + return 0; } -static int perform_extraction(struct archive *archive, +static int perform_extraction(alpm_handle_t *handle, struct archive *archive, struct archive_entry *entry, const char *filename, const char *origname) { int ret; @@ -125,27 +119,26 @@ static int perform_extraction(struct archive *archive, ret = archive_read_extract(archive, entry, archive_flags); if(ret == ARCHIVE_WARN && archive_errno(archive) != ENOSPC) { /* operation succeeded but a "non-critical" error was encountered */ - _alpm_log(PM_LOG_WARNING, _("warning given when extracting %s (%s)\n"), + _alpm_log(handle, ALPM_LOG_WARNING, _("warning given when extracting %s (%s)\n"), origname, archive_error_string(archive)); } else if(ret != ARCHIVE_OK) { - _alpm_log(PM_LOG_ERROR, _("could not extract %s (%s)\n"), + _alpm_log(handle, ALPM_LOG_ERROR, _("could not extract %s (%s)\n"), origname, archive_error_string(archive)); - alpm_logaction("error: could not extract %s (%s)\n", + alpm_logaction(handle, "error: could not extract %s (%s)\n", origname, archive_error_string(archive)); - return(1); + return 1; } - return(0); + return 0; } -static int extract_single_file(struct archive *archive, - struct archive_entry *entry, pmpkg_t *newpkg, pmpkg_t *oldpkg, - pmtrans_t *trans, pmdb_t *db) +static int extract_single_file(alpm_handle_t *handle, struct archive *archive, + struct archive_entry *entry, alpm_pkg_t *newpkg, alpm_pkg_t *oldpkg) { const char *entryname; mode_t entrymode; char filename[PATH_MAX]; /* the actual file we're extracting */ int needbackup = 0, notouch = 0; - char *hash_orig = NULL; + const char *hash_orig = NULL; char *entryname_orig = NULL; int errors = 0; @@ -157,19 +150,19 @@ static int extract_single_file(struct archive *archive, if(strcmp(entryname, ".INSTALL") == 0) { /* the install script goes inside the db */ snprintf(filename, PATH_MAX, "%s%s-%s/install", - _alpm_db_path(db), newpkg->name, newpkg->version); + _alpm_db_path(handle->db_local), newpkg->name, newpkg->version); archive_entry_set_perm(entry, 0644); } else if(strcmp(entryname, ".CHANGELOG") == 0) { /* the changelog goes inside the db */ snprintf(filename, PATH_MAX, "%s%s-%s/changelog", - _alpm_db_path(db), newpkg->name, newpkg->version); + _alpm_db_path(handle->db_local), newpkg->name, newpkg->version); archive_entry_set_perm(entry, 0644); } else if(*entryname == '.') { /* for now, ignore all files starting with '.' that haven't * already been handled (for future possibilities) */ - _alpm_log(PM_LOG_DEBUG, "skipping extraction of '%s'\n", entryname); + _alpm_log(handle, ALPM_LOG_DEBUG, "skipping extraction of '%s'\n", entryname); archive_read_data_skip(archive); - return(0); + return 0; } else { /* build the new entryname relative to handle->root */ snprintf(filename, PATH_MAX, "%s%s", handle->root, entryname); @@ -177,12 +170,12 @@ static int extract_single_file(struct archive *archive, /* if a file is in NoExtract then we never extract it */ if(alpm_list_find_str(handle->noextract, entryname)) { - _alpm_log(PM_LOG_DEBUG, "%s is in NoExtract, skipping extraction\n", + _alpm_log(handle, ALPM_LOG_DEBUG, "%s is in NoExtract, skipping extraction\n", entryname); - alpm_logaction("note: %s is in NoExtract, skipping extraction\n", + alpm_logaction(handle, "note: %s is in NoExtract, skipping extraction\n", entryname); archive_read_data_skip(archive); - return(0); + return 0; } /* Check for file existence. This is one of the more crucial parts @@ -216,42 +209,42 @@ static int extract_single_file(struct archive *archive, if(lsbuf.st_mode != entrymode) { /* if filesystem perms are different than pkg perms, warn user */ mode_t mask = 07777; - _alpm_log(PM_LOG_WARNING, _("directory permissions differ on %s\n" + _alpm_log(handle, ALPM_LOG_WARNING, _("directory permissions differ on %s\n" "filesystem: %o package: %o\n"), entryname, lsbuf.st_mode & mask, entrymode & mask); - alpm_logaction("warning: directory permissions differ on %s\n" + alpm_logaction(handle, "warning: directory permissions differ on %s\n" "filesystem: %o package: %o\n", entryname, lsbuf.st_mode & mask, entrymode & mask); } - _alpm_log(PM_LOG_DEBUG, "extract: skipping dir extraction of %s\n", + _alpm_log(handle, ALPM_LOG_DEBUG, "extract: skipping dir extraction of %s\n", entryname); archive_read_data_skip(archive); - return(0); + return 0; } else { /* case 10/11: trying to overwrite dir with file/symlink, don't allow it */ - _alpm_log(PM_LOG_ERROR, _("extract: not overwriting dir with file %s\n"), + _alpm_log(handle, ALPM_LOG_ERROR, _("extract: not overwriting dir with file %s\n"), entryname); archive_read_data_skip(archive); - return(1); + return 1; } } else if(S_ISLNK(lsbuf.st_mode) && S_ISDIR(entrymode)) { /* case 9: existing symlink, dir in package */ if(S_ISDIR(sbuf.st_mode)) { /* the symlink on FS is to a directory, so we'll use it */ - _alpm_log(PM_LOG_DEBUG, "extract: skipping symlink overwrite of %s\n", + _alpm_log(handle, ALPM_LOG_DEBUG, "extract: skipping symlink overwrite of %s\n", entryname); archive_read_data_skip(archive); - return(0); + return 0; } else { /* this is BAD. symlink was not to a directory */ - _alpm_log(PM_LOG_ERROR, _("extract: symlink %s does not point to dir\n"), + _alpm_log(handle, ALPM_LOG_ERROR, _("extract: symlink %s does not point to dir\n"), entryname); archive_read_data_skip(archive); - return(1); + return 1; } } else if(S_ISREG(lsbuf.st_mode) && S_ISDIR(entrymode)) { /* case 6: trying to overwrite file with dir */ - _alpm_log(PM_LOG_DEBUG, "extract: overwriting file with dir %s\n", + _alpm_log(handle, ALPM_LOG_DEBUG, "extract: overwriting file with dir %s\n", entryname); } else if(S_ISREG(entrymode)) { /* case 4,7: */ @@ -259,24 +252,24 @@ static int extract_single_file(struct archive *archive, if(alpm_list_find_str(handle->noupgrade, entryname)) { notouch = 1; } else { + alpm_backup_t *backup; /* go to the backup array and see if our conflict is there */ /* check newpkg first, so that adding backup files is retroactive */ - if(alpm_list_find_str(alpm_pkg_get_backup(newpkg), entryname) != NULL) { + backup = _alpm_needbackup(entryname, newpkg); + if(backup) { + /* if we force hash_orig to be non-NULL retroactive backup works */ + hash_orig = ""; needbackup = 1; } /* check oldpkg for a backup entry, store the hash if available */ if(oldpkg) { - hash_orig = _alpm_needbackup(entryname, alpm_pkg_get_backup(oldpkg)); - if(hash_orig) { + backup = _alpm_needbackup(entryname, oldpkg); + if(backup) { + hash_orig = backup->hash; needbackup = 1; } } - - /* if we force hash_orig to be non-NULL retroactive backup works */ - if(needbackup && !hash_orig) { - STRDUP(hash_orig, "", RET_ERR(PM_ERR_MEMORY, -1)); - } } } /* else if(S_ISLNK(entrymode)) */ @@ -285,7 +278,7 @@ static int extract_single_file(struct archive *archive, /* we need access to the original entryname later after calls to * archive_entry_set_pathname(), so we need to dupe it and free() later */ - STRDUP(entryname_orig, entryname, RET_ERR(PM_ERR_MEMORY, -1)); + STRDUP(entryname_orig, entryname, RET_ERR(handle, ALPM_ERR_MEMORY, -1)); if(needbackup) { char checkfile[PATH_MAX]; @@ -294,44 +287,36 @@ static int extract_single_file(struct archive *archive, snprintf(checkfile, PATH_MAX, "%s.paccheck", filename); - ret = perform_extraction(archive, entry, checkfile, entryname_orig); + ret = perform_extraction(handle, archive, entry, checkfile, entryname_orig); if(ret == 1) { /* error */ - FREE(hash_orig); FREE(entryname_orig); - return(1); + return 1; } hash_local = alpm_compute_md5sum(filename); hash_pkg = alpm_compute_md5sum(checkfile); - /* append the new md5 hash to it's respective entry - * in newpkg's backup (it will be the new orginal) */ - alpm_list_t *backups; - for(backups = alpm_pkg_get_backup(newpkg); backups; - backups = alpm_list_next(backups)) { - char *oldbackup = alpm_list_getdata(backups); - if(!oldbackup || strcmp(oldbackup, entryname_orig) != 0) { + /* update the md5 hash in newpkg's backup (it will be the new orginal) */ + alpm_list_t *i; + for(i = alpm_pkg_get_backup(newpkg); i; i = i->next) { + alpm_backup_t *backup = i->data; + char *newhash; + if(!backup->name || strcmp(backup->name, entryname_orig) != 0) { continue; } - char *backup = NULL; - /* length is tab char, null byte and MD5 (32 char) */ - size_t backup_len = strlen(oldbackup) + 34; - MALLOC(backup, backup_len, RET_ERR(PM_ERR_MEMORY, -1)); - - sprintf(backup, "%s\t%s", oldbackup, hash_pkg); - backup[backup_len-1] = '\0'; - FREE(oldbackup); - backups->data = backup; + STRDUP(newhash, hash_pkg, RET_ERR(handle, ALPM_ERR_MEMORY, -1)); + FREE(backup->hash); + backup->hash = newhash; } - _alpm_log(PM_LOG_DEBUG, "checking hashes for %s\n", entryname_orig); - _alpm_log(PM_LOG_DEBUG, "current: %s\n", hash_local); - _alpm_log(PM_LOG_DEBUG, "new: %s\n", hash_pkg); - _alpm_log(PM_LOG_DEBUG, "original: %s\n", hash_orig); + _alpm_log(handle, ALPM_LOG_DEBUG, "checking hashes for %s\n", entryname_orig); + _alpm_log(handle, ALPM_LOG_DEBUG, "current: %s\n", hash_local); + _alpm_log(handle, ALPM_LOG_DEBUG, "new: %s\n", hash_pkg); + _alpm_log(handle, ALPM_LOG_DEBUG, "original: %s\n", hash_orig); if(!oldpkg) { - if(strcmp(hash_local, hash_pkg) != 0) { + if(hash_local && hash_pkg && strcmp(hash_local, hash_pkg) != 0) { /* looks like we have a local file that has a different hash as the * file in the package, move it to a .pacorig */ char newpath[PATH_MAX]; @@ -339,22 +324,22 @@ static int extract_single_file(struct archive *archive, /* move the existing file to the "pacorig" */ if(rename(filename, newpath)) { - _alpm_log(PM_LOG_ERROR, _("could not rename %s to %s (%s)\n"), + _alpm_log(handle, ALPM_LOG_ERROR, _("could not rename %s to %s (%s)\n"), filename, newpath, strerror(errno)); - alpm_logaction("error: could not rename %s to %s (%s)\n", + alpm_logaction(handle, "error: could not rename %s to %s (%s)\n", filename, newpath, strerror(errno)); errors++; } else { /* rename the file we extracted to the real name */ if(rename(checkfile, filename)) { - _alpm_log(PM_LOG_ERROR, _("could not rename %s to %s (%s)\n"), + _alpm_log(handle, ALPM_LOG_ERROR, _("could not rename %s to %s (%s)\n"), checkfile, filename, strerror(errno)); - alpm_logaction("error: could not rename %s to %s (%s)\n", + alpm_logaction(handle, "error: could not rename %s to %s (%s)\n", checkfile, filename, strerror(errno)); errors++; } else { - _alpm_log(PM_LOG_WARNING, _("%s saved as %s\n"), filename, newpath); - alpm_logaction("warning: %s saved as %s\n", filename, newpath); + _alpm_log(handle, ALPM_LOG_WARNING, _("%s saved as %s\n"), filename, newpath); + alpm_logaction(handle, "warning: %s saved as %s\n", filename, newpath); } } } else { @@ -364,51 +349,51 @@ static int extract_single_file(struct archive *archive, } else if(hash_orig) { /* the fun part */ - if(strcmp(hash_orig, hash_local) == 0) { + if(hash_local && strcmp(hash_orig, hash_local) == 0) { /* installed file has NOT been changed by user */ - if(strcmp(hash_orig, hash_pkg) != 0) { - _alpm_log(PM_LOG_DEBUG, "action: installing new file: %s\n", + if(hash_pkg && strcmp(hash_orig, hash_pkg) != 0) { + _alpm_log(handle, ALPM_LOG_DEBUG, "action: installing new file: %s\n", entryname_orig); if(rename(checkfile, filename)) { - _alpm_log(PM_LOG_ERROR, _("could not rename %s to %s (%s)\n"), + _alpm_log(handle, ALPM_LOG_ERROR, _("could not rename %s to %s (%s)\n"), checkfile, filename, strerror(errno)); - alpm_logaction("error: could not rename %s to %s (%s)\n", + alpm_logaction(handle, "error: could not rename %s to %s (%s)\n", checkfile, filename, strerror(errno)); errors++; } } else { - /* there's no sense in installing the same file twice, install - * ONLY is the original and package hashes differ */ - _alpm_log(PM_LOG_DEBUG, "action: leaving existing file in place\n"); + /* no sense in installing the same file twice, install + * ONLY if the original and package hashes differ */ + _alpm_log(handle, ALPM_LOG_DEBUG, "action: leaving existing file in place\n"); unlink(checkfile); } - } else if(strcmp(hash_orig, hash_pkg) == 0) { + } else if(hash_pkg && strcmp(hash_orig, hash_pkg) == 0) { /* originally installed file and new file are the same - this * implies the case above failed - i.e. the file was changed by a * user */ - _alpm_log(PM_LOG_DEBUG, "action: leaving existing file in place\n"); + _alpm_log(handle, ALPM_LOG_DEBUG, "action: leaving existing file in place\n"); unlink(checkfile); - } else if(strcmp(hash_local, hash_pkg) == 0) { + } else if(hash_local && hash_pkg && strcmp(hash_local, hash_pkg) == 0) { /* this would be magical. The above two cases failed, but the * user changes just so happened to make the new file exactly the * same as the one in the package... skip it */ - _alpm_log(PM_LOG_DEBUG, "action: leaving existing file in place\n"); + _alpm_log(handle, ALPM_LOG_DEBUG, "action: leaving existing file in place\n"); unlink(checkfile); } else { char newpath[PATH_MAX]; - _alpm_log(PM_LOG_DEBUG, "action: keeping current file and installing" + _alpm_log(handle, ALPM_LOG_DEBUG, "action: keeping current file and installing" " new one with .pacnew ending\n"); snprintf(newpath, PATH_MAX, "%s.pacnew", filename); if(rename(checkfile, newpath)) { - _alpm_log(PM_LOG_ERROR, _("could not install %s as %s (%s)\n"), + _alpm_log(handle, ALPM_LOG_ERROR, _("could not install %s as %s (%s)\n"), filename, newpath, strerror(errno)); - alpm_logaction("error: could not install %s as %s (%s)\n", + alpm_logaction(handle, "error: could not install %s as %s (%s)\n", filename, newpath, strerror(errno)); } else { - _alpm_log(PM_LOG_WARNING, _("%s installed as %s\n"), + _alpm_log(handle, ALPM_LOG_WARNING, _("%s installed as %s\n"), filename, newpath); - alpm_logaction("warning: %s installed as %s\n", + alpm_logaction(handle, "warning: %s installed as %s\n", filename, newpath); } } @@ -416,126 +401,113 @@ static int extract_single_file(struct archive *archive, FREE(hash_local); FREE(hash_pkg); - FREE(hash_orig); } else { int ret; /* we didn't need a backup */ if(notouch) { /* change the path to a .pacnew extension */ - _alpm_log(PM_LOG_DEBUG, "%s is in NoUpgrade -- skipping\n", filename); - _alpm_log(PM_LOG_WARNING, _("extracting %s as %s.pacnew\n"), filename, filename); - alpm_logaction("warning: extracting %s as %s.pacnew\n", filename, filename); + _alpm_log(handle, ALPM_LOG_DEBUG, "%s is in NoUpgrade -- skipping\n", filename); + _alpm_log(handle, ALPM_LOG_WARNING, _("extracting %s as %s.pacnew\n"), filename, filename); + alpm_logaction(handle, "warning: extracting %s as %s.pacnew\n", filename, filename); strncat(filename, ".pacnew", PATH_MAX - strlen(filename)); } else { - _alpm_log(PM_LOG_DEBUG, "extracting %s\n", filename); + _alpm_log(handle, ALPM_LOG_DEBUG, "extracting %s\n", filename); } - if(trans->flags & PM_TRANS_FLAG_FORCE) { + if(handle->trans->flags & ALPM_TRANS_FLAG_FORCE) { /* if FORCE was used, unlink() each file (whether it's there * or not) before extracting. This prevents the old "Text file busy" * error that crops up if forcing a glibc or pacman upgrade. */ unlink(filename); } - ret = perform_extraction(archive, entry, filename, entryname_orig); + ret = perform_extraction(handle, archive, entry, filename, entryname_orig); if(ret == 1) { /* error */ FREE(entryname_orig); - return(1); + return 1; } /* calculate an hash if this is in newpkg's backup */ - alpm_list_t *b; - for(b = alpm_pkg_get_backup(newpkg); b; b = b->next) { - char *backup = NULL, *hash = NULL; - char *oldbackup = alpm_list_getdata(b); - /* length is tab char, null byte and MD5 (32 char) */ - size_t backup_len = strlen(oldbackup) + 34; - - if(!oldbackup || strcmp(oldbackup, entryname_orig) != 0) { + alpm_list_t *i; + for(i = alpm_pkg_get_backup(newpkg); i; i = i->next) { + alpm_backup_t *backup = i->data; + char *newhash; + if(!backup->name || strcmp(backup->name, entryname_orig) != 0) { continue; } - _alpm_log(PM_LOG_DEBUG, "appending backup entry for %s\n", filename); - - hash = alpm_compute_md5sum(filename); - MALLOC(backup, backup_len, RET_ERR(PM_ERR_MEMORY, -1)); - - sprintf(backup, "%s\t%s", oldbackup, hash); - backup[backup_len-1] = '\0'; - FREE(hash); - FREE(oldbackup); - b->data = backup; + _alpm_log(handle, ALPM_LOG_DEBUG, "appending backup entry for %s\n", entryname_orig); + newhash = alpm_compute_md5sum(filename); + FREE(backup->hash); + backup->hash = newhash; } } FREE(entryname_orig); - return(errors); + return errors; } -static int commit_single_pkg(pmpkg_t *newpkg, size_t pkg_current, - size_t pkg_count, pmtrans_t *trans, pmdb_t *db) +static int commit_single_pkg(alpm_handle_t *handle, alpm_pkg_t *newpkg, + size_t pkg_current, size_t pkg_count) { int i, ret = 0, errors = 0; - char scriptlet[PATH_MAX+1]; + char scriptlet[PATH_MAX]; int is_upgrade = 0; - pmpkg_t *oldpkg = NULL; - - ALPM_LOG_FUNC; + alpm_pkg_t *oldpkg = NULL; + alpm_db_t *db = handle->db_local; + alpm_trans_t *trans = handle->trans; - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); + ASSERT(trans != NULL, return -1); snprintf(scriptlet, PATH_MAX, "%s%s-%s/install", _alpm_db_path(db), alpm_pkg_get_name(newpkg), alpm_pkg_get_version(newpkg)); /* see if this is an upgrade. if so, remove the old package first */ - pmpkg_t *local = _alpm_db_get_pkgfromcache(db, newpkg->name); + alpm_pkg_t *local = _alpm_db_get_pkgfromcache(db, newpkg->name); if(local) { is_upgrade = 1; /* we'll need to save some record for backup checks later */ oldpkg = _alpm_pkg_dup(local); - /* make sure all infos are loaded because the database entry - * will be removed soon */ - _alpm_local_db_read(oldpkg->origin_data.db, oldpkg, INFRQ_ALL); - EVENT(trans, PM_TRANS_EVT_UPGRADE_START, newpkg, oldpkg); - _alpm_log(PM_LOG_DEBUG, "upgrading package %s-%s\n", + EVENT(trans, ALPM_TRANS_EVT_UPGRADE_START, newpkg, oldpkg); + _alpm_log(handle, ALPM_LOG_DEBUG, "upgrading package %s-%s\n", newpkg->name, newpkg->version); /* copy over the install reason */ newpkg->reason = alpm_pkg_get_reason(oldpkg); /* pre_upgrade scriptlet */ - if(alpm_pkg_has_scriptlet(newpkg) && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) { - _alpm_runscriptlet(handle->root, newpkg->origin_data.file, - "pre_upgrade", newpkg->version, oldpkg->version, trans); + if(alpm_pkg_has_scriptlet(newpkg) && !(trans->flags & ALPM_TRANS_FLAG_NOSCRIPTLET)) { + _alpm_runscriptlet(handle, newpkg->origin_data.file, + "pre_upgrade", newpkg->version, oldpkg->version); } } else { is_upgrade = 0; - EVENT(trans, PM_TRANS_EVT_ADD_START, newpkg, NULL); - _alpm_log(PM_LOG_DEBUG, "adding package %s-%s\n", + EVENT(trans, ALPM_TRANS_EVT_ADD_START, newpkg, NULL); + _alpm_log(handle, ALPM_LOG_DEBUG, "adding package %s-%s\n", newpkg->name, newpkg->version); /* pre_install scriptlet */ - if(alpm_pkg_has_scriptlet(newpkg) && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) { - _alpm_runscriptlet(handle->root, newpkg->origin_data.file, - "pre_install", newpkg->version, NULL, trans); + if(alpm_pkg_has_scriptlet(newpkg) && !(trans->flags & ALPM_TRANS_FLAG_NOSCRIPTLET)) { + _alpm_runscriptlet(handle, newpkg->origin_data.file, + "pre_install", newpkg->version, NULL); } } /* we override any pre-set reason if we have alldeps or allexplicit set */ - if(trans->flags & PM_TRANS_FLAG_ALLDEPS) { - newpkg->reason = PM_PKG_REASON_DEPEND; - } else if(trans->flags & PM_TRANS_FLAG_ALLEXPLICIT) { - newpkg->reason = PM_PKG_REASON_EXPLICIT; + if(trans->flags & ALPM_TRANS_FLAG_ALLDEPS) { + newpkg->reason = ALPM_PKG_REASON_DEPEND; + } else if(trans->flags & ALPM_TRANS_FLAG_ALLEXPLICIT) { + newpkg->reason = ALPM_PKG_REASON_EXPLICIT; } if(oldpkg) { /* set up fake remove transaction */ - if(_alpm_upgraderemove_package(oldpkg, newpkg, trans) == -1) { - pm_errno = PM_ERR_TRANS_ABORT; + if(_alpm_remove_single_package(handle, oldpkg, newpkg, 0, 0) == -1) { + handle->pm_errno = ALPM_ERR_TRANS_ABORT; ret = -1; goto cleanup; } @@ -544,23 +516,23 @@ static int commit_single_pkg(pmpkg_t *newpkg, size_t pkg_current, /* prepare directory for database entries so permission are correct after changelog/install script installation (FS#12263) */ if(_alpm_local_db_prepare(db, newpkg)) { - alpm_logaction("error: could not create database entry %s-%s\n", + alpm_logaction(handle, "error: could not create database entry %s-%s\n", alpm_pkg_get_name(newpkg), alpm_pkg_get_version(newpkg)); - pm_errno = PM_ERR_DB_WRITE; + handle->pm_errno = ALPM_ERR_DB_WRITE; ret = -1; goto cleanup; } - if(!(trans->flags & PM_TRANS_FLAG_DBONLY)) { + if(!(trans->flags & ALPM_TRANS_FLAG_DBONLY)) { struct archive *archive; struct archive_entry *entry; char cwd[PATH_MAX] = ""; int restore_cwd = 0; - _alpm_log(PM_LOG_DEBUG, "extracting files\n"); + _alpm_log(handle, ALPM_LOG_DEBUG, "extracting files\n"); - if ((archive = archive_read_new()) == NULL) { - pm_errno = PM_ERR_LIBARCHIVE; + if((archive = archive_read_new()) == NULL) { + handle->pm_errno = ALPM_ERR_LIBARCHIVE; ret = -1; goto cleanup; } @@ -568,34 +540,35 @@ static int commit_single_pkg(pmpkg_t *newpkg, size_t pkg_current, archive_read_support_compression_all(archive); archive_read_support_format_all(archive); - _alpm_log(PM_LOG_DEBUG, "archive: %s\n", newpkg->origin_data.file); + _alpm_log(handle, ALPM_LOG_DEBUG, "archive: %s\n", newpkg->origin_data.file); if(archive_read_open_filename(archive, newpkg->origin_data.file, ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) { - pm_errno = PM_ERR_PKG_OPEN; + handle->pm_errno = ALPM_ERR_PKG_OPEN; ret = -1; goto cleanup; } /* save the cwd so we can restore it later */ if(getcwd(cwd, PATH_MAX) == NULL) { - _alpm_log(PM_LOG_ERROR, _("could not get current working directory\n")); + _alpm_log(handle, ALPM_LOG_ERROR, _("could not get current working directory\n")); } else { restore_cwd = 1; } /* libarchive requires this for extracting hard links */ if(chdir(handle->root) != 0) { - _alpm_log(PM_LOG_ERROR, _("could not change directory to %s (%s)\n"), handle->root, strerror(errno)); + _alpm_log(handle, ALPM_LOG_ERROR, _("could not change directory to %s (%s)\n"), + handle->root, strerror(errno)); ret = -1; goto cleanup; } /* call PROGRESS once with 0 percent, as we sort-of skip that here */ if(is_upgrade) { - PROGRESS(trans, PM_TRANS_PROGRESS_UPGRADE_START, + PROGRESS(trans, ALPM_TRANS_PROGRESS_UPGRADE_START, alpm_pkg_get_name(newpkg), 0, pkg_count, pkg_current); } else { - PROGRESS(trans, PM_TRANS_PROGRESS_ADD_START, + PROGRESS(trans, ALPM_TRANS_PROGRESS_ADD_START, alpm_pkg_get_name(newpkg), 0, pkg_count, pkg_current); } @@ -608,7 +581,7 @@ static int commit_single_pkg(pmpkg_t *newpkg, size_t pkg_current, * (missing metadata sizes) */ int64_t pos = archive_position_compressed(archive); percent = (pos * 100) / newpkg->size; - _alpm_log(PM_LOG_DEBUG, "decompression progress: " + _alpm_log(handle, ALPM_LOG_DEBUG, "decompression progress: " "%d%% (%"PRId64" / %jd)\n", percent, pos, (intmax_t)newpkg->size); if(percent >= 100) { @@ -619,37 +592,36 @@ static int commit_single_pkg(pmpkg_t *newpkg, size_t pkg_current, } if(is_upgrade) { - PROGRESS(trans, PM_TRANS_PROGRESS_UPGRADE_START, + PROGRESS(trans, ALPM_TRANS_PROGRESS_UPGRADE_START, alpm_pkg_get_name(newpkg), percent, pkg_count, pkg_current); } else { - PROGRESS(trans, PM_TRANS_PROGRESS_ADD_START, + PROGRESS(trans, ALPM_TRANS_PROGRESS_ADD_START, alpm_pkg_get_name(newpkg), percent, pkg_count, pkg_current); } /* extract the next file from the archive */ - errors += extract_single_file(archive, entry, newpkg, oldpkg, - trans, db); + errors += extract_single_file(handle, archive, entry, newpkg, oldpkg); } archive_read_finish(archive); /* restore the old cwd if we have it */ if(restore_cwd && chdir(cwd) != 0) { - _alpm_log(PM_LOG_ERROR, _("could not change directory to %s (%s)\n"), cwd, strerror(errno)); + _alpm_log(handle, ALPM_LOG_ERROR, _("could not change directory to %s (%s)\n"), cwd, strerror(errno)); } if(errors) { ret = -1; if(is_upgrade) { - _alpm_log(PM_LOG_ERROR, _("problem occurred while upgrading %s\n"), + _alpm_log(handle, ALPM_LOG_ERROR, _("problem occurred while upgrading %s\n"), newpkg->name); - alpm_logaction("error: problem occurred while upgrading %s\n", + alpm_logaction(handle, "error: problem occurred while upgrading %s\n", newpkg->name); } else { - _alpm_log(PM_LOG_ERROR, _("problem occurred while installing %s\n"), + _alpm_log(handle, ALPM_LOG_ERROR, _("problem occurred while installing %s\n"), newpkg->name); - alpm_logaction("error: problem occurred while installing %s\n", + alpm_logaction(handle, "error: problem occurred while installing %s\n", newpkg->name); } } @@ -658,69 +630,65 @@ static int commit_single_pkg(pmpkg_t *newpkg, size_t pkg_current, /* make an install date (in UTC) */ newpkg->installdate = time(NULL); - _alpm_log(PM_LOG_DEBUG, "updating database\n"); - _alpm_log(PM_LOG_DEBUG, "adding database entry '%s'\n", newpkg->name); + _alpm_log(handle, ALPM_LOG_DEBUG, "updating database\n"); + _alpm_log(handle, ALPM_LOG_DEBUG, "adding database entry '%s'\n", newpkg->name); if(_alpm_local_db_write(db, newpkg, INFRQ_ALL)) { - _alpm_log(PM_LOG_ERROR, _("could not update database entry %s-%s\n"), + _alpm_log(handle, ALPM_LOG_ERROR, _("could not update database entry %s-%s\n"), alpm_pkg_get_name(newpkg), alpm_pkg_get_version(newpkg)); - alpm_logaction("error: could not update database entry %s-%s\n", + alpm_logaction(handle, "error: could not update database entry %s-%s\n", alpm_pkg_get_name(newpkg), alpm_pkg_get_version(newpkg)); - pm_errno = PM_ERR_DB_WRITE; + handle->pm_errno = ALPM_ERR_DB_WRITE; ret = -1; goto cleanup; } if(_alpm_db_add_pkgincache(db, newpkg) == -1) { - _alpm_log(PM_LOG_ERROR, _("could not add entry '%s' in cache\n"), + _alpm_log(handle, ALPM_LOG_ERROR, _("could not add entry '%s' in cache\n"), alpm_pkg_get_name(newpkg)); } if(is_upgrade) { - PROGRESS(trans, PM_TRANS_PROGRESS_UPGRADE_START, + PROGRESS(trans, ALPM_TRANS_PROGRESS_UPGRADE_START, alpm_pkg_get_name(newpkg), 100, pkg_count, pkg_current); } else { - PROGRESS(trans, PM_TRANS_PROGRESS_ADD_START, + PROGRESS(trans, ALPM_TRANS_PROGRESS_ADD_START, alpm_pkg_get_name(newpkg), 100, pkg_count, pkg_current); } /* run the post-install script if it exists */ if(alpm_pkg_has_scriptlet(newpkg) - && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) { + && !(trans->flags & ALPM_TRANS_FLAG_NOSCRIPTLET)) { if(is_upgrade) { - _alpm_runscriptlet(handle->root, scriptlet, "post_upgrade", + _alpm_runscriptlet(handle, scriptlet, "post_upgrade", alpm_pkg_get_version(newpkg), - oldpkg ? alpm_pkg_get_version(oldpkg) : NULL, trans); + oldpkg ? alpm_pkg_get_version(oldpkg) : NULL); } else { - _alpm_runscriptlet(handle->root, scriptlet, "post_install", - alpm_pkg_get_version(newpkg), NULL, trans); + _alpm_runscriptlet(handle, scriptlet, "post_install", + alpm_pkg_get_version(newpkg), NULL); } } if(is_upgrade) { - EVENT(trans, PM_TRANS_EVT_UPGRADE_DONE, newpkg, oldpkg); + EVENT(trans, ALPM_TRANS_EVT_UPGRADE_DONE, newpkg, oldpkg); } else { - EVENT(trans, PM_TRANS_EVT_ADD_DONE, newpkg, oldpkg); + EVENT(trans, ALPM_TRANS_EVT_ADD_DONE, newpkg, oldpkg); } cleanup: _alpm_pkg_free(oldpkg); - return(ret); + return ret; } -int _alpm_upgrade_packages(pmtrans_t *trans, pmdb_t *db) +int _alpm_upgrade_packages(alpm_handle_t *handle) { size_t pkg_count, pkg_current; int skip_ldconfig = 0, ret = 0; alpm_list_t *targ; - - ALPM_LOG_FUNC; - - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); + alpm_trans_t *trans = handle->trans; if(trans->add == NULL) { - return(0); + return 0; } pkg_count = alpm_list_count(trans->add); @@ -728,15 +696,16 @@ int _alpm_upgrade_packages(pmtrans_t *trans, pmdb_t *db) /* loop through our package list adding/upgrading one at a time */ for(targ = trans->add; targ; targ = targ->next) { + alpm_pkg_t *newpkg = targ->data; + if(handle->trans->state == STATE_INTERRUPTED) { - return(ret); + return ret; } - pmpkg_t *newpkg = (pmpkg_t *)targ->data; - if(commit_single_pkg(newpkg, pkg_current, pkg_count, trans, db)) { + if(commit_single_pkg(handle, newpkg, pkg_current, pkg_count)) { /* something screwed up on the commit, abort the trans */ trans->state = STATE_INTERRUPTED; - pm_errno = PM_ERR_TRANS_ABORT; + handle->pm_errno = ALPM_ERR_TRANS_ABORT; /* running ldconfig at this point could possibly screw system */ skip_ldconfig = 1; ret = -1; @@ -747,10 +716,10 @@ int _alpm_upgrade_packages(pmtrans_t *trans, pmdb_t *db) if(!skip_ldconfig) { /* run ldconfig if it exists */ - _alpm_ldconfig(handle->root); + _alpm_ldconfig(handle); } - return(ret); + return ret; } /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/add.h b/lib/libalpm/add.h index afc7be26..77a3d22a 100644 --- a/lib/libalpm/add.h +++ b/lib/libalpm/add.h @@ -24,7 +24,7 @@ #include "alpm_list.h" #include "trans.h" -int _alpm_upgrade_packages(pmtrans_t *trans, pmdb_t *db); +int _alpm_upgrade_packages(alpm_handle_t *handle); #endif /* _ALPM_ADD_H */ diff --git a/lib/libalpm/alpm.c b/lib/libalpm/alpm.c index a60a4bb6..585c6a82 100644 --- a/lib/libalpm/alpm.c +++ b/lib/libalpm/alpm.c @@ -23,20 +23,17 @@ #include "config.h" -/* connection caching setup */ -#ifdef HAVE_LIBFETCH -#include <fetch.h> +#ifdef HAVE_LIBCURL +#include <curl/curl.h> #endif /* libalpm */ #include "alpm.h" #include "alpm_list.h" #include "handle.h" +#include "log.h" #include "util.h" -/* Globals */ -enum _pmerrno_t pm_errno SYMEXPORT; - /** \addtogroup alpm_interface Interface Functions * @brief Functions to initialize and release libalpm * @{ @@ -44,64 +41,90 @@ enum _pmerrno_t pm_errno SYMEXPORT; /** Initializes the library. This must be called before any other * functions are called. - * @return 0 on success, -1 on error (pm_errno is set accordingly) + * @param root the root path for all filesystem operations + * @param dbpath the absolute path to the libalpm database + * @param err an optional variable to hold any error return codes + * @return a context handle on success, NULL on error, err will be set if provided */ -int SYMEXPORT alpm_initialize(void) +alpm_handle_t SYMEXPORT *alpm_initialize(const char *root, const char *dbpath, + enum _alpm_errno_t *err) { - ASSERT(handle == NULL, RET_ERR(PM_ERR_HANDLE_NOT_NULL, -1)); - - handle = _alpm_handle_new(); - if(handle == NULL) { - RET_ERR(PM_ERR_MEMORY, -1); + enum _alpm_errno_t myerr; + const char *lf = "db.lck"; + size_t lockfilelen; + alpm_handle_t *myhandle = _alpm_handle_new(); + + if(myhandle == NULL) { + myerr = ALPM_ERR_MEMORY; + goto cleanup; + } + if((myerr = _alpm_set_directory_option(root, &(myhandle->root), 1))) { + goto cleanup; } - if(_alpm_db_register_local() == NULL) { - /* error code should be set */ - _alpm_handle_free(handle); - handle = NULL; - return(-1); + if((myerr = _alpm_set_directory_option(dbpath, &(myhandle->dbpath), 1))) { + goto cleanup; + } + + lockfilelen = strlen(myhandle->dbpath) + strlen(lf) + 1; + myhandle->lockfile = calloc(lockfilelen, sizeof(char)); + snprintf(myhandle->lockfile, lockfilelen, "%s%s", myhandle->dbpath, lf); + + if(_alpm_db_register_local(myhandle) == NULL) { + myerr = myhandle->pm_errno; + goto cleanup; } #ifdef ENABLE_NLS bindtextdomain("libalpm", LOCALEDIR); #endif -#ifdef HAVE_LIBFETCH - fetchConnectionCacheInit(5, 1); +#ifdef HAVE_LIBCURL + curl_global_init(CURL_GLOBAL_SSL); + myhandle->curl = curl_easy_init(); #endif - return(0); + return myhandle; + +cleanup: + _alpm_handle_free(myhandle); + if(err && myerr) { + *err = myerr; + } + return NULL; } /** Release the library. This should be the last alpm call you make. - * @return 0 on success, -1 on error (pm_errno is set accordingly) + * After this returns, handle should be considered invalid and cannot be reused + * in any way. + * @param handle the context handle + * @return 0 on success, -1 on error */ -int SYMEXPORT alpm_release(void) +int SYMEXPORT alpm_release(alpm_handle_t *myhandle) { - pmdb_t *db; - - ALPM_LOG_FUNC; + int ret = 0; + alpm_db_t *db; - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + CHECK_HANDLE(myhandle, return -1); /* close local database */ - db = handle->db_local; + db = myhandle->db_local; if(db) { db->ops->unregister(db); - handle->db_local = NULL; + myhandle->db_local = NULL; } - if(alpm_db_unregister_all() == -1) { - return(-1); + if(alpm_db_unregister_all(myhandle) == -1) { + ret = -1; } - _alpm_handle_free(handle); - handle = NULL; + _alpm_handle_unlock(myhandle); + _alpm_handle_free(myhandle); -#ifdef HAVE_LIBFETCH - fetchConnectionCacheClose(); +#ifdef HAVE_LIBCURL + curl_global_cleanup(); #endif - return(0); + return ret; } /** @} */ @@ -112,7 +135,7 @@ int SYMEXPORT alpm_release(void) /* Get the version of library */ const char SYMEXPORT *alpm_version(void) { - return(LIB_VERSION); + return LIB_VERSION; } /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index cb643d29..a91b00f0 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -45,49 +45,209 @@ extern "C" { */ /* - * Structures + * Enumerations + * These ones are used in multiple contexts, so are forward-declared. + */ + +/** + * Install reasons. + * Why the package was installed. */ +typedef enum _alpm_pkgreason_t { + /** Explicitly requested by the user. */ + ALPM_PKG_REASON_EXPLICIT = 0, + /** Installed as a dependency for another package. */ + ALPM_PKG_REASON_DEPEND = 1 +} alpm_pkgreason_t; -typedef struct __pmdb_t pmdb_t; -typedef struct __pmpkg_t pmpkg_t; -typedef struct __pmdelta_t pmdelta_t; -typedef struct __pmgrp_t pmgrp_t; -typedef struct __pmtrans_t pmtrans_t; -typedef struct __pmdepend_t pmdepend_t; -typedef struct __pmdepmissing_t pmdepmissing_t; -typedef struct __pmconflict_t pmconflict_t; -typedef struct __pmfileconflict_t pmfileconflict_t; +/** Types of version constraints in dependency specs. */ +typedef enum _alpm_depmod_t { + /** No version constraint */ + ALPM_DEP_MOD_ANY = 1, + /** Test version equality (package=x.y.z) */ + ALPM_DEP_MOD_EQ, + /** Test for at least a version (package>=x.y.z) */ + ALPM_DEP_MOD_GE, + /** Test for at most a version (package<=x.y.z) */ + ALPM_DEP_MOD_LE, + /** Test for greater than some version (package>x.y.z) */ + ALPM_DEP_MOD_GT, + /** Test for less than some version (package<x.y.z) */ + ALPM_DEP_MOD_LT +} alpm_depmod_t; + +/** + * File conflict type. + * Whether the conflict results from a file existing on the filesystem, or with + * another target in the transaction. + */ +typedef enum _alpm_fileconflicttype_t { + ALPM_FILECONFLICT_TARGET = 1, + ALPM_FILECONFLICT_FILESYSTEM +} alpm_fileconflicttype_t; + +/** + * PGP signature verification options + */ +typedef enum _alpm_siglevel_t { + ALPM_SIG_PACKAGE = (1 << 0), + ALPM_SIG_PACKAGE_OPTIONAL = (1 << 1), + ALPM_SIG_PACKAGE_MARGINAL_OK = (1 << 2), + ALPM_SIG_PACKAGE_UNKNOWN_OK = (1 << 3), + + ALPM_SIG_DATABASE = (1 << 10), + ALPM_SIG_DATABASE_OPTIONAL = (1 << 11), + ALPM_SIG_DATABASE_MARGINAL_OK = (1 << 12), + ALPM_SIG_DATABASE_UNKNOWN_OK = (1 << 13), + + ALPM_SIG_USE_DEFAULT = (1 << 31) +} alpm_siglevel_t; + +/** + * PGP signature verification status return codes + */ +typedef enum _alpm_sigstatus_t { + ALPM_SIGSTATUS_VALID, + ALPM_SIGSTATUS_KEY_EXPIRED, + ALPM_SIGSTATUS_SIG_EXPIRED, + ALPM_SIGSTATUS_KEY_UNKNOWN, + ALPM_SIGSTATUS_INVALID +} alpm_sigstatus_t; + +/** + * PGP signature verification status return codes + */ +typedef enum _alpm_sigvalidity_t { + ALPM_SIGVALIDITY_FULL, + ALPM_SIGVALIDITY_MARGINAL, + ALPM_SIGVALIDITY_NEVER, + ALPM_SIGVALIDITY_UNKNOWN +} alpm_sigvalidity_t; /* - * Library + * Structures */ -int alpm_initialize(void); -int alpm_release(void); -const char *alpm_version(void); +typedef struct __alpm_handle_t alpm_handle_t; +typedef struct __alpm_db_t alpm_db_t; +typedef struct __alpm_pkg_t alpm_pkg_t; +typedef struct __alpm_trans_t alpm_trans_t; + +/** Dependency */ +typedef struct _alpm_depend_t { + char *name; + char *version; + unsigned long name_hash; + alpm_depmod_t mod; +} alpm_depend_t; + +/** Missing dependency */ +typedef struct _alpm_depmissing_t { + char *target; + alpm_depend_t *depend; + /* this is used in case of remove dependency error only */ + char *causingpkg; +} alpm_depmissing_t; + +/** Conflict */ +typedef struct _alpm_conflict_t { + char *package1; + char *package2; + char *reason; +} alpm_conflict_t; + +/** File conflict */ +typedef struct _alpm_fileconflict_t { + char *target; + alpm_fileconflicttype_t type; + char *file; + char *ctarget; +} alpm_fileconflict_t; + +/** Package group */ +typedef struct _alpm_group_t { + /** group name */ + char *name; + /** list of alpm_pkg_t packages */ + alpm_list_t *packages; +} alpm_group_t; + +/** Package upgrade delta */ +typedef struct _alpm_delta_t { + /** filename of the delta patch */ + char *delta; + /** md5sum of the delta file */ + char *delta_md5; + /** filename of the 'before' file */ + char *from; + /** filename of the 'after' file */ + char *to; + /** filesize of the delta file */ + off_t delta_size; + /** download filesize of the delta file */ + off_t download_size; +} alpm_delta_t; + +/** File in a package */ +typedef struct _alpm_file_t { + char *name; + off_t size; + mode_t mode; +} alpm_file_t; + +/** Package filelist container */ +typedef struct _alpm_filelist_t { + size_t count; + alpm_file_t *files; +} alpm_filelist_t; + +/** Local package or package file backup entry */ +typedef struct _alpm_backup_t { + char *name; + char *hash; +} alpm_backup_t; + +/** Signature result. Contains the number of signatures found and pointers to + * arrays containing key and status info. All contained arrays have size + * #count.*/ +typedef struct _alpm_sigresult_t { + int count; + alpm_sigstatus_t *status; + alpm_sigvalidity_t *validity; + char **uid; +} alpm_sigresult_t; /* * Logging facilities */ -/* Levels */ -typedef enum _pmloglevel_t { - PM_LOG_ERROR = 1, - PM_LOG_WARNING = (1 << 1), - PM_LOG_DEBUG = (1 << 2), - PM_LOG_FUNCTION = (1 << 3) -} pmloglevel_t; +/** + * Logging Levels + */ +typedef enum _alpm_loglevel_t { + ALPM_LOG_ERROR = 1, + ALPM_LOG_WARNING = (1 << 1), + ALPM_LOG_DEBUG = (1 << 2), + ALPM_LOG_FUNCTION = (1 << 3) +} alpm_loglevel_t; -typedef void (*alpm_cb_log)(pmloglevel_t, const char *, va_list); -int alpm_logaction(const char *fmt, ...); +typedef void (*alpm_cb_log)(alpm_loglevel_t, const char *, va_list); +int alpm_logaction(alpm_handle_t *handle, const char *fmt, ...); /* * Downloading */ +/** Type of download progress callbacks. + * @param filename the name of the file being downloaded + * @param xfered the number of transferred bytes + * @param total the total number of bytes to transfer + */ typedef void (*alpm_cb_download)(const char *filename, off_t xfered, off_t total); + typedef void (*alpm_cb_totaldl)(off_t total); + /** A callback for downloading files * @param url the URL of the file to be downloaded * @param localpath the directory to which the file should be downloaded @@ -99,111 +259,131 @@ typedef int (*alpm_cb_fetch)(const char *url, const char *localpath, int force); /** Fetch a remote pkg. + * @param handle the context handle * @param url URL of the package to download * @return the downloaded filepath on success, NULL on error */ -char *alpm_fetch_pkgurl(const char *url); +char *alpm_fetch_pkgurl(alpm_handle_t *handle, const char *url); /** @addtogroup alpm_api_options Options * Libalpm option getters and setters * @{ */ -/** @name The logging callback. */ -/* @{ */ -alpm_cb_log alpm_option_get_logcb(void); -void alpm_option_set_logcb(alpm_cb_log cb); -/* @} */ +/** Returns the callback used for logging. */ +alpm_cb_log alpm_option_get_logcb(alpm_handle_t *handle); +/** Sets the callback used for logging. */ +int alpm_option_set_logcb(alpm_handle_t *handle, alpm_cb_log cb); -/** Get/set the download progress callback. */ -alpm_cb_download alpm_option_get_dlcb(void); -void alpm_option_set_dlcb(alpm_cb_download cb); +/** Returns the callback used to report download progress. */ +alpm_cb_download alpm_option_get_dlcb(alpm_handle_t *handle); +/** Sets the callback used to report download progress. */ +int alpm_option_set_dlcb(alpm_handle_t *handle, alpm_cb_download cb); -/** Get/set the downloader callback. */ -alpm_cb_fetch alpm_option_get_fetchcb(void); -void alpm_option_set_fetchcb(alpm_cb_fetch cb); +/** Returns the downloading callback. */ +alpm_cb_fetch alpm_option_get_fetchcb(alpm_handle_t *handle); +/** Sets the downloading callback. */ +int alpm_option_set_fetchcb(alpm_handle_t *handle, alpm_cb_fetch cb); -/** Get/set the callback used when download size is known. */ -alpm_cb_totaldl alpm_option_get_totaldlcb(void); -void alpm_option_set_totaldlcb(alpm_cb_totaldl cb); +/** Returns the callback used to report total download size. */ +alpm_cb_totaldl alpm_option_get_totaldlcb(alpm_handle_t *handle); +/** Sets the callback used to report total download size. */ +int alpm_option_set_totaldlcb(alpm_handle_t *handle, alpm_cb_totaldl cb); -/** Get/set the root of the destination filesystem. */ -const char *alpm_option_get_root(void); -int alpm_option_set_root(const char *root); +/** Returns the root of the destination filesystem. Read-only. */ +const char *alpm_option_get_root(alpm_handle_t *handle); -/** Get/set the path to the database directory. */ -const char *alpm_option_get_dbpath(void); -int alpm_option_set_dbpath(const char *dbpath); +/** Returns the path to the database directory. Read-only. */ +const char *alpm_option_get_dbpath(alpm_handle_t *handle); -/** Get/set the list of package cache directories. */ -alpm_list_t *alpm_option_get_cachedirs(void); -void alpm_option_set_cachedirs(alpm_list_t *cachedirs); +/** Get the name of the database lock file. Read-only. */ +const char *alpm_option_get_lockfile(alpm_handle_t *handle); -/** Add a single directory to the package cache paths. */ -int alpm_option_add_cachedir(const char *cachedir); +/** @name Accessors to the list of package cache directories. + * @{ + */ +alpm_list_t *alpm_option_get_cachedirs(alpm_handle_t *handle); +int alpm_option_set_cachedirs(alpm_handle_t *handle, alpm_list_t *cachedirs); +int alpm_option_add_cachedir(alpm_handle_t *handle, const char *cachedir); +int alpm_option_remove_cachedir(alpm_handle_t *handle, const char *cachedir); +/** @} */ -/** Remove a single directory from the package cache paths. */ -int alpm_option_remove_cachedir(const char *cachedir); +/** Returns the logfile name. */ +const char *alpm_option_get_logfile(alpm_handle_t *handle); +/** Sets the logfile name. */ +int alpm_option_set_logfile(alpm_handle_t *handle, const char *logfile); -/** Get/set the logfile name. */ -const char *alpm_option_get_logfile(void); -int alpm_option_set_logfile(const char *logfile); +/** Returns the path to libalpm's GnuPG home directory. */ +const char *alpm_option_get_gpgdir(alpm_handle_t *handle); +/** Sets the path to libalpm's GnuPG home directory. */ +int alpm_option_set_gpgdir(alpm_handle_t *handle, const char *gpgdir); -/** Get the name of the database lock file. - * - * This properly is read-only, and determined from - * the database path. - * - * @sa alpm_option_set_dbpath(const char*) - */ -const char *alpm_option_get_lockfile(void); +/** Returns whether to use syslog (0 is FALSE, TRUE otherwise). */ +int alpm_option_get_usesyslog(alpm_handle_t *handle); +/** Sets whether to use syslog (0 is FALSE, TRUE otherwise). */ +int alpm_option_set_usesyslog(alpm_handle_t *handle, int usesyslog); -/** Get/set whether to use syslog (0 is FALSE, TRUE otherwise). */ -int alpm_option_get_usesyslog(void); -void alpm_option_set_usesyslog(int usesyslog); +/** @name Accessors to the list of no-upgrade files. + * These functions modify the list of files which should + * not be updated by package installation. + * @{ + */ +alpm_list_t *alpm_option_get_noupgrades(alpm_handle_t *handle); +int alpm_option_add_noupgrade(alpm_handle_t *handle, const char *pkg); +int alpm_option_set_noupgrades(alpm_handle_t *handle, alpm_list_t *noupgrade); +int alpm_option_remove_noupgrade(alpm_handle_t *handle, const char *pkg); +/** @} */ -alpm_list_t *alpm_option_get_noupgrades(void); -void alpm_option_add_noupgrade(const char *pkg); -void alpm_option_set_noupgrades(alpm_list_t *noupgrade); -int alpm_option_remove_noupgrade(const char *pkg); +/** @name Accessors to the list of no-extract files. + * These functions modify the list of filenames which should + * be skipped packages which should + * not be upgraded by a sysupgrade operation. + * @{ + */ +alpm_list_t *alpm_option_get_noextracts(alpm_handle_t *handle); +int alpm_option_add_noextract(alpm_handle_t *handle, const char *pkg); +int alpm_option_set_noextracts(alpm_handle_t *handle, alpm_list_t *noextract); +int alpm_option_remove_noextract(alpm_handle_t *handle, const char *pkg); +/** @} */ -alpm_list_t *alpm_option_get_noextracts(void); -void alpm_option_add_noextract(const char *pkg); -void alpm_option_set_noextracts(alpm_list_t *noextract); -int alpm_option_remove_noextract(const char *pkg); +/** @name Accessors to the list of ignored packages. + * These functions modify the list of packages that + * should be ignored by a sysupgrade. + * @{ + */ +alpm_list_t *alpm_option_get_ignorepkgs(alpm_handle_t *handle); +int alpm_option_add_ignorepkg(alpm_handle_t *handle, const char *pkg); +int alpm_option_set_ignorepkgs(alpm_handle_t *handle, alpm_list_t *ignorepkgs); +int alpm_option_remove_ignorepkg(alpm_handle_t *handle, const char *pkg); +/** @} */ -alpm_list_t *alpm_option_get_ignorepkgs(void); -void alpm_option_add_ignorepkg(const char *pkg); -void alpm_option_set_ignorepkgs(alpm_list_t *ignorepkgs); -int alpm_option_remove_ignorepkg(const char *pkg); +/** @name Accessors to the list of ignored groups. + * These functions modify the list of groups whose packages + * should be ignored by a sysupgrade. + * @{ + */ +alpm_list_t *alpm_option_get_ignoregroups(alpm_handle_t *handle); +int alpm_option_add_ignoregroup(alpm_handle_t *handle, const char *grp); +int alpm_option_set_ignoregroups(alpm_handle_t *handle, alpm_list_t *ignoregrps); +int alpm_option_remove_ignoregroup(alpm_handle_t *handle, const char *grp); +/** @} */ -alpm_list_t *alpm_option_get_ignoregrps(void); -void alpm_option_add_ignoregrp(const char *grp); -void alpm_option_set_ignoregrps(alpm_list_t *ignoregrps); -int alpm_option_remove_ignoregrp(const char *grp); +/** Returns the targeted architecture. */ +const char *alpm_option_get_arch(alpm_handle_t *handle); +/** Sets the targeted architecture. */ +int alpm_option_set_arch(alpm_handle_t *handle, const char *arch); -/** Get/set the targeted architecture. */ -const char *alpm_option_get_arch(void); -void alpm_option_set_arch(const char *arch); +int alpm_option_get_usedelta(alpm_handle_t *handle); +int alpm_option_set_usedelta(alpm_handle_t *handle, int usedelta); -int alpm_option_get_usedelta(void); -void alpm_option_set_usedelta(int usedelta); +int alpm_option_get_checkspace(alpm_handle_t *handle); +int alpm_option_set_checkspace(alpm_handle_t *handle, int checkspace); -int alpm_option_get_checkspace(void); -void alpm_option_set_checkspace(int checkspace); +alpm_siglevel_t alpm_option_get_default_siglevel(alpm_handle_t *handle); +int alpm_option_set_default_siglevel(alpm_handle_t *handle, alpm_siglevel_t level); /** @} */ -/** Install reasons - * Why the package was installed. - */ -typedef enum _pmpkgreason_t { - /** Explicitly requested by the user. */ - PM_PKG_REASON_EXPLICIT = 0, - /** Installed as a dependency for another package. */ - PM_PKG_REASON_DEPEND = 1 -} pmpkgreason_t; - /** @addtogroup alpm_api_databases Database Functions * Functions to query and manipulate the database of libalpm. * @{ @@ -215,93 +395,112 @@ typedef enum _pmpkgreason_t { * libalpm functions. * @return a reference to the local database */ -pmdb_t *alpm_option_get_localdb(void); +alpm_db_t *alpm_option_get_localdb(alpm_handle_t *handle); /** Get the list of sync databases. - * Returns a list of pmdb_t structures, one for each registered + * Returns a list of alpm_db_t structures, one for each registered * sync database. - * @return a reference to an internal list of pmdb_t structures + * @param handle the context handle + * @return a reference to an internal list of alpm_db_t structures */ -alpm_list_t *alpm_option_get_syncdbs(void); +alpm_list_t *alpm_option_get_syncdbs(alpm_handle_t *handle); /** Register a sync database of packages. + * @param handle the context handle * @param treename the name of the sync repository - * @return a pmdb_t* on success (the value), NULL on error + * @param level what level of signature checking to perform on the + * database; note that this must be a '.sig' file type verification + * @return an alpm_db_t* on success (the value), NULL on error */ -pmdb_t *alpm_db_register_sync(const char *treename); +alpm_db_t *alpm_db_register_sync(alpm_handle_t *handle, const char *treename, + alpm_siglevel_t level); /** Unregister a package database. * @param db pointer to the package database to unregister * @return 0 on success, -1 on error (pm_errno is set accordingly) */ -int alpm_db_unregister(pmdb_t *db); +int alpm_db_unregister(alpm_db_t *db); /** Unregister all package databases. + * @param handle the context handle * @return 0 on success, -1 on error (pm_errno is set accordingly) */ -int alpm_db_unregister_all(void); +int alpm_db_unregister_all(alpm_handle_t *handle); /** Get the name of a package database. * @param db pointer to the package database * @return the name of the package database, NULL on error */ -const char *alpm_db_get_name(const pmdb_t *db); +const char *alpm_db_get_name(const alpm_db_t *db); -/** Get a download URL for the package database. +/** Get the signature verification level for a database. + * Will return the default verification level if this database is set up + * with ALPM_SIG_USE_DEFAULT. * @param db pointer to the package database - * @return a fully-specified download URL, NULL on error + * @return the signature verification level */ -const char *alpm_db_get_url(const pmdb_t *db); +alpm_siglevel_t alpm_db_get_siglevel(alpm_db_t *db); -/** Set the serverlist of a database. - * @param db database pointer - * @param url url of the server - * @return 0 on success, -1 on error (pm_errno is set accordingly) +/** Check the validity of a database. + * This is most useful for sync databases and verifying signature status. + * If invalid, the handle error code will be set accordingly. + * @param db pointer to the package database + * @return 0 if valid, -1 if invalid (pm_errno is set accordingly) + */ +int alpm_db_get_valid(alpm_db_t *db); + +/** @name Accessors to the list of servers for a database. + * @{ */ -int alpm_db_setserver(pmdb_t *db, const char *url); +alpm_list_t *alpm_db_get_servers(const alpm_db_t *db); +int alpm_db_set_servers(alpm_db_t *db, alpm_list_t *servers); +int alpm_db_add_server(alpm_db_t *db, const char *url); +int alpm_db_remove_server(alpm_db_t *db, const char *url); +/** @} */ -int alpm_db_update(int level, pmdb_t *db); +int alpm_db_update(int level, alpm_db_t *db); /** Get a package entry from a package database. * @param db pointer to the package database to get the package from * @param name of the package * @return the package entry on success, NULL on error */ -pmpkg_t *alpm_db_get_pkg(pmdb_t *db, const char *name); +alpm_pkg_t *alpm_db_get_pkg(alpm_db_t *db, const char *name); /** Get the package cache of a package database. * @param db pointer to the package database to get the package from * @return the list of packages on success, NULL on error */ -alpm_list_t *alpm_db_get_pkgcache(pmdb_t *db); +alpm_list_t *alpm_db_get_pkgcache(alpm_db_t *db); /** Get a group entry from a package database. * @param db pointer to the package database to get the group from * @param name of the group * @return the groups entry on success, NULL on error */ -pmgrp_t *alpm_db_readgrp(pmdb_t *db, const char *name); +alpm_group_t *alpm_db_readgroup(alpm_db_t *db, const char *name); /** Get the group cache of a package database. * @param db pointer to the package database to get the group from * @return the list of groups on success, NULL on error */ -alpm_list_t *alpm_db_get_grpcache(pmdb_t *db); +alpm_list_t *alpm_db_get_groupcache(alpm_db_t *db); -/** Searches a database. +/** Searches a database with regular expressions. * @param db pointer to the package database to search in - * @param needles the list of strings to search for - * @return the list of packages on success, NULL on error + * @param needles a list of regular expressions to search for + * @return the list of packages matching all regular expressions on success, NULL on error */ -alpm_list_t *alpm_db_search(pmdb_t *db, const alpm_list_t* needles); +alpm_list_t *alpm_db_search(alpm_db_t *db, const alpm_list_t* needles); /** Set install reason for a package in db. - * @param db pointer to the package database - * @param name the name of the package + * @param handle the context handle + * @param pkg the package to update * @param reason the new install reason * @return 0 on success, -1 on error (pm_errno is set accordingly) */ -int alpm_db_set_pkgreason(pmdb_t *db, const char *name, pmpkgreason_t reason); +int alpm_db_set_pkgreason(alpm_handle_t *handle, alpm_pkg_t *pkg, + alpm_pkgreason_t reason); /** @} */ @@ -313,26 +512,31 @@ int alpm_db_set_pkgreason(pmdb_t *db, const char *name, pmpkgreason_t reason); /** Create a package from a file. * If full is false, the archive is read only until all necessary * metadata is found. If it is true, the entire archive is read, which - * serves as a verfication of integrity and the filelist can be created. + * serves as a verification of integrity and the filelist can be created. + * The allocated structure should be freed using alpm_pkg_free(). + * @param handle the context handle * @param filename location of the package tarball * @param full whether to stop the load after metadata is read or continue - * through the full archive + * through the full archive + * @param level what level of package signature checking to perform on the + * package; note that this must be a '.sig' file type verification * @param pkg address of the package pointer * @return 0 on success, -1 on error (pm_errno is set accordingly) */ -int alpm_pkg_load(const char *filename, int full, pmpkg_t **pkg); +int alpm_pkg_load(alpm_handle_t *handle, const char *filename, int full, + alpm_siglevel_t, alpm_pkg_t **pkg); /** Free a package. * @param pkg package pointer to free * @return 0 on success, -1 on error (pm_errno is set accordingly) */ -int alpm_pkg_free(pmpkg_t *pkg); +int alpm_pkg_free(alpm_pkg_t *pkg); /** Check the integrity (with md5) of a package from the sync cache. * @param pkg package pointer * @return 0 on success, -1 on error (pm_errno is set accordingly) */ -int alpm_pkg_checkmd5sum(pmpkg_t *pkg); +int alpm_pkg_checkmd5sum(alpm_pkg_t *pkg); /** Compare two version strings and determine which one is 'newer'. */ int alpm_pkg_vercmp(const char *a, const char *b); @@ -343,7 +547,7 @@ int alpm_pkg_vercmp(const char *a, const char *b); * @param pkg a package * @return the list of packages requiring pkg */ -alpm_list_t *alpm_pkg_compute_requiredby(pmpkg_t *pkg); +alpm_list_t *alpm_pkg_compute_requiredby(alpm_pkg_t *pkg); /** @name Package Property Accessors * Any pointer returned by these functions points to internal structures @@ -356,13 +560,13 @@ alpm_list_t *alpm_pkg_compute_requiredby(pmpkg_t *pkg); * @param pkg a pointer to package * @return a reference to an internal string */ -const char *alpm_pkg_get_filename(pmpkg_t *pkg); +const char *alpm_pkg_get_filename(alpm_pkg_t *pkg); /** Returns the package name. * @param pkg a pointer to package * @return a reference to an internal string */ -const char *alpm_pkg_get_name(pmpkg_t *pkg); +const char *alpm_pkg_get_name(alpm_pkg_t *pkg); /** Returns the package version as a string. * This includes all available epoch, version, and pkgrel components. Use @@ -370,124 +574,125 @@ const char *alpm_pkg_get_name(pmpkg_t *pkg); * @param pkg a pointer to package * @return a reference to an internal string */ -const char *alpm_pkg_get_version(pmpkg_t *pkg); +const char *alpm_pkg_get_version(alpm_pkg_t *pkg); /** Returns the package description. * @param pkg a pointer to package * @return a reference to an internal string */ -const char *alpm_pkg_get_desc(pmpkg_t *pkg); +const char *alpm_pkg_get_desc(alpm_pkg_t *pkg); /** Returns the package URL. * @param pkg a pointer to package * @return a reference to an internal string */ -const char *alpm_pkg_get_url(pmpkg_t *pkg); +const char *alpm_pkg_get_url(alpm_pkg_t *pkg); /** Returns the build timestamp of the package. * @param pkg a pointer to package * @return the timestamp of the build time */ -time_t alpm_pkg_get_builddate(pmpkg_t *pkg); +time_t alpm_pkg_get_builddate(alpm_pkg_t *pkg); /** Returns the install timestamp of the package. * @param pkg a pointer to package * @return the timestamp of the install time */ -time_t alpm_pkg_get_installdate(pmpkg_t *pkg); +time_t alpm_pkg_get_installdate(alpm_pkg_t *pkg); /** Returns the packager's name. * @param pkg a pointer to package * @return a reference to an internal string */ -const char *alpm_pkg_get_packager(pmpkg_t *pkg); +const char *alpm_pkg_get_packager(alpm_pkg_t *pkg); /** Returns the package's MD5 checksum as a string. * The returned string is a sequence of lowercase hexadecimal digits. * @param pkg a pointer to package * @return a reference to an internal string */ -const char *alpm_pkg_get_md5sum(pmpkg_t *pkg); +const char *alpm_pkg_get_md5sum(alpm_pkg_t *pkg); /** Returns the architecture for which the package was built. * @param pkg a pointer to package * @return a reference to an internal string */ -const char *alpm_pkg_get_arch(pmpkg_t *pkg); +const char *alpm_pkg_get_arch(alpm_pkg_t *pkg); /** Returns the size of the package. * @param pkg a pointer to package * @return the size of the package in bytes. */ -off_t alpm_pkg_get_size(pmpkg_t *pkg); +off_t alpm_pkg_get_size(alpm_pkg_t *pkg); /** Returns the installed size of the package. * @param pkg a pointer to package * @return the total size of files installed by the package. */ -off_t alpm_pkg_get_isize(pmpkg_t *pkg); +off_t alpm_pkg_get_isize(alpm_pkg_t *pkg); /** Returns the package installation reason. * @param pkg a pointer to package * @return an enum member giving the install reason. */ -pmpkgreason_t alpm_pkg_get_reason(pmpkg_t *pkg); +alpm_pkgreason_t alpm_pkg_get_reason(alpm_pkg_t *pkg); /** Returns the list of package licenses. * @param pkg a pointer to package * @return a pointer to an internal list of strings. */ -alpm_list_t *alpm_pkg_get_licenses(pmpkg_t *pkg); +alpm_list_t *alpm_pkg_get_licenses(alpm_pkg_t *pkg); /** Returns the list of package groups. * @param pkg a pointer to package * @return a pointer to an internal list of strings. */ -alpm_list_t *alpm_pkg_get_groups(pmpkg_t *pkg); +alpm_list_t *alpm_pkg_get_groups(alpm_pkg_t *pkg); -/** Returns the list of package dependencies as pmdepend_t. +/** Returns the list of package dependencies as alpm_depend_t. * @param pkg a pointer to package - * @return a reference to an internal list of pmdepend_t structures. + * @return a reference to an internal list of alpm_depend_t structures. */ -alpm_list_t *alpm_pkg_get_depends(pmpkg_t *pkg); +alpm_list_t *alpm_pkg_get_depends(alpm_pkg_t *pkg); /** Returns the list of package optional dependencies. * @param pkg a pointer to package * @return a reference to an internal list of strings. */ -alpm_list_t *alpm_pkg_get_optdepends(pmpkg_t *pkg); +alpm_list_t *alpm_pkg_get_optdepends(alpm_pkg_t *pkg); /** Returns the list of package names conflicting with pkg. * @param pkg a pointer to package * @return a reference to an internal list of strings. */ -alpm_list_t *alpm_pkg_get_conflicts(pmpkg_t *pkg); +alpm_list_t *alpm_pkg_get_conflicts(alpm_pkg_t *pkg); /** Returns the list of package names provided by pkg. * @param pkg a pointer to package * @return a reference to an internal list of strings. */ -alpm_list_t *alpm_pkg_get_provides(pmpkg_t *pkg); +alpm_list_t *alpm_pkg_get_provides(alpm_pkg_t *pkg); /** Returns the list of available deltas for pkg. * @param pkg a pointer to package * @return a reference to an internal list of strings. */ -alpm_list_t *alpm_pkg_get_deltas(pmpkg_t *pkg); +alpm_list_t *alpm_pkg_get_deltas(alpm_pkg_t *pkg); /** Returns the list of packages to be replaced by pkg. * @param pkg a pointer to package * @return a reference to an internal list of strings. */ -alpm_list_t *alpm_pkg_get_replaces(pmpkg_t *pkg); +alpm_list_t *alpm_pkg_get_replaces(alpm_pkg_t *pkg); /** Returns the list of files installed by pkg. * The filenames are relative to the install root, * and do not include leading slashes. * @param pkg a pointer to package - * @return a reference to an internal list of strings. + * @return a pointer to a filelist object containing a count and an array of + * package file objects */ -alpm_list_t *alpm_pkg_get_files(pmpkg_t *pkg); +alpm_filelist_t *alpm_pkg_get_files(alpm_pkg_t *pkg); /** Returns the list of files backed up when installing pkg. * The elements of the returned list have the form @@ -496,17 +701,17 @@ alpm_list_t *alpm_pkg_get_files(pmpkg_t *pkg); * @param pkg a pointer to package * @return a reference to an internal list of strings. */ -alpm_list_t *alpm_pkg_get_backup(pmpkg_t *pkg); +alpm_list_t *alpm_pkg_get_backup(alpm_pkg_t *pkg); -/** Returns the database containing pkg - * Returns a pointer to the pmdb_t structure the package is - * originating from, or NULL is the package was loaded from a file. +/** Returns the database containing pkg. + * Returns a pointer to the alpm_db_t structure the package is + * originating from, or NULL if the package was loaded from a file. * @param pkg a pointer to package * @return a pointer to the DB containing pkg, or NULL. */ -pmdb_t *alpm_pkg_get_db(pmpkg_t *pkg); +alpm_db_t *alpm_pkg_get_db(alpm_pkg_t *pkg); -/* End of pmpkg_t accessors */ +/* End of alpm_pkg_t accessors */ /* @} */ /** Open a package changelog for reading. @@ -515,7 +720,7 @@ pmdb_t *alpm_pkg_get_db(pmpkg_t *pkg); * @param pkg the package to read the changelog of (either file or db) * @return a 'file stream' to the package changelog */ -void *alpm_pkg_changelog_open(pmpkg_t *pkg); +void *alpm_pkg_changelog_open(alpm_pkg_t *pkg); /** Read data from an open changelog 'file stream'. * Similar to fread in functionality, this function takes a buffer and @@ -528,13 +733,16 @@ void *alpm_pkg_changelog_open(pmpkg_t *pkg); * error occurred. */ size_t alpm_pkg_changelog_read(void *ptr, size_t size, - const pmpkg_t *pkg, const void *fp); + const alpm_pkg_t *pkg, const void *fp); -/*int alpm_pkg_changelog_feof(const pmpkg_t *pkg, void *fp);*/ +/*int alpm_pkg_changelog_feof(const alpm_pkg_t *pkg, void *fp);*/ -int alpm_pkg_changelog_close(const pmpkg_t *pkg, void *fp); +int alpm_pkg_changelog_close(const alpm_pkg_t *pkg, void *fp); -int alpm_pkg_has_scriptlet(pmpkg_t *pkg); +/** Returns whether the package has an install scriptlet. + * @return 0 if FALSE, TRUE otherwise + */ +int alpm_pkg_has_scriptlet(alpm_pkg_t *pkg); /** Returns the size of download. * Returns the size of the files that will be downloaded to install a @@ -542,35 +750,34 @@ int alpm_pkg_has_scriptlet(pmpkg_t *pkg); * @param newpkg the new package to upgrade to * @return the size of the download */ -off_t alpm_pkg_download_size(pmpkg_t *newpkg); +off_t alpm_pkg_download_size(alpm_pkg_t *newpkg); -alpm_list_t *alpm_pkg_unused_deltas(pmpkg_t *pkg); +alpm_list_t *alpm_pkg_unused_deltas(alpm_pkg_t *pkg); /* End of alpm_pkg */ /** @} */ /* - * Deltas + * Signatures */ -const char *alpm_delta_get_from(pmdelta_t *delta); -const char *alpm_delta_get_to(pmdelta_t *delta); -const char *alpm_delta_get_filename(pmdelta_t *delta); -const char *alpm_delta_get_md5sum(pmdelta_t *delta); -off_t alpm_delta_get_size(pmdelta_t *delta); +int alpm_pkg_check_pgp_signature(alpm_pkg_t *pkg, alpm_sigresult_t *result); + +int alpm_db_check_pgp_signature(alpm_db_t *db, alpm_sigresult_t *result); + +int alpm_sigresult_cleanup(alpm_sigresult_t *result); /* * Groups */ -const char *alpm_grp_get_name(const pmgrp_t *grp); -alpm_list_t *alpm_grp_get_pkgs(const pmgrp_t *grp); -alpm_list_t *alpm_find_grp_pkgs(alpm_list_t *dbs, const char *name); + +alpm_list_t *alpm_find_group_pkgs(alpm_list_t *dbs, const char *name); /* * Sync */ -pmpkg_t *alpm_sync_newversion(pmpkg_t *pkg, alpm_list_t *dbs_sync); +alpm_pkg_t *alpm_sync_newversion(alpm_pkg_t *pkg, alpm_list_t *dbs_sync); /** @addtogroup alpm_api_trans Transaction Functions * Functions to manipulate libalpm transactions @@ -578,290 +785,263 @@ pmpkg_t *alpm_sync_newversion(pmpkg_t *pkg, alpm_list_t *dbs_sync); */ /** Transaction flags */ -typedef enum _pmtransflag_t { +typedef enum _alpm_transflag_t { /** Ignore dependency checks. */ - PM_TRANS_FLAG_NODEPS = 1, + ALPM_TRANS_FLAG_NODEPS = 1, /** Ignore file conflicts and overwrite files. */ - PM_TRANS_FLAG_FORCE = (1 << 1), + ALPM_TRANS_FLAG_FORCE = (1 << 1), /** Delete files even if they are tagged as backup. */ - PM_TRANS_FLAG_NOSAVE = (1 << 2), + ALPM_TRANS_FLAG_NOSAVE = (1 << 2), /** Ignore version numbers when checking dependencies. */ - PM_TRANS_FLAG_NODEPVERSION = (1 << 3), + ALPM_TRANS_FLAG_NODEPVERSION = (1 << 3), /** Remove also any packages depending on a package being removed. */ - PM_TRANS_FLAG_CASCADE = (1 << 4), + ALPM_TRANS_FLAG_CASCADE = (1 << 4), /** Remove packages and their unneeded deps (not explicitly installed). */ - PM_TRANS_FLAG_RECURSE = (1 << 5), + ALPM_TRANS_FLAG_RECURSE = (1 << 5), /** Modify database but do not commit changes to the filesystem. */ - PM_TRANS_FLAG_DBONLY = (1 << 6), + ALPM_TRANS_FLAG_DBONLY = (1 << 6), /* (1 << 7) flag can go here */ - /** Use PM_PKG_REASON_DEPEND when installing packages. */ - PM_TRANS_FLAG_ALLDEPS = (1 << 8), + /** Use ALPM_PKG_REASON_DEPEND when installing packages. */ + ALPM_TRANS_FLAG_ALLDEPS = (1 << 8), /** Only download packages and do not actually install. */ - PM_TRANS_FLAG_DOWNLOADONLY = (1 << 9), + ALPM_TRANS_FLAG_DOWNLOADONLY = (1 << 9), /** Do not execute install scriptlets after installing. */ - PM_TRANS_FLAG_NOSCRIPTLET = (1 << 10), + ALPM_TRANS_FLAG_NOSCRIPTLET = (1 << 10), /** Ignore dependency conflicts. */ - PM_TRANS_FLAG_NOCONFLICTS = (1 << 11), + ALPM_TRANS_FLAG_NOCONFLICTS = (1 << 11), /* (1 << 12) flag can go here */ /** Do not install a package if it is already installed and up to date. */ - PM_TRANS_FLAG_NEEDED = (1 << 13), - /** Use PM_PKG_REASON_EXPLICIT when installing packages. */ - PM_TRANS_FLAG_ALLEXPLICIT = (1 << 14), + ALPM_TRANS_FLAG_NEEDED = (1 << 13), + /** Use ALPM_PKG_REASON_EXPLICIT when installing packages. */ + ALPM_TRANS_FLAG_ALLEXPLICIT = (1 << 14), /** Do not remove a package if it is needed by another one. */ - PM_TRANS_FLAG_UNNEEDED = (1 << 15), - /** Remove also explicitly installed unneeded deps (use with PM_TRANS_FLAG_RECURSE). */ - PM_TRANS_FLAG_RECURSEALL = (1 << 16), + ALPM_TRANS_FLAG_UNNEEDED = (1 << 15), + /** Remove also explicitly installed unneeded deps (use with ALPM_TRANS_FLAG_RECURSE). */ + ALPM_TRANS_FLAG_RECURSEALL = (1 << 16), /** Do not lock the database during the operation. */ - PM_TRANS_FLAG_NOLOCK = (1 << 17) -} pmtransflag_t; + ALPM_TRANS_FLAG_NOLOCK = (1 << 17) +} alpm_transflag_t; /** Transaction events. * NULL parameters are passed to in all events unless specified otherwise. */ -typedef enum _pmtransevt_t { +typedef enum _alpm_transevt_t { /** Dependencies will be computed for a package. */ - PM_TRANS_EVT_CHECKDEPS_START = 1, + ALPM_TRANS_EVT_CHECKDEPS_START = 1, /** Dependencies were computed for a package. */ - PM_TRANS_EVT_CHECKDEPS_DONE, + ALPM_TRANS_EVT_CHECKDEPS_DONE, /** File conflicts will be computed for a package. */ - PM_TRANS_EVT_FILECONFLICTS_START, + ALPM_TRANS_EVT_FILECONFLICTS_START, /** File conflicts were computed for a package. */ - PM_TRANS_EVT_FILECONFLICTS_DONE, + ALPM_TRANS_EVT_FILECONFLICTS_DONE, /** Dependencies will be resolved for target package. */ - PM_TRANS_EVT_RESOLVEDEPS_START, + ALPM_TRANS_EVT_RESOLVEDEPS_START, /** Dependencies were resolved for target package. */ - PM_TRANS_EVT_RESOLVEDEPS_DONE, + ALPM_TRANS_EVT_RESOLVEDEPS_DONE, /** Inter-conflicts will be checked for target package. */ - PM_TRANS_EVT_INTERCONFLICTS_START, + ALPM_TRANS_EVT_INTERCONFLICTS_START, /** Inter-conflicts were checked for target package. */ - PM_TRANS_EVT_INTERCONFLICTS_DONE, + ALPM_TRANS_EVT_INTERCONFLICTS_DONE, /** Package will be installed. * A pointer to the target package is passed to the callback. */ - PM_TRANS_EVT_ADD_START, + ALPM_TRANS_EVT_ADD_START, /** Package was installed. * A pointer to the new package is passed to the callback. */ - PM_TRANS_EVT_ADD_DONE, + ALPM_TRANS_EVT_ADD_DONE, /** Package will be removed. * A pointer to the target package is passed to the callback. */ - PM_TRANS_EVT_REMOVE_START, + ALPM_TRANS_EVT_REMOVE_START, /** Package was removed. * A pointer to the removed package is passed to the callback. */ - PM_TRANS_EVT_REMOVE_DONE, + ALPM_TRANS_EVT_REMOVE_DONE, /** Package will be upgraded. * A pointer to the upgraded package is passed to the callback. */ - PM_TRANS_EVT_UPGRADE_START, + ALPM_TRANS_EVT_UPGRADE_START, /** Package was upgraded. * A pointer to the new package, and a pointer to the old package is passed * to the callback, respectively. */ - PM_TRANS_EVT_UPGRADE_DONE, + ALPM_TRANS_EVT_UPGRADE_DONE, /** Target package's integrity will be checked. */ - PM_TRANS_EVT_INTEGRITY_START, + ALPM_TRANS_EVT_INTEGRITY_START, /** Target package's integrity was checked. */ - PM_TRANS_EVT_INTEGRITY_DONE, + ALPM_TRANS_EVT_INTEGRITY_DONE, /** Target deltas's integrity will be checked. */ - PM_TRANS_EVT_DELTA_INTEGRITY_START, + ALPM_TRANS_EVT_DELTA_INTEGRITY_START, /** Target delta's integrity was checked. */ - PM_TRANS_EVT_DELTA_INTEGRITY_DONE, + ALPM_TRANS_EVT_DELTA_INTEGRITY_DONE, /** Deltas will be applied to packages. */ - PM_TRANS_EVT_DELTA_PATCHES_START, + ALPM_TRANS_EVT_DELTA_PATCHES_START, /** Deltas were applied to packages. */ - PM_TRANS_EVT_DELTA_PATCHES_DONE, + ALPM_TRANS_EVT_DELTA_PATCHES_DONE, /** Delta patch will be applied to target package. * The filename of the package and the filename of the patch is passed to the * callback. */ - PM_TRANS_EVT_DELTA_PATCH_START, + ALPM_TRANS_EVT_DELTA_PATCH_START, /** Delta patch was applied to target package. */ - PM_TRANS_EVT_DELTA_PATCH_DONE, + ALPM_TRANS_EVT_DELTA_PATCH_DONE, /** Delta patch failed to apply to target package. */ - PM_TRANS_EVT_DELTA_PATCH_FAILED, + ALPM_TRANS_EVT_DELTA_PATCH_FAILED, /** Scriptlet has printed information. * A line of text is passed to the callback. */ - PM_TRANS_EVT_SCRIPTLET_INFO, + ALPM_TRANS_EVT_SCRIPTLET_INFO, /** Files will be downloaded from a repository. * The repository's tree name is passed to the callback. */ - PM_TRANS_EVT_RETRIEVE_START, + ALPM_TRANS_EVT_RETRIEVE_START, /** Disk space usage will be computed for a package */ - PM_TRANS_EVT_DISKSPACE_START, + ALPM_TRANS_EVT_DISKSPACE_START, /** Disk space usage was computed for a package */ - PM_TRANS_EVT_DISKSPACE_DONE, -} pmtransevt_t; + ALPM_TRANS_EVT_DISKSPACE_DONE, +} alpm_transevt_t; /** Transaction Conversations (ie, questions) */ -typedef enum _pmtransconv_t { - PM_TRANS_CONV_INSTALL_IGNOREPKG = 1, - PM_TRANS_CONV_REPLACE_PKG = (1 << 1), - PM_TRANS_CONV_CONFLICT_PKG = (1 << 2), - PM_TRANS_CONV_CORRUPTED_PKG = (1 << 3), - PM_TRANS_CONV_LOCAL_NEWER = (1 << 4), - PM_TRANS_CONV_REMOVE_PKGS = (1 << 5), - PM_TRANS_CONV_SELECT_PROVIDER = (1 << 6), -} pmtransconv_t; +typedef enum _alpm_transconv_t { + ALPM_TRANS_CONV_INSTALL_IGNOREPKG = 1, + ALPM_TRANS_CONV_REPLACE_PKG = (1 << 1), + ALPM_TRANS_CONV_CONFLICT_PKG = (1 << 2), + ALPM_TRANS_CONV_CORRUPTED_PKG = (1 << 3), + ALPM_TRANS_CONV_LOCAL_NEWER = (1 << 4), + ALPM_TRANS_CONV_REMOVE_PKGS = (1 << 5), + ALPM_TRANS_CONV_SELECT_PROVIDER = (1 << 6), +} alpm_transconv_t; /** Transaction Progress */ -typedef enum _pmtransprog_t { - PM_TRANS_PROGRESS_ADD_START, - PM_TRANS_PROGRESS_UPGRADE_START, - PM_TRANS_PROGRESS_REMOVE_START, - PM_TRANS_PROGRESS_CONFLICTS_START, - PM_TRANS_PROGRESS_DISKSPACE_START, - PM_TRANS_PROGRESS_INTEGRITY_START, -} pmtransprog_t; +typedef enum _alpm_transprog_t { + ALPM_TRANS_PROGRESS_ADD_START, + ALPM_TRANS_PROGRESS_UPGRADE_START, + ALPM_TRANS_PROGRESS_REMOVE_START, + ALPM_TRANS_PROGRESS_CONFLICTS_START, + ALPM_TRANS_PROGRESS_DISKSPACE_START, + ALPM_TRANS_PROGRESS_INTEGRITY_START, +} alpm_transprog_t; /** Transaction Event callback */ -typedef void (*alpm_trans_cb_event)(pmtransevt_t, void *, void *); +typedef void (*alpm_trans_cb_event)(alpm_transevt_t, void *, void *); /** Transaction Conversation callback */ -typedef void (*alpm_trans_cb_conv)(pmtransconv_t, void *, void *, +typedef void (*alpm_trans_cb_conv)(alpm_transconv_t, void *, void *, void *, int *); /** Transaction Progress callback */ -typedef void (*alpm_trans_cb_progress)(pmtransprog_t, const char *, int, size_t, size_t); +typedef void (*alpm_trans_cb_progress)(alpm_transprog_t, const char *, int, size_t, size_t); -int alpm_trans_get_flags(void); +/** Returns the bitfield of flags for the current transaction. + * @param handle the context handle + * @return the bitfield of transaction flags + */ +alpm_transflag_t alpm_trans_get_flags(alpm_handle_t *handle); /** Returns a list of packages added by the transaction. - * @return a list of pmpkg_t structures + * @param handle the context handle + * @return a list of alpm_pkg_t structures */ -alpm_list_t * alpm_trans_get_add(void); +alpm_list_t * alpm_trans_get_add(alpm_handle_t *handle); /** Returns the list of packages removed by the transaction. - * @return a list of pmpkg_t structures + * @param handle the context handle + * @return a list of alpm_pkg_t structures */ -alpm_list_t * alpm_trans_get_remove(void); +alpm_list_t * alpm_trans_get_remove(alpm_handle_t *handle); /** Initialize the transaction. + * @param handle the context handle * @param flags flags of the transaction (like nodeps, etc) * @param event event callback function pointer * @param conv question callback function pointer * @param progress progress callback function pointer * @return 0 on success, -1 on error (pm_errno is set accordingly) */ -int alpm_trans_init(pmtransflag_t flags, +int alpm_trans_init(alpm_handle_t *handle, alpm_transflag_t flags, alpm_trans_cb_event cb_event, alpm_trans_cb_conv conv, alpm_trans_cb_progress cb_progress); /** Prepare a transaction. + * @param handle the context handle * @param data the address of an alpm_list where a list - * of pmdepmissing_t objects is dumped (conflicting packages) + * of alpm_depmissing_t objects is dumped (conflicting packages) * @return 0 on success, -1 on error (pm_errno is set accordingly) */ -int alpm_trans_prepare(alpm_list_t **data); +int alpm_trans_prepare(alpm_handle_t *handle, alpm_list_t **data); /** Commit a transaction. + * @param handle the context handle * @param data the address of an alpm_list where detailed description * of an error can be dumped (ie. list of conflicting files) * @return 0 on success, -1 on error (pm_errno is set accordingly) */ -int alpm_trans_commit(alpm_list_t **data); +int alpm_trans_commit(alpm_handle_t *handle, alpm_list_t **data); /** Interrupt a transaction. + * @param handle the context handle * @return 0 on success, -1 on error (pm_errno is set accordingly) */ -int alpm_trans_interrupt(void); +int alpm_trans_interrupt(alpm_handle_t *handle); /** Release a transaction. + * @param handle the context handle * @return 0 on success, -1 on error (pm_errno is set accordingly) */ -int alpm_trans_release(void); +int alpm_trans_release(alpm_handle_t *handle); /** @} */ /** @name Common Transactions */ /** @{ */ -int alpm_sync_sysupgrade(int enable_downgrade); -int alpm_add_pkg(pmpkg_t *pkg); -int alpm_remove_pkg(pmpkg_t *pkg); -/** @} */ -/** @addtogroup alpm_api_depends Dependency Functions - * Functions dealing with libalpm representation of dependency - * information. - * @{ +/** Search for packages to upgrade and add them to the transaction. + * @param handle the context handle + * @param enable_downgrade allow downgrading of packages if the remote version is lower + * @return 0 on success, -1 on error (pm_errno is set accordingly) */ +int alpm_sync_sysupgrade(alpm_handle_t *handle, int enable_downgrade); -/** Types of version constraints in dependency specs. */ -typedef enum _pmdepmod_t { - /** No version constraint */ - PM_DEP_MOD_ANY = 1, - /** Test version equality (package=x.y.z) */ - PM_DEP_MOD_EQ, - /** Test for at least a version (package>=x.y.z) */ - PM_DEP_MOD_GE, - /** Test for at most a version (package<=x.y.z) */ - PM_DEP_MOD_LE, - /** Test for greater than some version (package>x.y.z) */ - PM_DEP_MOD_GT, - /** Test for less than some version (package<x.y.z) */ - PM_DEP_MOD_LT -} pmdepmod_t; - -alpm_list_t *alpm_checkdeps(alpm_list_t *pkglist, int reversedeps, - alpm_list_t *remove, alpm_list_t *upgrade); -pmpkg_t *alpm_find_satisfier(alpm_list_t *pkgs, const char *depstring); -pmpkg_t *alpm_find_dbs_satisfier(alpm_list_t *dbs, const char *depstring); - -const char *alpm_miss_get_target(const pmdepmissing_t *miss); -pmdepend_t *alpm_miss_get_dep(pmdepmissing_t *miss); -const char *alpm_miss_get_causingpkg(const pmdepmissing_t *miss); +/** Add a package to the transaction. + * If the package was loaded by alpm_pkg_load(), it will be freed upon + * alpm_trans_release() invocation. + * @param handle the context handle + * @param pkg the package to add + * @return 0 on success, -1 on error (pm_errno is set accordingly) + */ +int alpm_add_pkg(alpm_handle_t *handle, alpm_pkg_t *pkg); -alpm_list_t *alpm_checkconflicts(alpm_list_t *pkglist); +/** Add a package removal action to the transaction. + * @param handle the context handle + * @param pkg the package to uninstall + * @return 0 on success, -1 on error (pm_errno is set accordingly) + */ +int alpm_remove_pkg(alpm_handle_t *handle, alpm_pkg_t *pkg); -const char *alpm_conflict_get_package1(pmconflict_t *conflict); -const char *alpm_conflict_get_package2(pmconflict_t *conflict); -const char *alpm_conflict_get_reason(pmconflict_t *conflict); +/** @} */ -/** Returns the type of version constraint. - * @param dep a dependency info structure - * @return the type of version constraint (PM_DEP_MOD_ANY if no version - * is specified). +/** @addtogroup alpm_api_depends Dependency Functions + * Functions dealing with libalpm representation of dependency + * information. + * @{ */ -pmdepmod_t alpm_dep_get_mod(const pmdepend_t *dep); -/** Returns the package name of a dependency constraint. - * @param dep a dependency info structure - * @return a pointer to an internal string. - */ -const char *alpm_dep_get_name(const pmdepend_t *dep); +alpm_list_t *alpm_checkdeps(alpm_handle_t *handle, alpm_list_t *pkglist, + alpm_list_t *remove, alpm_list_t *upgrade, int reversedeps); +alpm_pkg_t *alpm_find_satisfier(alpm_list_t *pkgs, const char *depstring); +alpm_pkg_t *alpm_find_dbs_satisfier(alpm_handle_t *handle, + alpm_list_t *dbs, const char *depstring); -/** Returns the version specified by a dependency constraint. - * The version information is returned as a string in the same format - * as given by alpm_pkg_get_version(). - * @param dep a dependency info structure - * @return a pointer to an internal string. - */ -const char *alpm_dep_get_version(const pmdepend_t *dep); +alpm_list_t *alpm_checkconflicts(alpm_handle_t *handle, alpm_list_t *pkglist); /** Returns a newly allocated string representing the dependency information. * @param dep a dependency info structure * @return a formatted string, e.g. "glibc>=2.12" */ -char *alpm_dep_compute_string(const pmdepend_t *dep); +char *alpm_dep_compute_string(const alpm_depend_t *dep); /** @} */ -/** @addtogroup alpm_api_fileconflicts File Conflicts Functions - * Functions to manipulate file conflict information. - * @{ - */ - -typedef enum _pmfileconflicttype_t { - PM_FILECONFLICT_TARGET = 1, - PM_FILECONFLICT_FILESYSTEM -} pmfileconflicttype_t; - -const char *alpm_fileconflict_get_target(pmfileconflict_t *conflict); -pmfileconflicttype_t alpm_fileconflict_get_type(pmfileconflict_t *conflict); -const char *alpm_fileconflict_get_file(pmfileconflict_t *conflict); -const char *alpm_fileconflict_get_ctarget(pmfileconflict_t *conflict); - /** @} */ /* @@ -874,77 +1054,85 @@ char *alpm_compute_md5sum(const char *name); /** @addtogroup alpm_api_errors Error Codes * @{ */ -enum _pmerrno_t { - PM_ERR_MEMORY = 1, - PM_ERR_SYSTEM, - PM_ERR_BADPERMS, - PM_ERR_NOT_A_FILE, - PM_ERR_NOT_A_DIR, - PM_ERR_WRONG_ARGS, - PM_ERR_DISK_SPACE, +enum _alpm_errno_t { + ALPM_ERR_MEMORY = 1, + ALPM_ERR_SYSTEM, + ALPM_ERR_BADPERMS, + ALPM_ERR_NOT_A_FILE, + ALPM_ERR_NOT_A_DIR, + ALPM_ERR_WRONG_ARGS, + ALPM_ERR_DISK_SPACE, /* Interface */ - PM_ERR_HANDLE_NULL, - PM_ERR_HANDLE_NOT_NULL, - PM_ERR_HANDLE_LOCK, + ALPM_ERR_HANDLE_NULL, + ALPM_ERR_HANDLE_NOT_NULL, + ALPM_ERR_HANDLE_LOCK, /* Databases */ - PM_ERR_DB_OPEN, - PM_ERR_DB_CREATE, - PM_ERR_DB_NULL, - PM_ERR_DB_NOT_NULL, - PM_ERR_DB_NOT_FOUND, - PM_ERR_DB_VERSION, - PM_ERR_DB_WRITE, - PM_ERR_DB_REMOVE, + ALPM_ERR_DB_OPEN, + ALPM_ERR_DB_CREATE, + ALPM_ERR_DB_NULL, + ALPM_ERR_DB_NOT_NULL, + ALPM_ERR_DB_NOT_FOUND, + ALPM_ERR_DB_INVALID, + ALPM_ERR_DB_INVALID_SIG, + ALPM_ERR_DB_VERSION, + ALPM_ERR_DB_WRITE, + ALPM_ERR_DB_REMOVE, /* Servers */ - PM_ERR_SERVER_BAD_URL, - PM_ERR_SERVER_NONE, + ALPM_ERR_SERVER_BAD_URL, + ALPM_ERR_SERVER_NONE, /* Transactions */ - PM_ERR_TRANS_NOT_NULL, - PM_ERR_TRANS_NULL, - PM_ERR_TRANS_DUP_TARGET, - PM_ERR_TRANS_NOT_INITIALIZED, - PM_ERR_TRANS_NOT_PREPARED, - PM_ERR_TRANS_ABORT, - PM_ERR_TRANS_TYPE, - PM_ERR_TRANS_NOT_LOCKED, + ALPM_ERR_TRANS_NOT_NULL, + ALPM_ERR_TRANS_NULL, + ALPM_ERR_TRANS_DUP_TARGET, + ALPM_ERR_TRANS_NOT_INITIALIZED, + ALPM_ERR_TRANS_NOT_PREPARED, + ALPM_ERR_TRANS_ABORT, + ALPM_ERR_TRANS_TYPE, + ALPM_ERR_TRANS_NOT_LOCKED, /* Packages */ - PM_ERR_PKG_NOT_FOUND, - PM_ERR_PKG_IGNORED, - PM_ERR_PKG_INVALID, - PM_ERR_PKG_OPEN, - PM_ERR_PKG_CANT_REMOVE, - PM_ERR_PKG_INVALID_NAME, - PM_ERR_PKG_INVALID_ARCH, - PM_ERR_PKG_REPO_NOT_FOUND, + ALPM_ERR_PKG_NOT_FOUND, + ALPM_ERR_PKG_IGNORED, + ALPM_ERR_PKG_INVALID, + ALPM_ERR_PKG_INVALID_SIG, + ALPM_ERR_PKG_OPEN, + ALPM_ERR_PKG_CANT_REMOVE, + ALPM_ERR_PKG_INVALID_NAME, + ALPM_ERR_PKG_INVALID_ARCH, + ALPM_ERR_PKG_REPO_NOT_FOUND, + /* Signatures */ + ALPM_ERR_SIG_MISSING, + ALPM_ERR_SIG_INVALID, /* Deltas */ - PM_ERR_DLT_INVALID, - PM_ERR_DLT_PATCHFAILED, + ALPM_ERR_DLT_INVALID, + ALPM_ERR_DLT_PATCHFAILED, /* Dependencies */ - PM_ERR_UNSATISFIED_DEPS, - PM_ERR_CONFLICTING_DEPS, - PM_ERR_FILE_CONFLICTS, + ALPM_ERR_UNSATISFIED_DEPS, + ALPM_ERR_CONFLICTING_DEPS, + ALPM_ERR_FILE_CONFLICTS, /* Misc */ - PM_ERR_RETRIEVE, - PM_ERR_WRITE, - PM_ERR_INVALID_REGEX, + ALPM_ERR_RETRIEVE, + ALPM_ERR_INVALID_REGEX, /* External library errors */ - PM_ERR_LIBARCHIVE, - PM_ERR_LIBFETCH, - PM_ERR_EXTERNAL_DOWNLOAD + ALPM_ERR_LIBARCHIVE, + ALPM_ERR_LIBCURL, + ALPM_ERR_EXTERNAL_DOWNLOAD, + ALPM_ERR_GPGME }; -/** The number of the last error that occurred. */ -extern enum _pmerrno_t pm_errno; +/** Returns the current error code from the handle. */ +enum _alpm_errno_t alpm_errno(alpm_handle_t *handle); /** Returns the string corresponding to an error number. */ -const char *alpm_strerror(int err); - -/** Returns the string corresponding to pm_errno. */ -const char *alpm_strerrorlast(void); +const char *alpm_strerror(enum _alpm_errno_t err); /* End of alpm_api_errors */ /** @} */ +alpm_handle_t *alpm_initialize(const char *root, const char *dbpath, + enum _alpm_errno_t *err); +int alpm_release(alpm_handle_t *handle); +const char *alpm_version(void); + /* End of alpm_api */ /** @} */ diff --git a/lib/libalpm/alpm_list.c b/lib/libalpm/alpm_list.c index 42ef367a..83b9824c 100644 --- a/lib/libalpm/alpm_list.c +++ b/lib/libalpm/alpm_list.c @@ -20,7 +20,6 @@ #include <stdlib.h> #include <string.h> -#include <stdio.h> /* libalpm */ #include "alpm_list.h" @@ -92,7 +91,7 @@ alpm_list_t SYMEXPORT *alpm_list_add(alpm_list_t *list, void *data) ptr = calloc(1, sizeof(alpm_list_t)); if(ptr == NULL) { - return(list); + return list; } ptr->data = data; @@ -101,7 +100,7 @@ alpm_list_t SYMEXPORT *alpm_list_add(alpm_list_t *list, void *data) /* Special case: the input list is empty */ if(list == NULL) { ptr->prev = ptr; - return(ptr); + return ptr; } lp = alpm_list_last(list); @@ -109,7 +108,7 @@ alpm_list_t SYMEXPORT *alpm_list_add(alpm_list_t *list, void *data) ptr->prev = lp; list->prev = ptr; - return(list); + return list; } /** @@ -124,13 +123,13 @@ alpm_list_t SYMEXPORT *alpm_list_add(alpm_list_t *list, void *data) alpm_list_t SYMEXPORT *alpm_list_add_sorted(alpm_list_t *list, void *data, alpm_list_fn_cmp fn) { if(!fn || !list) { - return(alpm_list_add(list, data)); + return alpm_list_add(list, data); } else { alpm_list_t *add = NULL, *prev = NULL, *next = list; add = calloc(1, sizeof(alpm_list_t)); if(add == NULL) { - return(list); + return list; } add->data = data; @@ -146,19 +145,19 @@ alpm_list_t SYMEXPORT *alpm_list_add_sorted(alpm_list_t *list, void *data, alpm_ add->prev = list->prev; /* list != NULL */ add->next = list; list->prev = add; - return(add); + return add; } else if(next == NULL) { /* another special case: add last element */ add->prev = prev; add->next = NULL; prev->next = add; list->prev = add; - return(list); + return list; } else { add->prev = prev; add->next = next; next->prev = add; prev->next = add; - return(list); + return list; } } } @@ -178,11 +177,11 @@ alpm_list_t SYMEXPORT *alpm_list_join(alpm_list_t *first, alpm_list_t *second) { alpm_list_t *tmp; - if (first == NULL) { - return(second); + if(first == NULL) { + return second; } - if (second == NULL) { - return(first); + if(second == NULL) { + return first; } /* tmp is the last element of the first list */ tmp = first->prev; @@ -193,7 +192,7 @@ alpm_list_t SYMEXPORT *alpm_list_join(alpm_list_t *first, alpm_list_t *second) /* set the back reference to the tail */ second->prev = tmp; - return(first); + return first; } /** @@ -209,12 +208,12 @@ alpm_list_t SYMEXPORT *alpm_list_mmerge(alpm_list_t *left, alpm_list_t *right, a { alpm_list_t *newlist, *lp; - if (left == NULL) + if(left == NULL) return right; - if (right == NULL) + if(right == NULL) return left; - if (fn(left->data, right->data) <= 0) { + if(fn(left->data, right->data) <= 0) { newlist = left; left = left->next; } @@ -226,8 +225,8 @@ alpm_list_t SYMEXPORT *alpm_list_mmerge(alpm_list_t *left, alpm_list_t *right, a newlist->next = NULL; lp = newlist; - while ((left != NULL) && (right != NULL)) { - if (fn(left->data, right->data) <= 0) { + while((left != NULL) && (right != NULL)) { + if(fn(left->data, right->data) <= 0) { lp->next = left; left->prev = lp; left = left->next; @@ -240,11 +239,11 @@ alpm_list_t SYMEXPORT *alpm_list_mmerge(alpm_list_t *left, alpm_list_t *right, a lp = lp->next; lp->next = NULL; } - if (left != NULL) { + if(left != NULL) { lp->next = left; left->prev = lp; } - else if (right != NULL) { + else if(right != NULL) { lp->next = right; right->prev = lp; } @@ -257,7 +256,7 @@ alpm_list_t SYMEXPORT *alpm_list_mmerge(alpm_list_t *left, alpm_list_t *right, a } newlist->prev = lp; - return(newlist); + return newlist; } /** @@ -271,7 +270,7 @@ alpm_list_t SYMEXPORT *alpm_list_mmerge(alpm_list_t *left, alpm_list_t *right, a */ alpm_list_t SYMEXPORT *alpm_list_msort(alpm_list_t *list, size_t n, alpm_list_fn_cmp fn) { - if (n > 1) { + if(n > 1) { alpm_list_t *left = list; alpm_list_t *lastleft = alpm_list_nth(list, n/2 - 1); alpm_list_t *right = lastleft->next; @@ -282,7 +281,7 @@ alpm_list_t SYMEXPORT *alpm_list_msort(alpm_list_t *list, size_t n, alpm_list_fn right = alpm_list_msort(right, n - (n/2), fn); list = alpm_list_mmerge(left, right, fn); } - return(list); + return list; } /** @@ -298,7 +297,7 @@ alpm_list_t SYMEXPORT *alpm_list_remove_item(alpm_list_t *haystack, alpm_list_t *item) { if(haystack == NULL || item == NULL) { - return(haystack); + return haystack; } if(item == haystack) { @@ -328,7 +327,7 @@ alpm_list_t SYMEXPORT *alpm_list_remove_item(alpm_list_t *haystack, } } - return(haystack); + return haystack; } @@ -352,7 +351,7 @@ alpm_list_t SYMEXPORT *alpm_list_remove(alpm_list_t *haystack, } if(needle == NULL) { - return(haystack); + return haystack; } while(i) { @@ -373,7 +372,7 @@ alpm_list_t SYMEXPORT *alpm_list_remove(alpm_list_t *haystack, } } - return(haystack); + return haystack; } /** @@ -388,8 +387,8 @@ alpm_list_t SYMEXPORT *alpm_list_remove(alpm_list_t *haystack, alpm_list_t SYMEXPORT *alpm_list_remove_str(alpm_list_t *haystack, const char *needle, char **data) { - return(alpm_list_remove(haystack, (const void *)needle, - (alpm_list_fn_cmp)strcmp, (void **)data)); + return alpm_list_remove(haystack, (const void *)needle, + (alpm_list_fn_cmp)strcmp, (void **)data); } /** @@ -411,7 +410,7 @@ alpm_list_t SYMEXPORT *alpm_list_remove_dupes(const alpm_list_t *list) } lp = lp->next; } - return(newlist); + return newlist; } /** @@ -429,7 +428,7 @@ alpm_list_t SYMEXPORT *alpm_list_strdup(const alpm_list_t *list) newlist = alpm_list_add(newlist, strdup(lp->data)); lp = lp->next; } - return(newlist); + return newlist; } /** @@ -447,7 +446,7 @@ alpm_list_t SYMEXPORT *alpm_list_copy(const alpm_list_t *list) newlist = alpm_list_add(newlist, lp->data); lp = lp->next; } - return(newlist); + return newlist; } /** @@ -473,7 +472,7 @@ alpm_list_t SYMEXPORT *alpm_list_copy_data(const alpm_list_t *list, lp = lp->next; } } - return(newlist); + return newlist; } /** @@ -489,7 +488,7 @@ alpm_list_t SYMEXPORT *alpm_list_reverse(alpm_list_t *list) alpm_list_t *newlist = NULL, *backup; if(list == NULL) { - return(NULL); + return NULL; } lp = alpm_list_last(list); @@ -502,28 +501,12 @@ alpm_list_t SYMEXPORT *alpm_list_reverse(alpm_list_t *list) lp = lp->prev; } list->prev = backup; /* restore tail pointer */ - return(newlist); + return newlist; } /* Accessors */ /** - * @brief Get the first element of a list. - * - * @param list the list - * - * @return the first element in the list - */ -inline alpm_list_t SYMEXPORT *alpm_list_first(const alpm_list_t *list) -{ - if(list) { - return((alpm_list_t*)list); - } else { - return(NULL); - } -} - -/** * @brief Return nth element from list (starting from 0). * * @param list the list @@ -537,7 +520,7 @@ alpm_list_t SYMEXPORT *alpm_list_nth(const alpm_list_t *list, size_t n) while(n--) { i = i->next; } - return((alpm_list_t*)i); + return (alpm_list_t *)i; } /** @@ -550,9 +533,26 @@ alpm_list_t SYMEXPORT *alpm_list_nth(const alpm_list_t *list, size_t n) inline alpm_list_t SYMEXPORT *alpm_list_next(const alpm_list_t *node) { if(node) { - return(node->next); + return node->next; } else { - return(NULL); + return NULL; + } +} + +/** + * @brief Get the previous element of a list. + * + * @param list the list head + * @param node the list node + * + * @return the previous element, or NULL when no previous element exist + */ +inline alpm_list_t SYMEXPORT *alpm_list_previous(const alpm_list_t *list) +{ + if(list && list->prev->next) { + return list->prev; + } else { + return NULL; } } @@ -566,9 +566,9 @@ inline alpm_list_t SYMEXPORT *alpm_list_next(const alpm_list_t *node) alpm_list_t SYMEXPORT *alpm_list_last(const alpm_list_t *list) { if(list) { - return(list->prev); + return list->prev; } else { - return(NULL); + return NULL; } } @@ -581,8 +581,8 @@ alpm_list_t SYMEXPORT *alpm_list_last(const alpm_list_t *list) */ void SYMEXPORT *alpm_list_getdata(const alpm_list_t *node) { - if(node == NULL) return(NULL); - return(node->data); + if(node == NULL) return NULL; + return node->data; } /* Misc */ @@ -602,7 +602,7 @@ size_t SYMEXPORT alpm_list_count(const alpm_list_t *list) ++i; lp = lp->next; } - return(i); + return i; } /** @@ -620,17 +620,17 @@ void SYMEXPORT *alpm_list_find(const alpm_list_t *haystack, const void *needle, const alpm_list_t *lp = haystack; while(lp) { if(lp->data && fn(lp->data, needle) == 0) { - return(lp->data); + return lp->data; } lp = lp->next; } - return(NULL); + return NULL; } /* trivial helper function for alpm_list_find_ptr */ static int ptr_cmp(const void *p, const void *q) { - return(p != q); + return (p != q); } /** @@ -643,9 +643,10 @@ static int ptr_cmp(const void *p, const void *q) * * @return `needle` if found, NULL otherwise */ -void SYMEXPORT *alpm_list_find_ptr(const alpm_list_t *haystack, const void *needle) +void SYMEXPORT *alpm_list_find_ptr(const alpm_list_t *haystack, + const void *needle) { - return(alpm_list_find(haystack, needle, ptr_cmp)); + return alpm_list_find(haystack, needle, ptr_cmp); } /** @@ -659,8 +660,8 @@ void SYMEXPORT *alpm_list_find_ptr(const alpm_list_t *haystack, const void *need char SYMEXPORT *alpm_list_find_str(const alpm_list_t *haystack, const char *needle) { - return((char *)alpm_list_find(haystack, (const void*)needle, - (alpm_list_fn_cmp)strcmp)); + return (char *)alpm_list_find(haystack, (const void *)needle, + (alpm_list_fn_cmp)strcmp); } /** @@ -688,7 +689,7 @@ void SYMEXPORT alpm_list_diff_sorted(const alpm_list_t *left, return; } - while (l != NULL && r != NULL) { + while(l != NULL && r != NULL) { int cmp = fn(l->data, r->data); if(cmp < 0) { if(onlyleft) { @@ -706,13 +707,13 @@ void SYMEXPORT alpm_list_diff_sorted(const alpm_list_t *left, r = r->next; } } - while (l != NULL) { + while(l != NULL) { if(onlyleft) { *onlyleft = alpm_list_add(*onlyleft, l->data); } l = l->next; } - while (r != NULL) { + while(r != NULL) { if(onlyright) { *onlyright = alpm_list_add(*onlyright, r->data); } @@ -745,7 +746,39 @@ alpm_list_t SYMEXPORT *alpm_list_diff(const alpm_list_t *lhs, alpm_list_free(left); alpm_list_free(right); - return(ret); + return ret; +} + +/** + * @brief Copy a list and data into a standard C array of fixed length. + * Note that the data elements are shallow copied so any contained pointers + * will point to the original data. + * + * @param list the list to copy + * @param n the size of the list + * @param size the size of each data element + * + * @return an array version of the original list, data copied as well + */ +void SYMEXPORT *alpm_list_to_array(const alpm_list_t *list, size_t n, + size_t size) +{ + size_t i; + const alpm_list_t *item; + char *array; + + if(n == 0) { + return NULL; + } + + array = calloc(n, size); + if(array == NULL) { + return NULL; + } + for(i = 0, item = list; i < n && item; i++, item = item->next) { + memcpy(array + i * size, item->data, size); + } + return array; } /** @} */ diff --git a/lib/libalpm/alpm_list.h b/lib/libalpm/alpm_list.h index 1f6393a6..cd7b0291 100644 --- a/lib/libalpm/alpm_list.h +++ b/lib/libalpm/alpm_list.h @@ -67,9 +67,9 @@ alpm_list_t *alpm_list_copy_data(const alpm_list_t *list, size_t size); alpm_list_t *alpm_list_reverse(alpm_list_t *list); /* item accessors */ -alpm_list_t *alpm_list_first(const alpm_list_t *list); alpm_list_t *alpm_list_nth(const alpm_list_t *list, size_t n); alpm_list_t *alpm_list_next(const alpm_list_t *list); +alpm_list_t *alpm_list_previous(const alpm_list_t *list); alpm_list_t *alpm_list_last(const alpm_list_t *list); void *alpm_list_getdata(const alpm_list_t *entry); @@ -81,6 +81,7 @@ char *alpm_list_find_str(const alpm_list_t *haystack, const char *needle); alpm_list_t *alpm_list_diff(const alpm_list_t *lhs, const alpm_list_t *rhs, alpm_list_fn_cmp fn); void alpm_list_diff_sorted(const alpm_list_t *left, const alpm_list_t *right, alpm_list_fn_cmp fn, alpm_list_t **onlyleft, alpm_list_t **onlyright); +void *alpm_list_to_array(const alpm_list_t *list, size_t n, size_t size); #ifdef __cplusplus } diff --git a/lib/libalpm/backup.c b/lib/libalpm/backup.c index ca955ca4..728c1d05 100644 --- a/lib/libalpm/backup.c +++ b/lib/libalpm/backup.c @@ -32,82 +32,67 @@ #include "log.h" #include "util.h" -/* split a backup string "file\thash" into two strings : file and hash */ -static int backup_split(const char *string, char **file, char **hash) +/* split a backup string "file\thash" into the relevant components */ +int _alpm_split_backup(const char *string, alpm_backup_t **backup) { - char *str = strdup(string); - char *ptr; + char *str, *ptr; + + STRDUP(str, string, return -1); /* tab delimiter */ - ptr = strchr(str, '\t'); + ptr = str ? strchr(str, '\t') : NULL; if(ptr == NULL) { - if(file) { - *file = str; - } else { - /* don't need our dup as the fname wasn't requested, so free it */ - FREE(str); - } - return(0); + (*backup)->name = str; + (*backup)->hash = NULL; + return 0; } *ptr = '\0'; ptr++; /* now str points to the filename and ptr points to the hash */ - if(file) { - *file = strdup(str); - } - if(hash) { - *hash = strdup(ptr); - } + STRDUP((*backup)->name, str, return -1); + STRDUP((*backup)->hash, ptr, return -1); FREE(str); - return(1); -} - -char *_alpm_backup_file(const char *string) -{ - char *file = NULL; - backup_split(string, &file, NULL); - return(file); -} - -char *_alpm_backup_hash(const char *string) -{ - char *hash = NULL; - backup_split(string, NULL, &hash); - return(hash); + return 0; } -/* Look for a filename in a pmpkg_t.backup list. If we find it, - * then we return the md5 hash (parsed from the same line) +/* Look for a filename in a alpm_pkg_t.backup list. If we find it, + * then we return the full backup entry. */ -char *_alpm_needbackup(const char *file, const alpm_list_t *backup) +alpm_backup_t *_alpm_needbackup(const char *file, alpm_pkg_t *pkg) { const alpm_list_t *lp; - ALPM_LOG_FUNC; - - if(file == NULL || backup == NULL) { - return(NULL); + if(file == NULL || pkg == NULL) { + return NULL; } - /* run through the backup list and parse out the hash for our file */ - for(lp = backup; lp; lp = lp->next) { - char *filename = NULL; - char *hash = NULL; + for(lp = alpm_pkg_get_backup(pkg); lp; lp = lp->next) { + alpm_backup_t *backup = lp->data; - /* no hash found */ - if(!backup_split((char *)lp->data, &filename, &hash)) { - FREE(filename); - continue; - } - if(strcmp(file, filename) == 0) { - FREE(filename); - return(hash); + if(strcmp(file, backup->name) == 0) { + return backup; } - FREE(filename); - FREE(hash); } - return(NULL); + return NULL; +} + +void _alpm_backup_free(alpm_backup_t *backup) +{ + free(backup->name); + free(backup->hash); + free(backup); +} + +alpm_backup_t *_alpm_backup_dup(const alpm_backup_t *backup) +{ + alpm_backup_t *newbackup; + CALLOC(newbackup, 1, sizeof(alpm_backup_t), return NULL); + + STRDUP(newbackup->name, backup->name, return NULL); + STRDUP(newbackup->hash, backup->hash, return NULL); + + return newbackup; } /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/backup.h b/lib/libalpm/backup.h index 9475aa2a..0b84a68c 100644 --- a/lib/libalpm/backup.h +++ b/lib/libalpm/backup.h @@ -21,10 +21,12 @@ #define _ALPM_BACKUP_H #include "alpm_list.h" +#include "alpm.h" -char *_alpm_backup_file(const char *string); -char *_alpm_backup_hash(const char *string); -char *_alpm_needbackup(const char *file, const alpm_list_t *backup); +int _alpm_split_backup(const char *string, alpm_backup_t **backup); +alpm_backup_t *_alpm_needbackup(const char *file, alpm_pkg_t *pkg); +void _alpm_backup_free(alpm_backup_t *backup); +alpm_backup_t *_alpm_backup_dup(const alpm_backup_t *backup); #endif /* _ALPM_BACKUP_H */ diff --git a/lib/libalpm/base64.c b/lib/libalpm/base64.c new file mode 100644 index 00000000..fa8bec5c --- /dev/null +++ b/lib/libalpm/base64.c @@ -0,0 +1,190 @@ +/* + * RFC 1521 base64 encoding/decoding + * + * Copyright (C) 2006-2010, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org> + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +/* + * Pacman Notes: + * + * Taken from the PolarSSL project at www.polarssl.org under terms of the + * GPL. This is from version 0.14.2 of the library, and has been modified + * as following, which may be helpful for future updates: + * * remove "polarssl/config.h" include + * * change include from "polarssl/base64.h" to "base64.h" + * * removal of SELF_TEST code + */ + +#include "base64.h" + +static const unsigned char base64_enc_map[64] = +{ + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', '+', '/' +}; + +static const unsigned char base64_dec_map[128] = +{ + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 62, 127, 127, 127, 63, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 127, 127, + 127, 64, 127, 127, 127, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 127, 127, 127, 127, 127, 127, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 127, 127, 127, 127, 127 +}; + +/* + * Encode a buffer into base64 format + */ +int base64_encode( unsigned char *dst, int *dlen, + const unsigned char *src, int slen ) +{ + int i, n; + int C1, C2, C3; + unsigned char *p; + + if( slen == 0 ) + return( 0 ); + + n = (slen << 3) / 6; + + switch( (slen << 3) - (n * 6) ) + { + case 2: n += 3; break; + case 4: n += 2; break; + default: break; + } + + if( *dlen < n + 1 ) + { + *dlen = n + 1; + return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + n = (slen / 3) * 3; + + for( i = 0, p = dst; i < n; i += 3 ) + { + C1 = *src++; + C2 = *src++; + C3 = *src++; + + *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; + *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; + *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F]; + *p++ = base64_enc_map[C3 & 0x3F]; + } + + if( i < slen ) + { + C1 = *src++; + C2 = ((i + 1) < slen) ? *src++ : 0; + + *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; + *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; + + if( (i + 1) < slen ) + *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F]; + else *p++ = '='; + + *p++ = '='; + } + + *dlen = p - dst; + *p = 0; + + return( 0 ); +} + +/* + * Decode a base64-formatted buffer + */ +int base64_decode( unsigned char *dst, int *dlen, + const unsigned char *src, int slen ) +{ + int i, j, n; + unsigned long x; + unsigned char *p; + + for( i = j = n = 0; i < slen; i++ ) + { + if( ( slen - i ) >= 2 && + src[i] == '\r' && src[i + 1] == '\n' ) + continue; + + if( src[i] == '\n' ) + continue; + + if( src[i] == '=' && ++j > 2 ) + return( POLARSSL_ERR_BASE64_INVALID_CHARACTER ); + + if( src[i] > 127 || base64_dec_map[src[i]] == 127 ) + return( POLARSSL_ERR_BASE64_INVALID_CHARACTER ); + + if( base64_dec_map[src[i]] < 64 && j != 0 ) + return( POLARSSL_ERR_BASE64_INVALID_CHARACTER ); + + n++; + } + + if( n == 0 ) + return( 0 ); + + n = ((n * 6) + 7) >> 3; + + if( *dlen < n ) + { + *dlen = n; + return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ ) + { + if( *src == '\r' || *src == '\n' ) + continue; + + j -= ( base64_dec_map[*src] == 64 ); + x = (x << 6) | ( base64_dec_map[*src] & 0x3F ); + + if( ++n == 4 ) + { + n = 0; + if( j > 0 ) *p++ = (unsigned char)( x >> 16 ); + if( j > 1 ) *p++ = (unsigned char)( x >> 8 ); + if( j > 2 ) *p++ = (unsigned char)( x ); + } + } + + *dlen = p - dst; + + return( 0 ); +} diff --git a/lib/libalpm/base64.h b/lib/libalpm/base64.h new file mode 100644 index 00000000..0ae9612c --- /dev/null +++ b/lib/libalpm/base64.h @@ -0,0 +1,68 @@ +/** + * \file base64.h + * + * Copyright (C) 2006-2010, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org> + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _BASE64_H +#define _BASE64_H + +#define POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL 0x0010 +#define POLARSSL_ERR_BASE64_INVALID_CHARACTER 0x0012 + +/** + * \brief Encode a buffer into base64 format + * + * \param dst destination buffer + * \param dlen size of the buffer + * \param src source buffer + * \param slen amount of data to be encoded + * + * \return 0 if successful, or POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL. + * *dlen is always updated to reflect the amount + * of data that has (or would have) been written. + * + * \note Call this function with *dlen = 0 to obtain the + * required buffer size in *dlen + */ +int base64_encode( unsigned char *dst, int *dlen, + const unsigned char *src, int slen ); + +/** + * \brief Decode a base64-formatted buffer + * + * \param dst destination buffer + * \param dlen size of the buffer + * \param src source buffer + * \param slen amount of data to be decoded + * + * \return 0 if successful, POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL, or + * POLARSSL_ERR_BASE64_INVALID_DATA if the input data is not + * correct. *dlen is always updated to reflect the amount + * of data that has (or would have) been written. + * + * \note Call this function with *dlen = 0 to obtain the + * required buffer size in *dlen + */ +int base64_decode( unsigned char *dst, int *dlen, + const unsigned char *src, int slen ); + +#endif /* base64.h */ 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: */ diff --git a/lib/libalpm/be_package.c b/lib/libalpm/be_package.c index 6dfddd61..f80790cd 100644 --- a/lib/libalpm/be_package.c +++ b/lib/libalpm/be_package.c @@ -1,5 +1,5 @@ /* - * be_package.c + * be_package.c : backend for packages * * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> @@ -20,10 +20,8 @@ #include "config.h" -#include <stdio.h> #include <stdlib.h> #include <string.h> -#include <limits.h> #include <errno.h> /* libarchive */ @@ -32,8 +30,10 @@ /* libalpm */ #include "alpm_list.h" +#include "alpm.h" #include "util.h" #include "log.h" +#include "handle.h" #include "package.h" #include "deps.h" /* _alpm_splitdep */ @@ -43,40 +43,38 @@ * @param pkg the package (file) to read the changelog * @return a 'file stream' to the package changelog */ -static void *_package_changelog_open(pmpkg_t *pkg) +static void *_package_changelog_open(alpm_pkg_t *pkg) { - ALPM_LOG_FUNC; - - ASSERT(pkg != NULL, return(NULL)); + ASSERT(pkg != NULL, return NULL); struct archive *archive = NULL; struct archive_entry *entry; const char *pkgfile = pkg->origin_data.file; if((archive = archive_read_new()) == NULL) { - RET_ERR(PM_ERR_LIBARCHIVE, NULL); + RET_ERR(pkg->handle, ALPM_ERR_LIBARCHIVE, NULL); } archive_read_support_compression_all(archive); archive_read_support_format_all(archive); - if (archive_read_open_filename(archive, pkgfile, + if(archive_read_open_filename(archive, pkgfile, ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) { - RET_ERR(PM_ERR_PKG_OPEN, NULL); + RET_ERR(pkg->handle, ALPM_ERR_PKG_OPEN, NULL); } while(archive_read_next_header(archive, &entry) == ARCHIVE_OK) { const char *entry_name = archive_entry_pathname(entry); if(strcmp(entry_name, ".CHANGELOG") == 0) { - return(archive); + return archive; } } /* we didn't find a changelog */ archive_read_finish(archive); errno = ENOENT; - return(NULL); + return NULL; } /** @@ -89,26 +87,17 @@ static void *_package_changelog_open(pmpkg_t *pkg) * @return the number of characters read, or 0 if there is no more data */ static size_t _package_changelog_read(void *ptr, size_t size, - const pmpkg_t *pkg, const void *fp) + const alpm_pkg_t UNUSED *pkg, const void *fp) { - ssize_t sret = archive_read_data((struct archive*)fp, ptr, size); + ssize_t sret = archive_read_data((struct archive *)fp, ptr, size); /* Report error (negative values) */ if(sret < 0) { - pm_errno = PM_ERR_LIBARCHIVE; - return(0); + RET_ERR(pkg->handle, ALPM_ERR_LIBARCHIVE, 0); } else { - return((size_t)sret); + return (size_t)sret; } } -/* -static int _package_changelog_feof(const pmpkg_t *pkg, void *fp) -{ - // note: this doesn't quite work, no feof in libarchive - return( archive_read_data((struct archive*)fp, NULL, 0) ); -} -*/ - /** * Close a package changelog for reading. Similar to fclose in functionality, * except that the 'file stream' is from an archive. @@ -116,9 +105,9 @@ static int _package_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 _package_changelog_close(const pmpkg_t *pkg, void *fp) +static int _package_changelog_close(const alpm_pkg_t UNUSED *pkg, void *fp) { - return( archive_read_finish((struct archive *)fp) ); + return archive_read_finish((struct archive *)fp); } /** Package file operations struct accessor. We implement this as a method @@ -137,72 +126,70 @@ static struct pkg_operations *get_file_pkg_ops(void) file_pkg_ops.changelog_close = _package_changelog_close; file_pkg_ops_initialized = 1; } - return(&file_pkg_ops); + return &file_pkg_ops; } /** - * Parses the package description file for a package into a pmpkg_t struct. + * Parses the package description file for a package into a alpm_pkg_t struct. * @param archive the archive to read from, pointed at the .PKGINFO entry - * @param newpkg an empty pmpkg_t struct to fill with package info + * @param newpkg an empty alpm_pkg_t struct to fill with package info * - * @return 0 on success, 1 on error + * @return 0 on success, -1 on error */ -static int parse_descfile(struct archive *a, pmpkg_t *newpkg) +static int parse_descfile(alpm_handle_t *handle, struct archive *a, alpm_pkg_t *newpkg) { char *ptr = NULL; char *key = NULL; - int linenum = 0; + int ret, linenum = 0; struct archive_read_buffer buf; - ALPM_LOG_FUNC; - memset(&buf, 0, sizeof(buf)); /* 512K for a line length seems reasonable */ buf.max_line_size = 512 * 1024; /* loop until we reach EOF or other error */ - while(_alpm_archive_fgets(a, &buf) == ARCHIVE_OK) { - char *line = _alpm_strtrim(buf.line); + while((ret = _alpm_archive_fgets(a, &buf)) == ARCHIVE_OK) { + size_t len = _alpm_strip_newline(buf.line); linenum++; - if(strlen(line) == 0 || line[0] == '#') { + if(len == 0 || buf.line[0] == '#') { continue; } - ptr = line; + ptr = buf.line; key = strsep(&ptr, "="); if(key == NULL || ptr == NULL) { - _alpm_log(PM_LOG_DEBUG, "%s: syntax error in description file line %d\n", + _alpm_log(handle, ALPM_LOG_DEBUG, "%s: syntax error in description file line %d\n", newpkg->name ? newpkg->name : "error", linenum); } else { key = _alpm_strtrim(key); while(*ptr == ' ') ptr++; ptr = _alpm_strtrim(ptr); if(strcmp(key, "pkgname") == 0) { - STRDUP(newpkg->name, ptr, RET_ERR(PM_ERR_MEMORY, -1)); + STRDUP(newpkg->name, ptr, return -1); newpkg->name_hash = _alpm_hash_sdbm(newpkg->name); } else if(strcmp(key, "pkgbase") == 0) { /* not used atm */ } else if(strcmp(key, "pkgver") == 0) { - STRDUP(newpkg->version, ptr, RET_ERR(PM_ERR_MEMORY, -1)); + STRDUP(newpkg->version, ptr, return -1); } else if(strcmp(key, "pkgdesc") == 0) { - STRDUP(newpkg->desc, ptr, RET_ERR(PM_ERR_MEMORY, -1)); + STRDUP(newpkg->desc, ptr, return -1); } else if(strcmp(key, "group") == 0) { newpkg->groups = alpm_list_add(newpkg->groups, strdup(ptr)); } else if(strcmp(key, "url") == 0) { - STRDUP(newpkg->url, ptr, RET_ERR(PM_ERR_MEMORY, -1)); + STRDUP(newpkg->url, ptr, return -1); } else if(strcmp(key, "license") == 0) { newpkg->licenses = alpm_list_add(newpkg->licenses, strdup(ptr)); } else if(strcmp(key, "builddate") == 0) { newpkg->builddate = _alpm_parsedate(ptr); } else if(strcmp(key, "packager") == 0) { - STRDUP(newpkg->packager, ptr, RET_ERR(PM_ERR_MEMORY, -1)); + STRDUP(newpkg->packager, ptr, return -1); } else if(strcmp(key, "arch") == 0) { - STRDUP(newpkg->arch, ptr, RET_ERR(PM_ERR_MEMORY, -1)); + STRDUP(newpkg->arch, ptr, return -1); } else if(strcmp(key, "size") == 0) { /* size in the raw package is uncompressed (installed) size */ newpkg->isize = atol(ptr); } else if(strcmp(key, "depend") == 0) { - pmdepend_t *dep = _alpm_splitdep(ptr); + alpm_depend_t *dep = _alpm_splitdep(ptr); newpkg->depends = alpm_list_add(newpkg->depends, dep); } else if(strcmp(key, "optdepend") == 0) { newpkg->optdepends = alpm_list_add(newpkg->optdepends, strdup(ptr)); @@ -213,70 +200,148 @@ static int parse_descfile(struct archive *a, pmpkg_t *newpkg) } else if(strcmp(key, "provides") == 0) { newpkg->provides = alpm_list_add(newpkg->provides, strdup(ptr)); } else if(strcmp(key, "backup") == 0) { - newpkg->backup = alpm_list_add(newpkg->backup, strdup(ptr)); + alpm_backup_t *backup; + CALLOC(backup, 1, sizeof(alpm_backup_t), return -1); + STRDUP(backup->name, ptr, return -1); + newpkg->backup = alpm_list_add(newpkg->backup, backup); } else if(strcmp(key, "force") == 0) { /* deprecated, skip it */ } else if(strcmp(key, "makepkgopt") == 0) { /* not used atm */ } else { - _alpm_log(PM_LOG_DEBUG, "%s: unknown key '%s' in description file line %d\n", + _alpm_log(handle, ALPM_LOG_DEBUG, "%s: unknown key '%s' in description file line %d\n", newpkg->name ? newpkg->name : "error", key, linenum); } } - line[0] = '\0'; } + if(ret != ARCHIVE_EOF) { + _alpm_log(handle, ALPM_LOG_DEBUG, "error parsing package descfile\n"); + return -1; + } + + return 0; +} + +static void files_merge(alpm_file_t a[], alpm_file_t b[], alpm_file_t c[], + size_t m, size_t n) +{ + size_t i = 0, j = 0, k = 0; + while(i < m && j < n) { + if(strcmp(a[i].name, b[j].name) < 0) { + c[k++] = a[i++]; + } else { + c[k++] = b[j++]; + } + } + while(i < m) { + c[k++] = a[i++]; + } + while(j < n) { + c[k++] = b[j++]; + } +} - return(0); +static alpm_file_t *files_msort(alpm_file_t *files, size_t n) +{ + alpm_file_t *work; + size_t blocksize = 1; + + CALLOC(work, n, sizeof(alpm_file_t), return NULL); + + for(blocksize = 1; blocksize < n; blocksize *= 2) { + size_t i, max_extent = 0; + for(i = 0; i < n - blocksize; i += 2 * blocksize) { + /* this limits our actual merge to the length of the array, since we will + * not likely be a perfect power of two. */ + size_t right_blocksize = blocksize; + if(i + blocksize * 2 > n) { + right_blocksize = n - i - blocksize; + } + files_merge(files + i, files + i + blocksize, work + i, + blocksize, right_blocksize); + max_extent = i + blocksize + right_blocksize; + } + /* ensure we only copy what we actually touched on this merge pass, + * no more, no less */ + memcpy(files, work, max_extent * sizeof(alpm_file_t)); + } + free(work); + return files; } /** - * Load a package and create the corresponding pmpkg_t struct. + * Load a package and create the corresponding alpm_pkg_t struct. + * @param handle the context handle * @param pkgfile path to the package file * @param full whether to stop the load after metadata is read or continue * through the full archive - * @return An information filled pmpkg_t struct + * @return An information filled alpm_pkg_t struct */ -static pmpkg_t *pkg_load(const char *pkgfile, int full) +alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle, const char *pkgfile, + int full, const char *md5sum, const char *base64_sig, + alpm_siglevel_t level) { - int ret = ARCHIVE_OK; + int ret; int config = 0; struct archive *archive; struct archive_entry *entry; - pmpkg_t *newpkg = NULL; + alpm_pkg_t *newpkg = NULL; struct stat st; - - ALPM_LOG_FUNC; + size_t files_count = 0, files_size = 0; + alpm_file_t *files = NULL; if(pkgfile == NULL || strlen(pkgfile) == 0) { - RET_ERR(PM_ERR_WRONG_ARGS, NULL); + RET_ERR(handle, ALPM_ERR_WRONG_ARGS, NULL); } - if(stat(pkgfile, &st) != 0) { - RET_ERR(PM_ERR_PKG_OPEN, NULL); + /* attempt to stat the package file, ensure it exists */ + if(stat(pkgfile, &st) == 0) { + newpkg = _alpm_pkg_new(); + if(newpkg == NULL) { + RET_ERR(handle, ALPM_ERR_MEMORY, NULL); + } + newpkg->filename = strdup(pkgfile); + newpkg->size = st.st_size; + } else { + /* couldn't stat the pkgfile, return an error */ + RET_ERR(handle, ALPM_ERR_PKG_OPEN, NULL); } + /* first steps- validate the package file */ + _alpm_log(handle, ALPM_LOG_DEBUG, "md5sum: %s\n", md5sum); + if(md5sum) { + _alpm_log(handle, ALPM_LOG_DEBUG, "checking md5sum for %s\n", pkgfile); + if(_alpm_test_md5sum(pkgfile, md5sum) != 0) { + alpm_pkg_free(newpkg); + RET_ERR(handle, ALPM_ERR_PKG_INVALID, NULL); + } + } + + _alpm_log(handle, ALPM_LOG_DEBUG, "base64_sig: %s\n", base64_sig); + if(level & ALPM_SIG_PACKAGE && + _alpm_check_pgp_helper(handle, pkgfile, base64_sig, + level & ALPM_SIG_PACKAGE_OPTIONAL, level & ALPM_SIG_PACKAGE_MARGINAL_OK, + level & ALPM_SIG_PACKAGE_UNKNOWN_OK, ALPM_ERR_PKG_INVALID_SIG)) { + _alpm_pkg_free(newpkg); + return NULL; + } + + /* next- try to create an archive object to read in the package */ if((archive = archive_read_new()) == NULL) { - RET_ERR(PM_ERR_LIBARCHIVE, NULL); + alpm_pkg_free(newpkg); + RET_ERR(handle, ALPM_ERR_LIBARCHIVE, NULL); } archive_read_support_compression_all(archive); archive_read_support_format_all(archive); - if (archive_read_open_filename(archive, pkgfile, + if(archive_read_open_filename(archive, pkgfile, ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) { - RET_ERR(PM_ERR_PKG_OPEN, NULL); - } - - newpkg = _alpm_pkg_new(); - if(newpkg == NULL) { - archive_read_finish(archive); - RET_ERR(PM_ERR_MEMORY, NULL); + alpm_pkg_free(newpkg); + RET_ERR(handle, ALPM_ERR_PKG_OPEN, NULL); } - newpkg->filename = strdup(pkgfile); - newpkg->size = st.st_size; - - _alpm_log(PM_LOG_DEBUG, "starting package load for %s\n", pkgfile); + _alpm_log(handle, ALPM_LOG_DEBUG, "starting package load for %s\n", pkgfile); /* If full is false, only read through the archive until we find our needed * metadata. If it is true, read through the entire archive, which serves @@ -286,17 +351,17 @@ static pmpkg_t *pkg_load(const char *pkgfile, int full) if(strcmp(entry_name, ".PKGINFO") == 0) { /* parse the info file */ - if(parse_descfile(archive, newpkg) != 0) { - _alpm_log(PM_LOG_ERROR, _("could not parse package description file in %s\n"), + if(parse_descfile(handle, archive, newpkg) != 0) { + _alpm_log(handle, ALPM_LOG_ERROR, _("could not parse package description file in %s\n"), pkgfile); goto pkg_invalid; } if(newpkg->name == NULL || strlen(newpkg->name) == 0) { - _alpm_log(PM_LOG_ERROR, _("missing package name in %s\n"), pkgfile); + _alpm_log(handle, ALPM_LOG_ERROR, _("missing package name in %s\n"), pkgfile); goto pkg_invalid; } if(newpkg->version == NULL || strlen(newpkg->version) == 0) { - _alpm_log(PM_LOG_ERROR, _("missing package version in %s\n"), pkgfile); + _alpm_log(handle, ALPM_LOG_ERROR, _("missing package version in %s\n"), pkgfile); goto pkg_invalid; } config = 1; @@ -308,13 +373,33 @@ static pmpkg_t *pkg_load(const char *pkgfile, int full) * already been handled (for future possibilities) */ } else if(full) { /* Keep track of all files for filelist generation */ - newpkg->files = alpm_list_add(newpkg->files, strdup(entry_name)); + if(files_count >= files_size) { + size_t old_size = files_size; + if(files_size == 0) { + files_size = 4; + } 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, entry_name, goto error); + files[files_count].size = archive_entry_size(entry); + files[files_count].mode = archive_entry_mode(entry); + files_count++; } if(archive_read_data_skip(archive)) { - _alpm_log(PM_LOG_ERROR, _("error while reading package %s: %s\n"), + _alpm_log(handle, ALPM_LOG_ERROR, _("error while reading package %s: %s\n"), pkgfile, archive_error_string(archive)); - pm_errno = PM_ERR_LIBARCHIVE; + handle->pm_errno = ALPM_ERR_LIBARCHIVE; goto error; } @@ -325,14 +410,14 @@ static pmpkg_t *pkg_load(const char *pkgfile, int full) } if(ret != ARCHIVE_EOF && ret != ARCHIVE_OK) { /* An error occured */ - _alpm_log(PM_LOG_ERROR, _("error while reading package %s: %s\n"), + _alpm_log(handle, ALPM_LOG_ERROR, _("error while reading package %s: %s\n"), pkgfile, archive_error_string(archive)); - pm_errno = PM_ERR_LIBARCHIVE; + handle->pm_errno = ALPM_ERR_LIBARCHIVE; goto error; } if(!config) { - _alpm_log(PM_LOG_ERROR, _("missing package metadata in %s\n"), pkgfile); + _alpm_log(handle, ALPM_LOG_ERROR, _("missing package metadata in %s\n"), pkgfile); goto pkg_invalid; } @@ -340,49 +425,46 @@ static pmpkg_t *pkg_load(const char *pkgfile, int full) /* internal fields for package struct */ newpkg->origin = PKG_FROM_FILE; - /* TODO eventually kill/move this? */ newpkg->origin_data.file = strdup(pkgfile); newpkg->ops = get_file_pkg_ops(); + newpkg->handle = handle; if(full) { + /* attempt to hand back any memory we don't need */ + files = realloc(files, sizeof(alpm_file_t) * files_count); /* "checking for conflicts" requires a sorted list, ensure that here */ - _alpm_log(PM_LOG_DEBUG, "sorting package filelist for %s\n", pkgfile); - newpkg->files = alpm_list_msort(newpkg->files, alpm_list_count(newpkg->files), - _alpm_str_cmp); - newpkg->infolevel = INFRQ_ALL; + _alpm_log(handle, ALPM_LOG_DEBUG, "sorting package filelist for %s\n", pkgfile); + newpkg->files.files = files_msort(files, files_count); + newpkg->files.count = files_count; + newpkg->infolevel = INFRQ_BASE | INFRQ_DESC | INFRQ_FILES | INFRQ_SCRIPTLET; } else { - /* get rid of any partial filelist we may have collected, it is invalid */ - FREELIST(newpkg->files); - newpkg->infolevel = INFRQ_BASE | INFRQ_DESC; + newpkg->infolevel = INFRQ_BASE | INFRQ_DESC | INFRQ_SCRIPTLET; } - return(newpkg); + return newpkg; pkg_invalid: - pm_errno = PM_ERR_PKG_INVALID; + handle->pm_errno = ALPM_ERR_PKG_INVALID; error: _alpm_pkg_free(newpkg); archive_read_finish(archive); - return(NULL); + return NULL; } -int SYMEXPORT alpm_pkg_load(const char *filename, int full, pmpkg_t **pkg) +int SYMEXPORT alpm_pkg_load(alpm_handle_t *handle, const char *filename, int full, + alpm_siglevel_t level, alpm_pkg_t **pkg) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(filename != NULL && strlen(filename) != 0, - RET_ERR(PM_ERR_WRONG_ARGS, -1)); - ASSERT(pkg != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); + CHECK_HANDLE(handle, return -1); + ASSERT(pkg != NULL, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1)); - *pkg = pkg_load(filename, full); + *pkg = _alpm_pkg_load_internal(handle, filename, full, NULL, NULL, level); if(*pkg == NULL) { /* pm_errno is set by pkg_load */ - return(-1); + return -1; } - return(0); + return 0; } /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/be_sync.c b/lib/libalpm/be_sync.c index c440cd6b..d4c71a8e 100644 --- a/lib/libalpm/be_sync.c +++ b/lib/libalpm/be_sync.c @@ -1,5 +1,5 @@ /* - * be_sync.c + * be_sync.c : backend for sync databases * * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> @@ -21,7 +21,8 @@ #include "config.h" #include <errno.h> -#include <limits.h> +#include <sys/stat.h> +#include <unistd.h> /* libarchive */ #include <archive.h> @@ -38,32 +39,93 @@ #include "deps.h" #include "dload.h" +static char *get_sync_dir(alpm_handle_t *handle) +{ + const char *dbpath = alpm_option_get_dbpath(handle); + size_t len = strlen(dbpath) + 6; + char *syncpath; + struct stat buf; + + MALLOC(syncpath, len, RET_ERR(handle, ALPM_ERR_MEMORY, NULL)); + sprintf(syncpath, "%s%s", dbpath, "sync/"); + + if(stat(syncpath, &buf) != 0) { + _alpm_log(handle, ALPM_LOG_DEBUG, "database dir '%s' does not exist, creating it\n", + syncpath); + if(_alpm_makepath(syncpath) != 0) { + free(syncpath); + RET_ERR(handle, ALPM_ERR_SYSTEM, NULL); + } + } else if(!S_ISDIR(buf.st_mode)) { + _alpm_log(handle, ALPM_LOG_WARNING, _("removing invalid file: %s\n"), syncpath); + if(unlink(syncpath) != 0 || _alpm_makepath(syncpath) != 0) { + free(syncpath); + RET_ERR(handle, ALPM_ERR_SYSTEM, NULL); + } + } + + return syncpath; +} + +static int sync_db_validate(alpm_db_t *db) +{ + alpm_siglevel_t level; + + if(db->status & DB_STATUS_VALID) { + return 0; + } + + /* this takes into account the default verification level if UNKNOWN + * was assigned to this db */ + level = alpm_db_get_siglevel(db); + + if(level & ALPM_SIG_DATABASE) { + const char *dbpath = _alpm_db_path(db); + if(!dbpath) { + /* pm_errno set in _alpm_db_path() */ + return -1; + } + + /* we can skip any validation if the database doesn't exist */ + if(access(dbpath, R_OK) != 0 && errno == ENOENT) { + goto valid; + return 0; + } + + if(_alpm_check_pgp_helper(db->handle, dbpath, NULL, + level & ALPM_SIG_DATABASE_OPTIONAL, level & ALPM_SIG_DATABASE_MARGINAL_OK, + level & ALPM_SIG_DATABASE_UNKNOWN_OK, ALPM_ERR_DB_INVALID_SIG)) { + return 1; + } + } + +valid: + db->status |= DB_STATUS_VALID; + return 0; +} + /** Update a package database * * An update of the package database \a db will be attempted. Unless * \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)) { + * alpm_db_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 @@ -77,78 +139,175 @@ * @return 0 on success, -1 on error (pm_errno is set accordingly), 1 if up to * to date */ -int SYMEXPORT alpm_db_update(int force, pmdb_t *db) +int SYMEXPORT alpm_db_update(int force, alpm_db_t *db) { - char *dbfile, *syncpath; - const char *dbpath; - struct stat buf; - size_t len; - int ret; + char *syncpath; + alpm_list_t *i; + int ret = -1; mode_t oldmask; - - ALPM_LOG_FUNC; + alpm_handle_t *handle; + alpm_siglevel_t level; /* Sanity checks */ - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); - ASSERT(db != NULL && db != handle->db_local, RET_ERR(PM_ERR_WRONG_ARGS, -1)); + ASSERT(db != NULL, return -1); + handle = db->handle; + handle->pm_errno = 0; + ASSERT(db != handle->db_local, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1)); + ASSERT(db->servers != NULL, RET_ERR(handle, ALPM_ERR_SERVER_NONE, -1)); + + syncpath = get_sync_dir(handle); + if(!syncpath) { + return -1; + } - if(!alpm_list_find_ptr(handle->dbs_sync, db)) { - RET_ERR(PM_ERR_DB_NOT_FOUND, -1); + /* make sure we have a sane umask */ + oldmask = umask(0022); + + level = alpm_db_get_siglevel(db); + + /* attempt to grab a lock */ + if(_alpm_handle_lock(handle)) { + RET_ERR(handle, ALPM_ERR_HANDLE_LOCK, -1); } - len = strlen(db->treename) + 4; - MALLOC(dbfile, len, RET_ERR(PM_ERR_MEMORY, -1)); - sprintf(dbfile, "%s.db", db->treename); + for(i = db->servers; i; i = i->next) { + const char *server = i->data; + struct dload_payload *payload; + size_t len; + int sig_ret = 0; - dbpath = alpm_option_get_dbpath(); - len = strlen(dbpath) + 6; - MALLOC(syncpath, len, RET_ERR(PM_ERR_MEMORY, -1)); - sprintf(syncpath, "%s%s", dbpath, "sync/"); + CALLOC(payload, 1, sizeof(*payload), RET_ERR(handle, ALPM_ERR_MEMORY, -1)); - /* make sure we have a sane umask */ - oldmask = umask(0022); + /* set hard upper limit of 25MiB */ + payload->max_size = 25 * 1024 * 1024; - if(stat(syncpath, &buf) != 0) { - _alpm_log(PM_LOG_DEBUG, "database dir '%s' does not exist, creating it\n", - syncpath); - if(_alpm_makepath(syncpath) != 0) { - free(dbfile); - free(syncpath); - RET_ERR(PM_ERR_SYSTEM, -1); + /* print server + filename into a buffer (leave space for .sig) */ + len = strlen(server) + strlen(db->treename) + 9; + CALLOC(payload->fileurl, len, sizeof(char), RET_ERR(handle, ALPM_ERR_MEMORY, -1)); + snprintf(payload->fileurl, len, "%s/%s.db", server, db->treename); + payload->handle = handle; + payload->force = force; + + ret = _alpm_download(payload, syncpath, NULL); + + if(ret == 0 && (level & ALPM_SIG_DATABASE)) { + /* an existing sig file is no good at this point */ + char *sigpath = _alpm_db_sig_path(db); + if(!sigpath) { + ret = -1; + break; + } + unlink(sigpath); + free(sigpath); + + /* if we downloaded a DB, we want the .sig from the same server */ + snprintf(payload->fileurl, len, "%s/%s.db.sig", server, db->treename); + payload->handle = handle; + payload->force = 1; + payload->errors_ok = (level & ALPM_SIG_DATABASE_OPTIONAL); + + /* set hard upper limit of 16KiB */ + payload->max_size = 16 * 1024; + + sig_ret = _alpm_download(payload, syncpath, NULL); + /* errors_ok suppresses error messages, but not the return code */ + sig_ret = payload->errors_ok ? 0 : sig_ret; } - } else if(!S_ISDIR(buf.st_mode)) { - _alpm_log(PM_LOG_WARNING, _("removing invalid file: %s\n"), syncpath); - if(unlink(syncpath) != 0 || _alpm_makepath(syncpath) != 0) { - free(dbfile); - free(syncpath); - RET_ERR(PM_ERR_SYSTEM, -1); + + _alpm_dload_payload_free(payload); + if(ret != -1 && sig_ret != -1) { + break; } } - ret = _alpm_download_single_file(dbfile, db->servers, syncpath, force); - free(dbfile); - free(syncpath); - umask(oldmask); - if(ret == 1) { /* files match, do nothing */ - pm_errno = 0; - return(1); + handle->pm_errno = 0; + goto cleanup; } else if(ret == -1) { /* pm_errno was set by the download code */ - _alpm_log(PM_LOG_DEBUG, "failed to sync db: %s\n", alpm_strerrorlast()); - return(-1); + _alpm_log(handle, ALPM_LOG_DEBUG, "failed to sync db: %s\n", + alpm_strerror(handle->pm_errno)); + goto cleanup; } /* Cache needs to be rebuilt */ _alpm_db_free_pkgcache(db); - return(0); + db->status &= ~DB_STATUS_VALID; + if(sync_db_validate(db)) { + /* pm_errno should be set */ + ret = -1; + } + +cleanup: + + if(_alpm_handle_unlock(handle)) { + _alpm_log(handle, ALPM_LOG_WARNING, _("could not remove lock file %s\n"), + alpm_option_get_lockfile(handle)); + } + free(syncpath); + umask(oldmask); + return ret; } /* Forward decl so I don't reorganize the whole file right now */ -static int sync_db_read(pmdb_t *db, struct archive *archive, - struct archive_entry *entry, pmpkg_t *likely_pkg); +static int sync_db_read(alpm_db_t *db, struct archive *archive, + struct archive_entry *entry, alpm_pkg_t **likely_pkg); + +static alpm_pkg_t *load_pkg_for_entry(alpm_db_t *db, const char *entryname, + const char **entry_filename, alpm_pkg_t *likely_pkg) +{ + char *pkgname = NULL, *pkgver = NULL; + unsigned long pkgname_hash; + alpm_pkg_t *pkg; + + /* get package and db file names */ + if(entry_filename) { + char *fname = strrchr(entryname, '/'); + if(fname) { + *entry_filename = fname + 1; + } else { + *entry_filename = NULL; + } + } + if(_alpm_splitname(entryname, &pkgname, &pkgver, &pkgname_hash) != 0) { + _alpm_log(db->handle, ALPM_LOG_ERROR, + _("invalid name for database entry '%s'\n"), entryname); + return NULL; + } + + if(likely_pkg && strcmp(likely_pkg->name, pkgname) == 0) { + pkg = likely_pkg; + } else { + pkg = _alpm_pkghash_find(db->pkgcache, pkgname); + } + if(pkg == NULL) { + pkg = _alpm_pkg_new(); + if(pkg == NULL) { + RET_ERR(db->handle, ALPM_ERR_MEMORY, NULL); + } + + pkg->name = pkgname; + pkg->version = pkgver; + pkg->name_hash = pkgname_hash; + + pkg->origin = PKG_FROM_SYNCDB; + pkg->origin_data.db = db; + pkg->ops = &default_pkg_ops; + pkg->handle = db->handle; + + /* add to the collection */ + _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); + } else { + free(pkgname); + free(pkgver); + } + + return pkg; +} /* * This is the data table used to generate the estimating function below. @@ -206,10 +365,10 @@ static size_t estimate_package_count(struct stat *st, struct archive *archive) /* assume it is at least somewhat compressed */ per_package = 200; } - return((size_t)(st->st_size / per_package) + 1); + return (size_t)((st->st_size / per_package) + 1); } -static int sync_db_populate(pmdb_t *db) +static int sync_db_populate(alpm_db_t *db) { const char *dbpath; size_t est_count; @@ -217,14 +376,10 @@ static int sync_db_populate(pmdb_t *db) struct stat buf; struct archive *archive; struct archive_entry *entry; - pmpkg_t *pkg = NULL; - - ALPM_LOG_FUNC; - - ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); + alpm_pkg_t *pkg = NULL; if((archive = archive_read_new()) == NULL) { - RET_ERR(PM_ERR_LIBARCHIVE, -1); + RET_ERR(db->handle, ALPM_ERR_LIBARCHIVE, -1); } archive_read_support_compression_all(archive); @@ -236,24 +391,24 @@ static int sync_db_populate(pmdb_t *db) return -1; } - _alpm_log(PM_LOG_DEBUG, "opening database archive %s\n", dbpath); + _alpm_log(db->handle, ALPM_LOG_DEBUG, "opening database archive %s\n", dbpath); if(archive_read_open_filename(archive, dbpath, ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) { - _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), dbpath, + _alpm_log(db->handle, ALPM_LOG_ERROR, _("could not open file %s: %s\n"), dbpath, archive_error_string(archive)); archive_read_finish(archive); - RET_ERR(PM_ERR_DB_OPEN, -1); + RET_ERR(db->handle, ALPM_ERR_DB_OPEN, -1); } if(stat(dbpath, &buf) != 0) { - RET_ERR(PM_ERR_DB_OPEN, -1); + RET_ERR(db->handle, ALPM_ERR_DB_OPEN, -1); } est_count = estimate_package_count(&buf, archive); /* initialize hash at 66% full */ db->pkgcache = _alpm_pkghash_create(est_count * 3 / 2); if(db->pkgcache == NULL) { - RET_ERR(PM_ERR_MEMORY, -1); + RET_ERR(db->handle, ALPM_ERR_MEMORY, -1); } while(archive_read_next_header(archive, &entry) == ARCHIVE_OK) { @@ -262,139 +417,96 @@ static int sync_db_populate(pmdb_t *db) st = archive_entry_stat(entry); if(S_ISDIR(st->st_mode)) { - const char *name; - - pkg = _alpm_pkg_new(); - if(pkg == NULL) { - archive_read_finish(archive); - RET_ERR(PM_ERR_MEMORY, -1); - } - - name = archive_entry_pathname(entry); - - if(_alpm_splitname(name, pkg) != 0) { - _alpm_log(PM_LOG_ERROR, _("invalid name for database entry '%s'\n"), - name); - _alpm_pkg_free(pkg); - continue; - } - - /* 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_pkg_free(pkg); - continue; - } - - pkg->origin = PKG_FROM_SYNCDB; - pkg->ops = &default_pkg_ops; - pkg->origin_data.db = db; - - /* add to the collection */ - _alpm_log(PM_LOG_FUNCTION, "adding '%s' to package cache for db '%s'\n", - pkg->name, db->treename); - db->pkgcache = _alpm_pkghash_add(db->pkgcache, pkg); - count++; + continue; } else { /* we have desc, depends or deltas - parse it */ - sync_db_read(db, archive, entry, pkg); + if(sync_db_read(db, archive, entry, &pkg) != 0) { + _alpm_log(db->handle, ALPM_LOG_ERROR, + _("could not parse package description file '%s' from db '%s'\n"), + archive_entry_pathname(entry), db->treename); + continue; + } } } + count = alpm_list_count(db->pkgcache->list); + if(count > 0) { db->pkgcache->list = alpm_list_msort(db->pkgcache->list, (size_t)count, _alpm_pkg_cmp); } archive_read_finish(archive); + _alpm_log(db->handle, ALPM_LOG_DEBUG, "added %d packages to package cache for db '%s'\n", + count, db->treename); - return(count); + return count; } -#define READ_NEXT(s) do { \ +#define READ_NEXT() do { \ if(_alpm_archive_fgets(archive, &buf) != ARCHIVE_OK) goto error; \ - s = _alpm_strtrim(buf.line); \ + line = buf.line; \ + _alpm_strip_newline(line); \ } while(0) #define READ_AND_STORE(f) do { \ - READ_NEXT(line); \ + READ_NEXT(); \ STRDUP(f, line, goto error); \ } while(0) #define READ_AND_STORE_ALL(f) do { \ char *linedup; \ - READ_NEXT(line); \ - if(strlen(line) == 0) break; \ - STRDUP(linedup, line, goto error); \ + if(_alpm_archive_fgets(archive, &buf) != ARCHIVE_OK) goto error; \ + if(_alpm_strip_newline(buf.line) == 0) break; \ + STRDUP(linedup, buf.line, goto error); \ f = alpm_list_add(f, linedup); \ } while(1) /* note the while(1) and not (0) */ -static int sync_db_read(pmdb_t *db, struct archive *archive, - struct archive_entry *entry, pmpkg_t *likely_pkg) +static int sync_db_read(alpm_db_t *db, struct archive *archive, + struct archive_entry *entry, alpm_pkg_t **likely_pkg) { - const char *entryname = NULL, *filename; - char *pkgname, *p, *q; - pmpkg_t *pkg; + const char *entryname, *filename; + alpm_pkg_t *pkg; struct archive_read_buffer buf; - ALPM_LOG_FUNC; - - if(db == NULL) { - RET_ERR(PM_ERR_DB_NULL, -1); - } - - if(entry != NULL) { - entryname = archive_entry_pathname(entry); - } + entryname = archive_entry_pathname(entry); if(entryname == NULL) { - _alpm_log(PM_LOG_DEBUG, "invalid archive entry provided to _alpm_sync_db_read, skipping\n"); - return(-1); + _alpm_log(db->handle, ALPM_LOG_DEBUG, + "invalid archive entry provided to _alpm_sync_db_read, skipping\n"); + return -1; } - _alpm_log(PM_LOG_FUNCTION, "loading package data from archive entry %s\n", + _alpm_log(db->handle, ALPM_LOG_FUNCTION, "loading package data from archive entry %s\n", entryname); memset(&buf, 0, sizeof(buf)); /* 512K for a line length seems reasonable */ buf.max_line_size = 512 * 1024; - /* get package and db file names */ - STRDUP(pkgname, entryname, RET_ERR(PM_ERR_MEMORY, -1)); - p = pkgname + strlen(pkgname); - for(q = --p; *q && *q != '/'; q--); - filename = q + 1; - for(p = --q; *p && *p != '-'; p--); - for(q = --p; *q && *q != '-'; q--); - *q = '\0'; - - /* package is already in db due to parsing of directory name */ - if(likely_pkg && strcmp(likely_pkg->name, pkgname) == 0) { - pkg = likely_pkg; - } else { - if(db->pkgcache == NULL) { - RET_ERR(PM_ERR_MEMORY, -1); - } - pkg = _alpm_pkghash_find(db->pkgcache, pkgname); - } + pkg = load_pkg_for_entry(db, entryname, &filename, *likely_pkg); + if(pkg == NULL) { - _alpm_log(PM_LOG_DEBUG, "package %s not found in %s sync database", - pkgname, db->treename); - return(-1); + _alpm_log(db->handle, ALPM_LOG_DEBUG, + "entry %s could not be loaded into %s sync database", + entryname, db->treename); + return -1; } if(strcmp(filename, "desc") == 0 || strcmp(filename, "depends") == 0 || strcmp(filename, "deltas") == 0) { - while(_alpm_archive_fgets(archive, &buf) == ARCHIVE_OK) { - char *line = _alpm_strtrim(buf.line); + int ret; + while((ret = _alpm_archive_fgets(archive, &buf)) == ARCHIVE_OK) { + char *line = buf.line; + _alpm_strip_newline(line); if(strcmp(line, "%NAME%") == 0) { - READ_NEXT(line); + READ_NEXT(); if(strcmp(line, pkg->name) != 0) { - _alpm_log(PM_LOG_ERROR, _("%s database is inconsistent: name " + _alpm_log(db->handle, ALPM_LOG_ERROR, _("%s database is inconsistent: name " "mismatch on package %s\n"), db->treename, pkg->name); } } else if(strcmp(line, "%VERSION%") == 0) { - READ_NEXT(line); + READ_NEXT(); if(strcmp(line, pkg->version) != 0) { - _alpm_log(PM_LOG_ERROR, _("%s database is inconsistent: version " + _alpm_log(db->handle, ALPM_LOG_ERROR, _("%s database is inconsistent: version " "mismatch on package %s\n"), db->treename, pkg->name); } } else if(strcmp(line, "%FILENAME%") == 0) { @@ -410,7 +522,7 @@ static int sync_db_read(pmdb_t *db, struct archive *archive, } else if(strcmp(line, "%ARCH%") == 0) { READ_AND_STORE(pkg->arch); } else if(strcmp(line, "%BUILDDATE%") == 0) { - READ_NEXT(line); + READ_NEXT(); pkg->builddate = _alpm_parsedate(line); } else if(strcmp(line, "%PACKAGER%") == 0) { READ_AND_STORE(pkg->packager); @@ -419,29 +531,28 @@ static int sync_db_read(pmdb_t *db, struct archive *archive, * 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. */ - READ_NEXT(line); + READ_NEXT(); pkg->size = atol(line); /* also store this value to isize if isize is unset */ if(pkg->isize == 0) { pkg->isize = pkg->size; } } else if(strcmp(line, "%ISIZE%") == 0) { - READ_NEXT(line); + READ_NEXT(); pkg->isize = atol(line); } else if(strcmp(line, "%MD5SUM%") == 0) { READ_AND_STORE(pkg->md5sum); } else if(strcmp(line, "%SHA256SUM%") == 0) { /* we don't do anything with this value right now */ - READ_NEXT(line); + READ_NEXT(); } else if(strcmp(line, "%PGPSIG%") == 0) { - /* we don't do anything with this value right now */ - READ_NEXT(line); + READ_AND_STORE(pkg->base64_sig); } else if(strcmp(line, "%REPLACES%") == 0) { READ_AND_STORE_ALL(pkg->replaces); } else if(strcmp(line, "%DEPENDS%") == 0) { /* Different than the rest because of the _alpm_splitdep call. */ while(1) { - READ_NEXT(line); + READ_NEXT(); if(strlen(line) == 0) break; pkg->depends = alpm_list_add(pkg->depends, _alpm_splitdep(line)); } @@ -454,62 +565,61 @@ static int sync_db_read(pmdb_t *db, struct archive *archive, } else if(strcmp(line, "%DELTAS%") == 0) { /* Different than the rest because of the _alpm_delta_parse call. */ while(1) { - READ_NEXT(line); + READ_NEXT(); if(strlen(line) == 0) break; pkg->deltas = alpm_list_add(pkg->deltas, _alpm_delta_parse(line)); } } } + if(ret != ARCHIVE_EOF) { + goto error; + } + *likely_pkg = pkg; } else if(strcmp(filename, "files") == 0) { /* currently do nothing with this file */ } else { /* unknown database file */ - _alpm_log(PM_LOG_DEBUG, "unknown database file: %s\n", filename); + _alpm_log(db->handle, ALPM_LOG_DEBUG, "unknown database file: %s\n", filename); } -error: - FREE(pkgname); - /* TODO: return 0 always? */ - return(0); -} + return 0; -static int sync_db_version(pmdb_t *db) -{ - return(2); +error: + _alpm_log(db->handle, ALPM_LOG_DEBUG, "error parsing database file: %s\n", filename); + return -1; } struct db_operations sync_db_ops = { + .validate = sync_db_validate, .populate = sync_db_populate, .unregister = _alpm_db_unregister, - .version = sync_db_version, }; -pmdb_t *_alpm_db_register_sync(const char *treename) +alpm_db_t *_alpm_db_register_sync(alpm_handle_t *handle, const char *treename, + alpm_siglevel_t level) { - pmdb_t *db; - alpm_list_t *i; + alpm_db_t *db; - ALPM_LOG_FUNC; + _alpm_log(handle, ALPM_LOG_DEBUG, "registering sync database '%s'\n", treename); - for(i = handle->dbs_sync; i; i = i->next) { - pmdb_t *sdb = i->data; - if(strcmp(treename, sdb->treename) == 0) { - _alpm_log(PM_LOG_DEBUG, "attempt to re-register the '%s' database, using existing\n", sdb->treename); - return sdb; - } +#ifndef HAVE_LIBGPGME + if(level != 0 && level != ALPM_SIG_USE_DEFAULT) { + RET_ERR(handle, ALPM_ERR_WRONG_ARGS, NULL); } - - _alpm_log(PM_LOG_DEBUG, "registering sync database '%s'\n", treename); +#endif db = _alpm_db_new(treename, 0); if(db == NULL) { - RET_ERR(PM_ERR_DB_CREATE, NULL); + RET_ERR(handle, ALPM_ERR_DB_CREATE, NULL); } db->ops = &sync_db_ops; + db->handle = handle; + db->siglevel = level; + + sync_db_validate(db); handle->dbs_sync = alpm_list_add(handle->dbs_sync, db); - return(db); + return db; } - /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/conflict.c b/lib/libalpm/conflict.c index db10d329..538c4c73 100644 --- a/lib/libalpm/conflict.c +++ b/lib/libalpm/conflict.c @@ -34,29 +34,28 @@ /* libalpm */ #include "conflict.h" #include "alpm_list.h" +#include "alpm.h" #include "handle.h" #include "trans.h" #include "util.h" #include "log.h" #include "deps.h" -pmconflict_t *_alpm_conflict_new(const char *package1, const char *package2, +static alpm_conflict_t *conflict_new(const char *package1, const char *package2, const char *reason) { - pmconflict_t *conflict; + alpm_conflict_t *conflict; - ALPM_LOG_FUNC; + MALLOC(conflict, sizeof(alpm_conflict_t), return NULL); - MALLOC(conflict, sizeof(pmconflict_t), RET_ERR(PM_ERR_MEMORY, NULL)); + STRDUP(conflict->package1, package1, return NULL); + STRDUP(conflict->package2, package2, return NULL); + STRDUP(conflict->reason, reason, return NULL); - STRDUP(conflict->package1, package1, RET_ERR(PM_ERR_MEMORY, NULL)); - STRDUP(conflict->package2, package2, RET_ERR(PM_ERR_MEMORY, NULL)); - STRDUP(conflict->reason, reason, RET_ERR(PM_ERR_MEMORY, NULL)); - - return(conflict); + return conflict; } -void _alpm_conflict_free(pmconflict_t *conflict) +void _alpm_conflict_free(alpm_conflict_t *conflict) { FREE(conflict->package2); FREE(conflict->package1); @@ -64,55 +63,59 @@ void _alpm_conflict_free(pmconflict_t *conflict) FREE(conflict); } -pmconflict_t *_alpm_conflict_dup(const pmconflict_t *conflict) +alpm_conflict_t *_alpm_conflict_dup(const alpm_conflict_t *conflict) { - pmconflict_t *newconflict; - CALLOC(newconflict, 1, sizeof(pmconflict_t), RET_ERR(PM_ERR_MEMORY, NULL)); + alpm_conflict_t *newconflict; + CALLOC(newconflict, 1, sizeof(alpm_conflict_t), return NULL); - STRDUP(newconflict->package1, conflict->package1, RET_ERR(PM_ERR_MEMORY, NULL)); - STRDUP(newconflict->package2, conflict->package2, RET_ERR(PM_ERR_MEMORY, NULL)); - STRDUP(newconflict->reason, conflict->reason, RET_ERR(PM_ERR_MEMORY, NULL)); + STRDUP(newconflict->package1, conflict->package1, return NULL); + STRDUP(newconflict->package2, conflict->package2, return NULL); + STRDUP(newconflict->reason, conflict->reason, return NULL); - return(newconflict); + return newconflict; } -static int conflict_isin(pmconflict_t *needle, alpm_list_t *haystack) +static int conflict_isin(alpm_conflict_t *needle, alpm_list_t *haystack) { alpm_list_t *i; const char *npkg1 = needle->package1; const char *npkg2 = needle->package2; - ALPM_LOG_FUNC; - for(i = haystack; i; i = i->next) { - pmconflict_t *conflict = i->data; + alpm_conflict_t *conflict = i->data; const char *cpkg1 = conflict->package1; const char *cpkg2 = conflict->package2; if((strcmp(cpkg1, npkg1) == 0 && strcmp(cpkg2, npkg2) == 0) || (strcmp(cpkg1, npkg2) == 0 && strcmp(cpkg2, npkg1) == 0)) { - return(1); + return 1; } } - return(0); + return 0; } -/** Adds the pkg1/pkg2 conflict to the baddeps list - * @param *baddeps list to add conflict to +/** Adds the pkg1/pkg2 conflict to the baddeps list. + * @param handle the context handle + * @param baddeps list to add conflict to * @param pkg1 first package * @param pkg2 package causing conflict + * @param reason reason for this conflict */ -static void add_conflict(alpm_list_t **baddeps, const char *pkg1, - const char *pkg2, const char *reason) +static int add_conflict(alpm_handle_t *handle, alpm_list_t **baddeps, + const char *pkg1, const char *pkg2, const char *reason) { - pmconflict_t *conflict = _alpm_conflict_new(pkg1, pkg2, reason); - _alpm_log(PM_LOG_DEBUG, "package %s conflicts with %s (by %s)\n", + alpm_conflict_t *conflict = conflict_new(pkg1, pkg2, reason); + if(!conflict) { + return -1; + } + _alpm_log(handle, ALPM_LOG_DEBUG, "package %s conflicts with %s (by %s)\n", pkg1, pkg2, reason); - if(conflict && !conflict_isin(conflict, *baddeps)) { + if(!conflict_isin(conflict, *baddeps)) { *baddeps = alpm_list_add(*baddeps, conflict); } else { _alpm_conflict_free(conflict); } + return 0; } /** Check if packages from list1 conflict with packages from list2. @@ -121,28 +124,32 @@ static void add_conflict(alpm_list_t **baddeps, const char *pkg1, * If a conflict (pkg1, pkg2) is found, it is added to the baddeps list * in this order if order >= 0, or reverse order (pkg2,pkg1) otherwise. * + * @param handle the context handle * @param list1 first list of packages * @param list2 second list of packages - * @param *baddeps list to store conflicts + * @param baddeps list to store conflicts * @param order if >= 0 the conflict order is preserved, if < 0 it's reversed */ -static void check_conflict(alpm_list_t *list1, alpm_list_t *list2, +static void check_conflict(alpm_handle_t *handle, + alpm_list_t *list1, alpm_list_t *list2, alpm_list_t **baddeps, int order) { - alpm_list_t *i, *j, *k; + alpm_list_t *i; if(!baddeps) { return; } for(i = list1; i; i = i->next) { - pmpkg_t *pkg1 = i->data; + alpm_pkg_t *pkg1 = i->data; const char *pkg1name = alpm_pkg_get_name(pkg1); + alpm_list_t *j; for(j = alpm_pkg_get_conflicts(pkg1); j; j = j->next) { const char *conflict = j->data; - pmdepend_t *parsed_conflict = _alpm_splitdep(conflict); + alpm_list_t *k; + alpm_depend_t *parsed_conflict = _alpm_splitdep(conflict); for(k = list2; k; k = k->next) { - pmpkg_t *pkg2 = k->data; + alpm_pkg_t *pkg2 = k->data; const char *pkg2name = alpm_pkg_get_name(pkg2); if(strcmp(pkg1name, pkg2name) == 0) { @@ -152,9 +159,9 @@ static void check_conflict(alpm_list_t *list1, alpm_list_t *list2, if(_alpm_depcmp(pkg2, parsed_conflict)) { if(order >= 0) { - add_conflict(baddeps, pkg1name, pkg2name, conflict); + add_conflict(handle, baddeps, pkg1name, pkg2name, conflict); } else { - add_conflict(baddeps, pkg2name, pkg1name, conflict); + add_conflict(handle, baddeps, pkg2name, pkg1name, conflict); } } } @@ -164,189 +171,183 @@ static void check_conflict(alpm_list_t *list1, alpm_list_t *list2, } /* Check for inter-conflicts */ -alpm_list_t *_alpm_innerconflicts(alpm_list_t *packages) +alpm_list_t *_alpm_innerconflicts(alpm_handle_t *handle, alpm_list_t *packages) { alpm_list_t *baddeps = NULL; - ALPM_LOG_FUNC; - - _alpm_log(PM_LOG_DEBUG, "check targets vs targets\n"); - check_conflict(packages, packages, &baddeps, 0); + _alpm_log(handle, ALPM_LOG_DEBUG, "check targets vs targets\n"); + check_conflict(handle, packages, packages, &baddeps, 0); - return(baddeps); + return baddeps; } /* Check for target vs (db - target) conflicts * In case of conflict the package1 field of pmdepconflict_t contains * the target package, package2 field contains the local package */ -alpm_list_t *_alpm_outerconflicts(pmdb_t *db, alpm_list_t *packages) +alpm_list_t *_alpm_outerconflicts(alpm_db_t *db, alpm_list_t *packages) { alpm_list_t *baddeps = NULL; - ALPM_LOG_FUNC; - if(db == NULL) { - return(NULL); + return NULL; } alpm_list_t *dblist = alpm_list_diff(_alpm_db_get_pkgcache(db), packages, _alpm_pkg_cmp); /* two checks to be done here for conflicts */ - _alpm_log(PM_LOG_DEBUG, "check targets vs db\n"); - check_conflict(packages, dblist, &baddeps, 1); - _alpm_log(PM_LOG_DEBUG, "check db vs targets\n"); - check_conflict(dblist, packages, &baddeps, -1); + _alpm_log(db->handle, ALPM_LOG_DEBUG, "check targets vs db\n"); + check_conflict(db->handle, packages, dblist, &baddeps, 1); + _alpm_log(db->handle, ALPM_LOG_DEBUG, "check db vs targets\n"); + check_conflict(db->handle, dblist, packages, &baddeps, -1); alpm_list_free(dblist); - return(baddeps); + return baddeps; } /** Check the package conflicts in a database * + * @param handle the context handle * @param pkglist the list of packages to check - * @return an alpm_list_t of pmconflict_t + * @return an alpm_list_t of alpm_conflict_t */ -alpm_list_t SYMEXPORT *alpm_checkconflicts(alpm_list_t *pkglist) { - return(_alpm_innerconflicts(pkglist)); -} - -/* Returns a alpm_list_t* of file conflicts. - * Hooray for set-intersects! - * Pre-condition: both lists are sorted! - */ -static alpm_list_t *chk_fileconflicts(alpm_list_t *filesA, alpm_list_t *filesB) +alpm_list_t SYMEXPORT *alpm_checkconflicts(alpm_handle_t *handle, + alpm_list_t *pkglist) { - alpm_list_t *ret = NULL; - alpm_list_t *pA = filesA, *pB = filesB; - - while(pA && pB) { - const char *strA = pA->data; - const char *strB = pB->data; - /* skip directories, we don't care about dir conflicts */ - if(strA[strlen(strA)-1] == '/') { - pA = pA->next; - } else if(strB[strlen(strB)-1] == '/') { - pB = pB->next; - } else { - int cmp = strcmp(strA, strB); - if(cmp < 0) { - /* item only in filesA, ignore it */ - pA = pA->next; - } else if(cmp > 0) { - /* item only in filesB, ignore it */ - pB = pB->next; - } else { - /* item in both, record it */ - ret = alpm_list_add(ret, strdup(strA)); - pA = pA->next; - pB = pB->next; - } - } - } - - return(ret); + CHECK_HANDLE(handle, return NULL); + return _alpm_innerconflicts(handle, pkglist); } -/* Returns a alpm_list_t* of files that are in filesA but *NOT* in filesB - * This is an 'A minus B' set operation - * Pre-condition: both lists are sorted! +static const int DIFFERENCE = 0; +static const int INTERSECT = 1; +/* Returns a set operation on the provided two lists of files. + * Pre-condition: both lists are sorted! + * When done, free the list but NOT the contained data. + * + * Operations: + * DIFFERENCE - a difference operation is performed. filesA - filesB. + * INTERSECT - an intersection operation is performed. filesA & filesB. */ -static alpm_list_t *chk_filedifference(alpm_list_t *filesA, alpm_list_t *filesB) +static alpm_list_t *filelist_operation(alpm_filelist_t *filesA, + alpm_filelist_t *filesB, int operation) { alpm_list_t *ret = NULL; - alpm_list_t *pA = filesA, *pB = filesB; - - /* if both filesA and filesB have entries, do this loop */ - while(pA && pB) { - const char *strA = pA->data; - const char *strB = pB->data; - /* skip directories, we don't care about dir conflicts */ + size_t ctrA = 0, ctrB = 0; + + while(ctrA < filesA->count && ctrB < filesB->count) { + alpm_file_t *fileA = filesA->files + ctrA; + alpm_file_t *fileB = filesB->files + ctrB; + const char *strA = fileA->name; + const char *strB = fileB->name; + /* skip directories, we don't care about them */ if(strA[strlen(strA)-1] == '/') { - pA = pA->next; + ctrA++; } else if(strB[strlen(strB)-1] == '/') { - pB = pB->next; + ctrB++; } else { int cmp = strcmp(strA, strB); if(cmp < 0) { - /* item only in filesA, record it */ - ret = alpm_list_add(ret, strdup(strA)); - pA = pA->next; + if(operation == DIFFERENCE) { + /* item only in filesA, qualifies as a difference */ + ret = alpm_list_add(ret, fileA); + } + ctrA++; } else if(cmp > 0) { - /* item only in fileB, but this means nothing */ - pB = pB->next; + ctrB++; } else { - /* item in both, ignore it */ - pA = pA->next; - pB = pB->next; + if(operation == INTERSECT) { + /* item in both, qualifies as an intersect */ + ret = alpm_list_add(ret, fileA); + } + ctrA++; + ctrB++; } } } - /* ensure we have completely emptied pA */ - while(pA) { - const char *strA = pA->data; + + /* if doing a difference, ensure we have completely emptied pA */ + while(operation == DIFFERENCE && ctrA < filesA->count) { + alpm_file_t *fileA = filesA->files + ctrA; + const char *strA = fileA->name; /* skip directories */ if(strA[strlen(strA)-1] != '/') { - ret = alpm_list_add(ret, strdup(strA)); + ret = alpm_list_add(ret, fileA); } - pA = pA->next; + ctrA++; } - return(ret); + return ret; } -/* Adds pmfileconflict_t to a conflicts list. Pass the conflicts list, type - * (either PM_FILECONFLICT_TARGET or PM_FILECONFLICT_FILESYSTEM), a file +/* Adds alpm_fileconflict_t to a conflicts list. Pass the conflicts list, type + * (either ALPM_FILECONFLICT_TARGET or ALPM_FILECONFLICT_FILESYSTEM), a file * string, and either two package names or one package name and NULL. This is * a wrapper for former functionality that was done inline. */ -static alpm_list_t *add_fileconflict(alpm_list_t *conflicts, - pmfileconflicttype_t type, const char *filestr, - const char *name1, const char *name2) +static alpm_list_t *add_fileconflict(alpm_handle_t *handle, + alpm_list_t *conflicts, alpm_fileconflicttype_t type, const char *filestr, + const char *name1, const char *name2) { - pmfileconflict_t *conflict; - MALLOC(conflict, sizeof(pmfileconflict_t), RET_ERR(PM_ERR_MEMORY, NULL)); + alpm_fileconflict_t *conflict; + MALLOC(conflict, sizeof(alpm_fileconflict_t), goto error); conflict->type = type; - STRDUP(conflict->target, name1, RET_ERR(PM_ERR_MEMORY, NULL)); - STRDUP(conflict->file, filestr, RET_ERR(PM_ERR_MEMORY, NULL)); + STRDUP(conflict->target, name1, goto error); + STRDUP(conflict->file, filestr, goto error); if(name2) { - STRDUP(conflict->ctarget, name2, RET_ERR(PM_ERR_MEMORY, NULL)); + STRDUP(conflict->ctarget, name2, goto error); } else { - conflict->ctarget = ""; + STRDUP(conflict->ctarget, "", goto error); } conflicts = alpm_list_add(conflicts, conflict); - _alpm_log(PM_LOG_DEBUG, "found file conflict %s, packages %s and %s\n", + _alpm_log(handle, ALPM_LOG_DEBUG, "found file conflict %s, packages %s and %s\n", filestr, name1, name2 ? name2 : "(filesystem)"); - return(conflicts); + return conflicts; + +error: + RET_ERR(handle, ALPM_ERR_MEMORY, conflicts); } -void _alpm_fileconflict_free(pmfileconflict_t *conflict) +void _alpm_fileconflict_free(alpm_fileconflict_t *conflict) { - if(strlen(conflict->ctarget) > 0) { - FREE(conflict->ctarget); - } - FREE(conflict->file);; + FREE(conflict->ctarget); + FREE(conflict->file); FREE(conflict->target); FREE(conflict); } -static int dir_belongsto_pkg(const char *dirpath, pmpkg_t *pkg) +const alpm_file_t *_alpm_filelist_contains(alpm_filelist_t *filelist, + const char *name) +{ + size_t i; + const alpm_file_t *file = filelist->files; + for(i = 0; i < filelist->count; i++) { + if(strcmp(file->name, name) == 0) { + return file; + } + file++; + } + return NULL; +} + +static int dir_belongsto_pkg(const char *root, const char *dirpath, + alpm_pkg_t *pkg) { - struct dirent *ent = NULL; struct stat sbuf; char path[PATH_MAX]; char abspath[PATH_MAX]; + struct dirent *ent = NULL; DIR *dir; - snprintf(abspath, PATH_MAX, "%s%s", handle->root, dirpath); + snprintf(abspath, PATH_MAX, "%s%s", root, dirpath); dir = opendir(abspath); if(dir == NULL) { - return(1); + return 1; } + while((ent = readdir(dir)) != NULL) { const char *name = ent->d_name; @@ -354,44 +355,43 @@ static int dir_belongsto_pkg(const char *dirpath, pmpkg_t *pkg) continue; } snprintf(path, PATH_MAX, "%s/%s", dirpath, name); - snprintf(abspath, PATH_MAX, "%s%s", handle->root, path); + snprintf(abspath, PATH_MAX, "%s%s", root, path); if(stat(abspath, &sbuf) != 0) { continue; } if(S_ISDIR(sbuf.st_mode)) { - if(dir_belongsto_pkg(path, pkg)) { + if(dir_belongsto_pkg(root, path, pkg)) { continue; } else { closedir(dir); - return(0); + return 0; } } else { - if(alpm_list_find_str(alpm_pkg_get_files(pkg), path)) { + if(_alpm_filelist_contains(alpm_pkg_get_files(pkg), path)) { continue; } else { closedir(dir); - return(0); + return 0; } } } closedir(dir); - return(1); + return 1; } /* Find file conflicts that may occur during the transaction with two checks: * 1: check every target against every target * 2: check every target against the filesystem */ -alpm_list_t *_alpm_db_find_fileconflicts(pmdb_t *db, pmtrans_t *trans, +alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle, alpm_list_t *upgrade, alpm_list_t *remove) { - alpm_list_t *i, *j, *conflicts = NULL; + alpm_list_t *i, *conflicts = NULL; size_t numtargs = alpm_list_count(upgrade); size_t current; + alpm_trans_t *trans = handle->trans; - ALPM_LOG_FUNC; - - if(db == NULL || upgrade == NULL || trans == NULL) { - return(NULL); + if(!upgrade) { + return NULL; } /* TODO this whole function needs a huge change, which hopefully will @@ -399,61 +399,75 @@ alpm_list_t *_alpm_db_find_fileconflicts(pmdb_t *db, pmtrans_t *trans, * here as we do when we actually extract files in add.c with our 12 * different cases. */ for(current = 0, i = upgrade; i; i = i->next, current++) { - alpm_list_t *k, *tmpfiles = NULL; - pmpkg_t *p1, *p2, *dbpkg; - char path[PATH_MAX+1]; - - p1 = i->data; - if(!p1) { - continue; - } + alpm_pkg_t *p1 = i->data; + alpm_list_t *j; + alpm_filelist_t tmpfiles; + alpm_pkg_t *dbpkg; + size_t filenum; int percent = (current * 100) / numtargs; - PROGRESS(trans, PM_TRANS_PROGRESS_CONFLICTS_START, "", percent, + PROGRESS(trans, ALPM_TRANS_PROGRESS_CONFLICTS_START, "", percent, numtargs, current); /* CHECK 1: check every target against every target */ - _alpm_log(PM_LOG_DEBUG, "searching for file conflicts: %s\n", + _alpm_log(handle, ALPM_LOG_DEBUG, "searching for file conflicts: %s\n", alpm_pkg_get_name(p1)); for(j = i->next; j; j = j->next) { - p2 = j->data; - if(!p2) { - continue; - } - tmpfiles = chk_fileconflicts(alpm_pkg_get_files(p1), alpm_pkg_get_files(p2)); - - if(tmpfiles) { - for(k = tmpfiles; k; k = k->next) { + alpm_list_t *common_files; + alpm_pkg_t *p2 = j->data; + common_files = filelist_operation(alpm_pkg_get_files(p1), + alpm_pkg_get_files(p2), INTERSECT); + + if(common_files) { + alpm_list_t *k; + char path[PATH_MAX]; + for(k = common_files; k; k = k->next) { snprintf(path, PATH_MAX, "%s%s", handle->root, (char *)k->data); - conflicts = add_fileconflict(conflicts, PM_FILECONFLICT_TARGET, path, + conflicts = add_fileconflict(handle, conflicts, + ALPM_FILECONFLICT_TARGET, path, alpm_pkg_get_name(p1), alpm_pkg_get_name(p2)); + if(handle->pm_errno == ALPM_ERR_MEMORY) { + FREELIST(conflicts); + FREELIST(common_files); + return NULL; + } } - FREELIST(tmpfiles); + alpm_list_free(common_files); } } - /* declarations for second check */ - struct stat lsbuf, sbuf; - /* CHECK 2: check every target against the filesystem */ - _alpm_log(PM_LOG_DEBUG, "searching for filesystem conflicts: %s\n", p1->name); - dbpkg = _alpm_db_get_pkgfromcache(db, p1->name); + _alpm_log(handle, ALPM_LOG_DEBUG, "searching for filesystem conflicts: %s\n", + p1->name); + dbpkg = _alpm_db_get_pkgfromcache(handle->db_local, p1->name); /* Do two different checks here. If the package is currently installed, * then only check files that are new in the new package. If the package - * is not currently installed, then simply stat the whole filelist */ + * is not currently installed, then simply stat the whole filelist. Note + * that the former list needs to be freed while the latter list should NOT + * be freed. */ if(dbpkg) { + alpm_list_t *difference; /* older ver of package currently installed */ - tmpfiles = chk_filedifference(alpm_pkg_get_files(p1), - alpm_pkg_get_files(dbpkg)); + difference = filelist_operation(alpm_pkg_get_files(p1), + alpm_pkg_get_files(dbpkg), DIFFERENCE); + tmpfiles.count = alpm_list_count(difference); + tmpfiles.files = alpm_list_to_array(difference, tmpfiles.count, + sizeof(alpm_file_t)); + alpm_list_free(difference); } else { /* no version of package currently installed */ - tmpfiles = alpm_list_strdup(alpm_pkg_get_files(p1)); + tmpfiles = *alpm_pkg_get_files(p1); } - for(j = tmpfiles; j; j = j->next) { - const char *filestr = j->data, *relative_path; + for(filenum = 0; filenum < tmpfiles.count; filenum++) { + alpm_file_t *file = tmpfiles.files + filenum; + const char *filestr = file->name; + const char *relative_path; + alpm_list_t *k; /* have we acted on this conflict? */ int resolved_conflict = 0; + struct stat lsbuf; + char path[PATH_MAX]; snprintf(path, PATH_MAX, "%s%s", handle->root, filestr); @@ -461,14 +475,16 @@ alpm_list_t *_alpm_db_find_fileconflicts(pmdb_t *db, pmtrans_t *trans, if(_alpm_lstat(path, &lsbuf) != 0) { continue; } - stat(path, &sbuf); - if(path[strlen(path) - 1] == '/') { + if(S_ISDIR(file->mode)) { + struct stat sbuf; if(S_ISDIR(lsbuf.st_mode)) { - _alpm_log(PM_LOG_DEBUG, "%s is a directory, not a conflict\n", path); + _alpm_log(handle, ALPM_LOG_DEBUG, "%s is a directory, not a conflict\n", path); continue; - } else if(S_ISLNK(lsbuf.st_mode) && S_ISDIR(sbuf.st_mode)) { - _alpm_log(PM_LOG_DEBUG, + } + stat(path, &sbuf); + if(S_ISLNK(lsbuf.st_mode) && S_ISDIR(sbuf.st_mode)) { + _alpm_log(handle, ALPM_LOG_DEBUG, "%s is a symlink to a dir, hopefully not a conflict\n", path); continue; } @@ -478,38 +494,37 @@ alpm_list_t *_alpm_db_find_fileconflicts(pmdb_t *db, pmtrans_t *trans, path[strlen(path) - 1] = '\0'; } - _alpm_log(PM_LOG_DEBUG, "checking possible conflict: %s\n", path); + _alpm_log(handle, ALPM_LOG_DEBUG, "checking possible conflict: %s\n", path); relative_path = path + strlen(handle->root); /* Check remove list (will we remove the conflicting local file?) */ for(k = remove; k && !resolved_conflict; k = k->next) { - pmpkg_t *rempkg = k->data; - if(alpm_list_find_str(alpm_pkg_get_files(rempkg), relative_path)) { - _alpm_log(PM_LOG_DEBUG, - "local file will be removed, not a conflict: %s\n", - relative_path); + alpm_pkg_t *rempkg = k->data; + if(rempkg && _alpm_filelist_contains(alpm_pkg_get_files(rempkg), + relative_path)) { + _alpm_log(handle, ALPM_LOG_DEBUG, + "local file will be removed, not a conflict: %s\n", path); resolved_conflict = 1; } } /* Look at all the targets to see if file has changed hands */ for(k = upgrade; k && !resolved_conflict; k = k->next) { - p2 = k->data; + alpm_pkg_t *p2 = k->data; if(!p2 || strcmp(p1->name, p2->name) == 0) { continue; } - pmpkg_t *localp2 = _alpm_db_get_pkgfromcache(db, p2->name); + alpm_pkg_t *localp2 = _alpm_db_get_pkgfromcache(handle->db_local, p2->name); /* localp2->files will be removed (target conflicts are handled by CHECK 1) */ - if(localp2 && alpm_list_find_str(alpm_pkg_get_files(localp2), filestr)) { + if(localp2 && _alpm_filelist_contains(alpm_pkg_get_files(localp2), filestr)) { /* skip removal of file, but not add. this will prevent a second * package from removing the file when it was already installed * by its new owner (whether the file is in backup array or not */ - trans->skip_remove = alpm_list_add(trans->skip_remove, - strdup(filestr)); - _alpm_log(PM_LOG_DEBUG, - "file changed packages, adding to remove skiplist: %s\n", - filestr); + handle->trans->skip_remove = + alpm_list_add(handle->trans->skip_remove, strdup(filestr)); + _alpm_log(handle, ALPM_LOG_DEBUG, + "file changed packages, adding to remove skiplist: %s\n", path); resolved_conflict = 1; } } @@ -518,115 +533,67 @@ alpm_list_t *_alpm_db_find_fileconflicts(pmdb_t *db, pmtrans_t *trans, if(!resolved_conflict && S_ISDIR(lsbuf.st_mode) && dbpkg) { char *dir = malloc(strlen(filestr) + 2); sprintf(dir, "%s/", filestr); - if(alpm_list_find_str(alpm_pkg_get_files(dbpkg),dir)) { - _alpm_log(PM_LOG_DEBUG, "check if all files in %s belongs to %s\n", + if(_alpm_filelist_contains(alpm_pkg_get_files(dbpkg), dir)) { + _alpm_log(handle, ALPM_LOG_DEBUG, + "check if all files in %s belongs to %s\n", dir, dbpkg->name); - resolved_conflict = dir_belongsto_pkg(filestr, dbpkg); + resolved_conflict = dir_belongsto_pkg(handle->root, filestr, dbpkg); } free(dir); } if(!resolved_conflict && dbpkg) { - char *rpath = calloc(PATH_MAX+1, sizeof(char)); + char *rpath = calloc(PATH_MAX, sizeof(char)); const char *relative_rpath; if(!realpath(path, rpath)) { free(rpath); continue; } relative_rpath = rpath + strlen(handle->root); - if(alpm_list_find_str(alpm_pkg_get_files(dbpkg), relative_rpath)) { + if(_alpm_filelist_contains(alpm_pkg_get_files(dbpkg), relative_rpath)) { resolved_conflict = 1; } free(rpath); } + /* is the file unowned and in the backup list of the new package? */ + if(!resolved_conflict && _alpm_needbackup(filestr, p1)) { + alpm_list_t *local_pkgs = _alpm_db_get_pkgcache(handle->db_local); + int found = 0; + for(k = local_pkgs; k && !found; k = k->next) { + if(_alpm_filelist_contains(alpm_pkg_get_files(k->data), filestr)) { + found = 1; + } + } + if(!found) { + _alpm_log(handle, ALPM_LOG_DEBUG, + "file was unowned but in new backup list: %s\n", path); + resolved_conflict = 1; + } + } + if(!resolved_conflict) { - conflicts = add_fileconflict(conflicts, PM_FILECONFLICT_FILESYSTEM, - path, p1->name, NULL); + conflicts = add_fileconflict(handle, conflicts, + ALPM_FILECONFLICT_FILESYSTEM, path, p1->name, NULL); + if(handle->pm_errno == ALPM_ERR_MEMORY) { + FREELIST(conflicts); + if(dbpkg) { + /* only freed if it was generated from filelist_operation() */ + free(tmpfiles.files); + } + return NULL; + } } } - FREELIST(tmpfiles); + if(dbpkg) { + /* only freed if it was generated from filelist_operation() */ + free(tmpfiles.files); + } } - PROGRESS(trans, PM_TRANS_PROGRESS_CONFLICTS_START, "", 100, + PROGRESS(trans, ALPM_TRANS_PROGRESS_CONFLICTS_START, "", 100, numtargs, current); - return(conflicts); + return conflicts; } -const char SYMEXPORT *alpm_conflict_get_package1(pmconflict_t *conflict) -{ - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(conflict != NULL, return(NULL)); - - return conflict->package1; -} - -const char SYMEXPORT *alpm_conflict_get_package2(pmconflict_t *conflict) -{ - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(conflict != NULL, return(NULL)); - - return conflict->package2; -} - -const char SYMEXPORT *alpm_conflict_get_reason(pmconflict_t *conflict) -{ - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(conflict != NULL, return(NULL)); - - return conflict->reason; -} - -const char SYMEXPORT *alpm_fileconflict_get_target(pmfileconflict_t *conflict) -{ - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(conflict != NULL, return(NULL)); - - return conflict->target; -} - -pmfileconflicttype_t SYMEXPORT alpm_fileconflict_get_type(pmfileconflict_t *conflict) -{ - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(-1)); - ASSERT(conflict != NULL, return(-1)); - - return conflict->type; -} - -const char SYMEXPORT *alpm_fileconflict_get_file(pmfileconflict_t *conflict) -{ - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(conflict != NULL, return(NULL)); - - return conflict->file; -} - -const char SYMEXPORT *alpm_fileconflict_get_ctarget(pmfileconflict_t *conflict) -{ - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(conflict != NULL, return(NULL)); - - return conflict->ctarget; -} /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/conflict.h b/lib/libalpm/conflict.h index 418d3f61..8b7471fd 100644 --- a/lib/libalpm/conflict.h +++ b/lib/libalpm/conflict.h @@ -24,28 +24,17 @@ #include "db.h" #include "package.h" -struct __pmconflict_t { - char *package1; - char *package2; - char *reason; -}; +alpm_conflict_t *_alpm_conflict_dup(const alpm_conflict_t *conflict); +void _alpm_conflict_free(alpm_conflict_t *conflict); +alpm_list_t *_alpm_innerconflicts(alpm_handle_t *handle, alpm_list_t *packages); +alpm_list_t *_alpm_outerconflicts(alpm_db_t *db, alpm_list_t *packages); +alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle, + alpm_list_t *upgrade, alpm_list_t *remove); -struct __pmfileconflict_t { - char *target; - pmfileconflicttype_t type; - char *file; - char *ctarget; -}; +void _alpm_fileconflict_free(alpm_fileconflict_t *conflict); -pmconflict_t *_alpm_conflict_new(const char *package1, const char *package2, const char *reason); -pmconflict_t *_alpm_conflict_dup(const pmconflict_t *conflict); -void _alpm_conflict_free(pmconflict_t *conflict); -alpm_list_t *_alpm_innerconflicts(alpm_list_t *packages); -alpm_list_t *_alpm_outerconflicts(pmdb_t *db, alpm_list_t *packages); -alpm_list_t *_alpm_db_find_fileconflicts(pmdb_t *db, pmtrans_t *trans, - alpm_list_t *upgrade, alpm_list_t *remove); - -void _alpm_fileconflict_free(pmfileconflict_t *conflict); +const alpm_file_t *_alpm_filelist_contains(alpm_filelist_t *filelist, + const char *name); #endif /* _ALPM_CONFLICT_H */ diff --git a/lib/libalpm/db.c b/lib/libalpm/db.c index 1a3168b4..9e8e75bf 100644 --- a/lib/libalpm/db.c +++ b/lib/libalpm/db.c @@ -26,11 +26,8 @@ #include <stdio.h> #include <stdlib.h> -#include <errno.h> #include <string.h> -#include <sys/stat.h> #include <regex.h> -#include <time.h> /* libalpm */ #include "db.h" @@ -48,42 +45,40 @@ */ /** Register a sync database of packages. */ -pmdb_t SYMEXPORT *alpm_db_register_sync(const char *treename) +alpm_db_t SYMEXPORT *alpm_db_register_sync(alpm_handle_t *handle, + const char *treename, alpm_siglevel_t level) { - ALPM_LOG_FUNC; - /* Sanity checks */ - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, NULL)); - ASSERT(treename != NULL && strlen(treename) != 0, RET_ERR(PM_ERR_WRONG_ARGS, NULL)); + CHECK_HANDLE(handle, return NULL); + ASSERT(treename != NULL && strlen(treename) != 0, + RET_ERR(handle, ALPM_ERR_WRONG_ARGS, NULL)); /* Do not register a database if a transaction is on-going */ - ASSERT(handle->trans == NULL, RET_ERR(PM_ERR_TRANS_NOT_NULL, NULL)); + ASSERT(handle->trans == NULL, RET_ERR(handle, ALPM_ERR_TRANS_NOT_NULL, NULL)); - return(_alpm_db_register_sync(treename)); + return _alpm_db_register_sync(handle, treename, level); } /* Helper function for alpm_db_unregister{_all} */ -void _alpm_db_unregister(pmdb_t *db) +void _alpm_db_unregister(alpm_db_t *db) { if(db == NULL) { return; } - _alpm_log(PM_LOG_DEBUG, "unregistering database '%s'\n", db->treename); + _alpm_log(db->handle, ALPM_LOG_DEBUG, "unregistering database '%s'\n", db->treename); _alpm_db_free(db); } /** Unregister all package databases. */ -int SYMEXPORT alpm_db_unregister_all(void) +int SYMEXPORT alpm_db_unregister_all(alpm_handle_t *handle) { alpm_list_t *i; - pmdb_t *db; - - ALPM_LOG_FUNC; + alpm_db_t *db; /* Sanity checks */ - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + CHECK_HANDLE(handle, return -1); /* Do not unregister a database if a transaction is on-going */ - ASSERT(handle->trans == NULL, RET_ERR(PM_ERR_TRANS_NOT_NULL, -1)); + ASSERT(handle->trans == NULL, RET_ERR(handle, ALPM_ERR_TRANS_NOT_NULL, -1)); /* unregister all sync dbs */ for(i = handle->dbs_sync; i; i = i->next) { @@ -92,21 +87,21 @@ int SYMEXPORT alpm_db_unregister_all(void) i->data = NULL; } FREELIST(handle->dbs_sync); - return(0); + return 0; } /** Unregister a package database. */ -int SYMEXPORT alpm_db_unregister(pmdb_t *db) +int SYMEXPORT alpm_db_unregister(alpm_db_t *db) { int found = 0; - - ALPM_LOG_FUNC; + alpm_handle_t *handle; /* Sanity checks */ - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); - ASSERT(db != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); + ASSERT(db != NULL, return -1); /* Do not unregister a database if a transaction is on-going */ - ASSERT(handle->trans == NULL, RET_ERR(PM_ERR_TRANS_NOT_NULL, -1)); + handle = db->handle; + handle->pm_errno = 0; + ASSERT(handle->trans == NULL, RET_ERR(handle, ALPM_ERR_TRANS_NOT_NULL, -1)); if(db == handle->db_local) { handle->db_local = NULL; @@ -125,196 +120,219 @@ int SYMEXPORT alpm_db_unregister(pmdb_t *db) } if(!found) { - RET_ERR(PM_ERR_DB_NOT_FOUND, -1); + RET_ERR(handle, ALPM_ERR_DB_NOT_FOUND, -1); } db->ops->unregister(db); - return(0); + return 0; +} + +/** Get the serverlist of a database. */ +alpm_list_t SYMEXPORT *alpm_db_get_servers(const alpm_db_t *db) +{ + ASSERT(db != NULL, return NULL); + return db->servers; } /** Set the serverlist of a database. */ -int SYMEXPORT alpm_db_setserver(pmdb_t *db, const char *url) +int SYMEXPORT alpm_db_set_servers(alpm_db_t *db, alpm_list_t *servers) +{ + ASSERT(db != NULL, return -1); + if(db->servers) FREELIST(db->servers); + db->servers = servers; + return 0; +} + +static char *sanitize_url(const char *url) { - alpm_list_t *i; - int found = 0; char *newurl; - size_t len = 0; + size_t len = strlen(url); + + STRDUP(newurl, url, return NULL); + /* strip the trailing slash if one exists */ + if(newurl[len - 1] == '/') { + newurl[len - 1] = '\0'; + } + return newurl; +} - ALPM_LOG_FUNC; +/** Add a download server to a database. + * @param db database pointer + * @param url url of the server + * @return 0 on success, -1 on error (pm_errno is set accordingly) + */ +int SYMEXPORT alpm_db_add_server(alpm_db_t *db, const char *url) +{ + char *newurl; /* Sanity checks */ - ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); + ASSERT(db != NULL, return -1); + db->handle->pm_errno = 0; + ASSERT(url != NULL && strlen(url) != 0, RET_ERR(db->handle, ALPM_ERR_WRONG_ARGS, -1)); - for(i = handle->dbs_sync; i && !found; i = i->next) { - pmdb_t *sdb = i->data; - if(strcmp(db->treename, sdb->treename) == 0) { - found = 1; - } - } - if(!found) { - RET_ERR(PM_ERR_DB_NOT_FOUND, -1); + newurl = sanitize_url(url); + if(!newurl) { + return -1; } + db->servers = alpm_list_add(db->servers, newurl); + _alpm_log(db->handle, ALPM_LOG_DEBUG, "adding new server URL to database '%s': %s\n", + db->treename, newurl); - if(url) { - len = strlen(url); - } - if(len) { - newurl = strdup(url); - /* strip the trailing slash if one exists */ - if(newurl[len - 1] == '/') { - newurl[len - 1] = '\0'; - } - db->servers = alpm_list_add(db->servers, newurl); - _alpm_log(PM_LOG_DEBUG, "adding new server URL to database '%s': %s\n", + return 0; +} + +/** Remove a download server from a database. + * @param db database pointer + * @param url url of the server + * @return 0 on success, 1 on server not present, + * -1 on error (pm_errno is set accordingly) + */ +int SYMEXPORT alpm_db_remove_server(alpm_db_t *db, const char *url) +{ + char *newurl, *vdata = NULL; + + /* Sanity checks */ + ASSERT(db != NULL, return -1); + db->handle->pm_errno = 0; + ASSERT(url != NULL && strlen(url) != 0, RET_ERR(db->handle, ALPM_ERR_WRONG_ARGS, -1)); + + newurl = sanitize_url(url); + if(!newurl) { + return -1; + } + db->servers = alpm_list_remove_str(db->servers, newurl, &vdata); + free(newurl); + if(vdata) { + _alpm_log(db->handle, ALPM_LOG_DEBUG, "removed server URL from database '%s': %s\n", db->treename, newurl); - } else { - FREELIST(db->servers); - _alpm_log(PM_LOG_DEBUG, "serverlist flushed for '%s'\n", db->treename); + free(vdata); + return 0; } - return(0); + return 1; } /** Get the name of a package database. */ -const char SYMEXPORT *alpm_db_get_name(const pmdb_t *db) +const char SYMEXPORT *alpm_db_get_name(const alpm_db_t *db) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(db != NULL, return(NULL)); - + ASSERT(db != NULL, return NULL); return db->treename; } -/** Get a download URL for the package database. */ -const char SYMEXPORT *alpm_db_get_url(const pmdb_t *db) +/** Get the signature verification level for a database. */ +alpm_siglevel_t SYMEXPORT alpm_db_get_siglevel(alpm_db_t *db) { - char *url; - - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(db != NULL, return(NULL)); - ASSERT(db->servers != NULL, return(NULL)); - - url = (char*)db->servers->data; - - return(url); + ASSERT(db != NULL, return -1); + if(db->siglevel & ALPM_SIG_USE_DEFAULT) { + return alpm_option_get_default_siglevel(db->handle); + } else { + return db->siglevel; + } } +/** Check the validity of a database. */ +int SYMEXPORT alpm_db_get_valid(alpm_db_t *db) +{ + ASSERT(db != NULL, return -1); + db->handle->pm_errno = 0; + return db->ops->validate(db); +} /** Get a package entry from a package database. */ -pmpkg_t SYMEXPORT *alpm_db_get_pkg(pmdb_t *db, const char *name) +alpm_pkg_t SYMEXPORT *alpm_db_get_pkg(alpm_db_t *db, const char *name) { - ALPM_LOG_FUNC; + alpm_pkg_t *pkg; + ASSERT(db != NULL, return NULL); + db->handle->pm_errno = 0; + ASSERT(name != NULL && strlen(name) != 0, + RET_ERR(db->handle, ALPM_ERR_WRONG_ARGS, NULL)); - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(db != NULL, return(NULL)); - ASSERT(name != NULL && strlen(name) != 0, return(NULL)); - - return(_alpm_db_get_pkgfromcache(db, name)); + pkg = _alpm_db_get_pkgfromcache(db, name); + if(!pkg) { + RET_ERR(db->handle, ALPM_ERR_PKG_NOT_FOUND, NULL); + } + return pkg; } /** Get the package cache of a package database. */ -alpm_list_t SYMEXPORT *alpm_db_get_pkgcache(pmdb_t *db) +alpm_list_t SYMEXPORT *alpm_db_get_pkgcache(alpm_db_t *db) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(db != NULL, return(NULL)); - - return(_alpm_db_get_pkgcache(db)); + ASSERT(db != NULL, return NULL); + db->handle->pm_errno = 0; + return _alpm_db_get_pkgcache(db); } /** Get a group entry from a package database. */ -pmgrp_t SYMEXPORT *alpm_db_readgrp(pmdb_t *db, const char *name) +alpm_group_t SYMEXPORT *alpm_db_readgroup(alpm_db_t *db, const char *name) { - ALPM_LOG_FUNC; + ASSERT(db != NULL, return NULL); + db->handle->pm_errno = 0; + ASSERT(name != NULL && strlen(name) != 0, + RET_ERR(db->handle, ALPM_ERR_WRONG_ARGS, NULL)); - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(db != NULL, return(NULL)); - ASSERT(name != NULL && strlen(name) != 0, return(NULL)); - - return(_alpm_db_get_grpfromcache(db, name)); + return _alpm_db_get_groupfromcache(db, name); } /** Get the group cache of a package database. */ -alpm_list_t SYMEXPORT *alpm_db_get_grpcache(pmdb_t *db) +alpm_list_t SYMEXPORT *alpm_db_get_groupcache(alpm_db_t *db) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(db != NULL, return(NULL)); + ASSERT(db != NULL, return NULL); + db->handle->pm_errno = 0; - return(_alpm_db_get_grpcache(db)); + return _alpm_db_get_groupcache(db); } /** Searches a database. */ -alpm_list_t SYMEXPORT *alpm_db_search(pmdb_t *db, const alpm_list_t* needles) +alpm_list_t SYMEXPORT *alpm_db_search(alpm_db_t *db, const alpm_list_t* needles) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(db != NULL, return(NULL)); + ASSERT(db != NULL, return NULL); + db->handle->pm_errno = 0; - return(_alpm_db_search(db, needles)); + return _alpm_db_search(db, needles); } /** Set install reason for a package in db. */ -int SYMEXPORT alpm_db_set_pkgreason(pmdb_t *db, const char *name, pmpkgreason_t reason) +int SYMEXPORT alpm_db_set_pkgreason(alpm_handle_t *handle, alpm_pkg_t *pkg, + alpm_pkgreason_t reason) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); - ASSERT(db != NULL && name != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); - - pmpkg_t *pkg = _alpm_db_get_pkgfromcache(db, name); - if(pkg == NULL) { - RET_ERR(PM_ERR_PKG_NOT_FOUND, -1); - } - - _alpm_log(PM_LOG_DEBUG, "setting install reason %u for %s/%s\n", reason, db->treename, name); + CHECK_HANDLE(handle, return -1); + ASSERT(pkg != NULL, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1)); + ASSERT(pkg->origin == PKG_FROM_LOCALDB, + RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1)); + ASSERT(pkg->origin_data.db == handle->db_local, + RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1)); + + _alpm_log(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); + return 0; } /* set reason (in pkgcache) */ pkg->reason = reason; /* write DESC */ - if(_alpm_local_db_write(db, pkg, INFRQ_DESC)) { - RET_ERR(PM_ERR_DB_WRITE, -1); + if(_alpm_local_db_write(handle->db_local, pkg, INFRQ_DESC)) { + RET_ERR(handle, ALPM_ERR_DB_WRITE, -1); } - return(0); + return 0; } /** @} */ -pmdb_t *_alpm_db_new(const char *treename, int is_local) +alpm_db_t *_alpm_db_new(const char *treename, int is_local) { - pmdb_t *db; - - ALPM_LOG_FUNC; + alpm_db_t *db; - CALLOC(db, 1, sizeof(pmdb_t), RET_ERR(PM_ERR_MEMORY, NULL)); - STRDUP(db->treename, treename, RET_ERR(PM_ERR_MEMORY, NULL)); + CALLOC(db, 1, sizeof(alpm_db_t), return NULL); + STRDUP(db->treename, treename, return NULL); db->is_local = is_local; - return(db); + return db; } -void _alpm_db_free(pmdb_t *db) +void _alpm_db_free(alpm_db_t *db) { - ALPM_LOG_FUNC; - /* cleanup pkgcache */ _alpm_db_free_pkgcache(db); /* cleanup server list */ @@ -326,61 +344,65 @@ void _alpm_db_free(pmdb_t *db) return; } -const char *_alpm_db_path(pmdb_t *db) +const char *_alpm_db_path(alpm_db_t *db) { if(!db) { - return(NULL); + return NULL; } if(!db->_path) { const char *dbpath; size_t pathsize; - dbpath = alpm_option_get_dbpath(); + dbpath = alpm_option_get_dbpath(db->handle); if(!dbpath) { - _alpm_log(PM_LOG_ERROR, _("database path is undefined\n")); - RET_ERR(PM_ERR_DB_OPEN, NULL); + _alpm_log(db->handle, ALPM_LOG_ERROR, _("database path is undefined\n")); + RET_ERR(db->handle, ALPM_ERR_DB_OPEN, NULL); } if(db->is_local) { pathsize = strlen(dbpath) + strlen(db->treename) + 2; - CALLOC(db->_path, 1, pathsize, RET_ERR(PM_ERR_MEMORY, NULL)); + CALLOC(db->_path, 1, pathsize, RET_ERR(db->handle, ALPM_ERR_MEMORY, NULL)); sprintf(db->_path, "%s%s/", dbpath, db->treename); } else { pathsize = strlen(dbpath) + 5 + strlen(db->treename) + 4; - CALLOC(db->_path, 1, pathsize, RET_ERR(PM_ERR_MEMORY, NULL)); + CALLOC(db->_path, 1, pathsize, RET_ERR(db->handle, ALPM_ERR_MEMORY, NULL)); /* all sync DBs now reside in the sync/ subdir of the dbpath */ sprintf(db->_path, "%ssync/%s.db", dbpath, db->treename); } - _alpm_log(PM_LOG_DEBUG, "database path for tree %s set to %s\n", + _alpm_log(db->handle, ALPM_LOG_DEBUG, "database path for tree %s set to %s\n", db->treename, db->_path); } - return(db->_path); + return db->_path; } -int _alpm_db_version(pmdb_t *db) +char *_alpm_db_sig_path(alpm_db_t *db) { - if(!db) { - return(-1); - } - return(db->ops->version(db)); + char *sigpath; + size_t len; + const char *dbfile = _alpm_db_path(db); + if(!db || !dbfile) { + return NULL; + } + len = strlen(dbfile) + strlen(".sig") + 1; + CALLOC(sigpath, len, sizeof(char), RET_ERR(db->handle, ALPM_ERR_MEMORY, NULL)); + sprintf(sigpath, "%s.sig", dbfile); + return sigpath; } int _alpm_db_cmp(const void *d1, const void *d2) { - pmdb_t *db1 = (pmdb_t *)d1; - pmdb_t *db2 = (pmdb_t *)d2; - return(strcmp(db1->treename, db2->treename)); + alpm_db_t *db1 = (alpm_db_t *)d1; + alpm_db_t *db2 = (alpm_db_t *)d2; + return strcmp(db1->treename, db2->treename); } -alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles) +alpm_list_t *_alpm_db_search(alpm_db_t *db, const alpm_list_t *needles) { const alpm_list_t *i, *j, *k; alpm_list_t *ret = NULL; /* copy the pkgcache- we will free the list var after each needle */ alpm_list_t *list = alpm_list_copy(_alpm_db_get_pkgcache(db)); - ALPM_LOG_FUNC; - for(i = needles; i; i = i->next) { char *targ; regex_t reg; @@ -390,14 +412,14 @@ alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles) } ret = NULL; targ = i->data; - _alpm_log(PM_LOG_DEBUG, "searching for target '%s'\n", targ); + _alpm_log(db->handle, ALPM_LOG_DEBUG, "searching for target '%s'\n", targ); if(regcomp(®, targ, REG_EXTENDED | REG_NOSUB | REG_ICASE | REG_NEWLINE) != 0) { - RET_ERR(PM_ERR_INVALID_REGEX, NULL); + RET_ERR(db->handle, ALPM_ERR_INVALID_REGEX, NULL); } for(j = list; j; j = j->next) { - pmpkg_t *pkg = j->data; + alpm_pkg_t *pkg = j->data; const char *matched = NULL; const char *name = alpm_pkg_get_name(pkg); const char *desc = alpm_pkg_get_desc(pkg); @@ -407,7 +429,7 @@ alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles) matched = name; } /* check desc */ - else if (desc && regexec(®, desc, 0, 0, 0) == 0) { + else if(desc && regexec(®, desc, 0, 0, 0) == 0) { matched = desc; } /* TODO: should we be doing this, and should we print something @@ -415,7 +437,7 @@ alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles) if(!matched) { /* check provides */ for(k = alpm_pkg_get_provides(pkg); k; k = k->next) { - if (regexec(®, k->data, 0, 0, 0) == 0) { + if(regexec(®, k->data, 0, 0, 0) == 0) { matched = k->data; break; } @@ -424,7 +446,7 @@ alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles) if(!matched) { /* check groups */ for(k = alpm_pkg_get_groups(pkg); k; k = k->next) { - if (regexec(®, k->data, 0, 0, 0) == 0) { + if(regexec(®, k->data, 0, 0, 0) == 0) { matched = k->data; break; } @@ -432,7 +454,7 @@ alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles) } if(matched != NULL) { - _alpm_log(PM_LOG_DEBUG, " search target '%s' matched '%s'\n", + _alpm_log(db->handle, ALPM_LOG_DEBUG, " search target '%s' matched '%s'\n", targ, matched); ret = alpm_list_add(ret, pkg); } @@ -445,179 +467,176 @@ alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles) regfree(®); } - return(ret); + return ret; } /* 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(alpm_db_t *db) { - ALPM_LOG_FUNC; - - if(db == NULL) { - return(-1); - } _alpm_db_free_pkgcache(db); - _alpm_log(PM_LOG_DEBUG, "loading package cache for repository '%s'\n", + _alpm_log(db->handle, ALPM_LOG_DEBUG, "loading package cache for repository '%s'\n", db->treename); if(db->ops->populate(db) == -1) { - _alpm_log(PM_LOG_DEBUG, + _alpm_log(db->handle, ALPM_LOG_DEBUG, "failed to load package cache for repository '%s'\n", db->treename); - return(-1); + return -1; } - db->pkgcache_loaded = 1; - return(0); + db->status |= DB_STATUS_PKGCACHE; + return 0; } -void _alpm_db_free_pkgcache(pmdb_t *db) +static void free_groupcache(alpm_db_t *db) { - ALPM_LOG_FUNC; + alpm_list_t *lg; - if(db == NULL || !db->pkgcache_loaded) { + if(db == NULL || !(db->status & DB_STATUS_GRPCACHE)) { return; } - _alpm_log(PM_LOG_DEBUG, "freeing package cache for repository '%s'\n", - db->treename); + _alpm_log(db->handle, ALPM_LOG_DEBUG, + "freeing group cache for repository '%s'\n", db->treename); + + for(lg = db->grpcache; lg; lg = lg->next) { + _alpm_group_free(lg->data); + lg->data = NULL; + } + FREELIST(db->grpcache); + db->status &= ~DB_STATUS_GRPCACHE; +} + +void _alpm_db_free_pkgcache(alpm_db_t *db) +{ + if(db == NULL || !(db->status & DB_STATUS_PKGCACHE)) { + return; + } + + _alpm_log(db->handle, ALPM_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); + free_groupcache(db); } -pmpkghash_t *_alpm_db_get_pkgcache_hash(pmdb_t *db) +alpm_pkghash_t *_alpm_db_get_pkgcache_hash(alpm_db_t *db) { - ALPM_LOG_FUNC; - if(db == NULL) { - return(NULL); + return NULL; } - if(!db->pkgcache_loaded) { - _alpm_db_load_pkgcache(db); + if(!(db->status & DB_STATUS_VALID)) { + RET_ERR(db->handle, ALPM_ERR_DB_INVALID, NULL); } - /* hmmm, still NULL ?*/ - if(!db->pkgcache) { - _alpm_log(PM_LOG_DEBUG, "warning: pkgcache is NULL for db '%s'\n", db->treename); + if(!(db->status & DB_STATUS_PKGCACHE)) { + load_pkgcache(db); } - return(db->pkgcache); + return db->pkgcache; } -alpm_list_t *_alpm_db_get_pkgcache(pmdb_t *db) +alpm_list_t *_alpm_db_get_pkgcache(alpm_db_t *db) { - ALPM_LOG_FUNC; - - pmpkghash_t *hash = _alpm_db_get_pkgcache_hash(db); + alpm_pkghash_t *hash = _alpm_db_get_pkgcache_hash(db); if(hash == NULL) { - return(NULL); + return NULL; } - return(hash->list); + return hash->list; } /* "duplicate" pkg then add it to pkgcache */ -int _alpm_db_add_pkgincache(pmdb_t *db, pmpkg_t *pkg) +int _alpm_db_add_pkgincache(alpm_db_t *db, alpm_pkg_t *pkg) { - pmpkg_t *newpkg; + alpm_pkg_t *newpkg; - ALPM_LOG_FUNC; - - if(db == NULL || !db->pkgcache_loaded || pkg == NULL) { - return(-1); + if(db == NULL || pkg == NULL || !(db->status & DB_STATUS_PKGCACHE)) { + return -1; } newpkg = _alpm_pkg_dup(pkg); if(newpkg == NULL) { - return(-1); + return -1; } - _alpm_log(PM_LOG_DEBUG, "adding entry '%s' in '%s' cache\n", + _alpm_log(db->handle, ALPM_LOG_DEBUG, "adding entry '%s' in '%s' cache\n", alpm_pkg_get_name(newpkg), db->treename); db->pkgcache = _alpm_pkghash_add_sorted(db->pkgcache, newpkg); - _alpm_db_free_grpcache(db); + free_groupcache(db); - return(0); + return 0; } -int _alpm_db_remove_pkgfromcache(pmdb_t *db, pmpkg_t *pkg) +int _alpm_db_remove_pkgfromcache(alpm_db_t *db, alpm_pkg_t *pkg) { - pmpkg_t *data = NULL; - - ALPM_LOG_FUNC; + alpm_pkg_t *data = NULL; - if(db == NULL || !db->pkgcache_loaded || pkg == NULL) { - return(-1); + if(db == NULL || pkg == NULL || !(db->status & DB_STATUS_PKGCACHE)) { + return -1; } - _alpm_log(PM_LOG_DEBUG, "removing entry '%s' from '%s' cache\n", + _alpm_log(db->handle, ALPM_LOG_DEBUG, "removing entry '%s' from '%s' cache\n", alpm_pkg_get_name(pkg), db->treename); db->pkgcache = _alpm_pkghash_remove(db->pkgcache, pkg, &data); if(data == NULL) { /* package not found */ - _alpm_log(PM_LOG_DEBUG, "cannot remove entry '%s' from '%s' cache: not found\n", + _alpm_log(db->handle, ALPM_LOG_DEBUG, "cannot remove entry '%s' from '%s' cache: not found\n", alpm_pkg_get_name(pkg), db->treename); - return(-1); + return -1; } _alpm_pkg_free(data); - _alpm_db_free_grpcache(db); + free_groupcache(db); - return(0); + return 0; } -pmpkg_t *_alpm_db_get_pkgfromcache(pmdb_t *db, const char *target) +alpm_pkg_t *_alpm_db_get_pkgfromcache(alpm_db_t *db, const char *target) { - ALPM_LOG_FUNC; - if(db == NULL) { - return(NULL); + return NULL; } - pmpkghash_t *pkgcache = _alpm_db_get_pkgcache_hash(db); + alpm_pkghash_t *pkgcache = _alpm_db_get_pkgcache_hash(db); if(!pkgcache) { - _alpm_log(PM_LOG_DEBUG, "warning: failed to get '%s' from NULL pkgcache\n", - target); - return(NULL); + return NULL; } - return(_alpm_pkghash_find(pkgcache, target)); + return _alpm_pkghash_find(pkgcache, target); } /* Returns a new group cache from db. */ -int _alpm_db_load_grpcache(pmdb_t *db) +static int load_grpcache(alpm_db_t *db) { alpm_list_t *lp; - ALPM_LOG_FUNC; - if(db == NULL) { - return(-1); + return -1; } - _alpm_log(PM_LOG_DEBUG, "loading group cache for repository '%s'\n", + _alpm_log(db->handle, ALPM_LOG_DEBUG, "loading group cache for repository '%s'\n", db->treename); for(lp = _alpm_db_get_pkgcache(db); lp; lp = lp->next) { const alpm_list_t *i; - pmpkg_t *pkg = lp->data; + alpm_pkg_t *pkg = lp->data; for(i = alpm_pkg_get_groups(pkg); i; i = i->next) { const char *grpname = i->data; alpm_list_t *j; - pmgrp_t *grp = NULL; + alpm_group_t *grp = NULL; int found = 0; /* first look through the group cache for a group with this name */ @@ -635,71 +654,54 @@ int _alpm_db_load_grpcache(pmdb_t *db) continue; } /* we didn't find the group, so create a new one with this name */ - grp = _alpm_grp_new(grpname); + grp = _alpm_group_new(grpname); + if(!grp) { + free_groupcache(db); + return -1; + } grp->packages = alpm_list_add(grp->packages, pkg); db->grpcache = alpm_list_add(db->grpcache, grp); } } - db->grpcache_loaded = 1; - return(0); + db->status |= DB_STATUS_GRPCACHE; + return 0; } -void _alpm_db_free_grpcache(pmdb_t *db) +alpm_list_t *_alpm_db_get_groupcache(alpm_db_t *db) { - alpm_list_t *lg; - - ALPM_LOG_FUNC; - - if(db == NULL || !db->grpcache_loaded) { - return; - } - - _alpm_log(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; + if(db == NULL) { + return NULL; } - FREELIST(db->grpcache); - db->grpcache_loaded = 0; -} - -alpm_list_t *_alpm_db_get_grpcache(pmdb_t *db) -{ - ALPM_LOG_FUNC; - if(db == NULL) { - return(NULL); + if(!(db->status & DB_STATUS_VALID)) { + RET_ERR(db->handle, ALPM_ERR_DB_INVALID, NULL); } - if(!db->grpcache_loaded) { - _alpm_db_load_grpcache(db); + if(!(db->status & DB_STATUS_GRPCACHE)) { + load_grpcache(db); } - return(db->grpcache); + return db->grpcache; } -pmgrp_t *_alpm_db_get_grpfromcache(pmdb_t *db, const char *target) +alpm_group_t *_alpm_db_get_groupfromcache(alpm_db_t *db, const char *target) { alpm_list_t *i; - ALPM_LOG_FUNC; - if(db == NULL || target == NULL || strlen(target) == 0) { - return(NULL); + return NULL; } - for(i = _alpm_db_get_grpcache(db); i; i = i->next) { - pmgrp_t *info = i->data; + for(i = _alpm_db_get_groupcache(db); i; i = i->next) { + alpm_group_t *info = i->data; if(strcmp(info->name, target) == 0) { - return(info); + return info; } } - return(NULL); + return NULL; } /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/db.h b/lib/libalpm/db.h index 75776d71..a09c7e26 100644 --- a/lib/libalpm/db.h +++ b/lib/libalpm/db.h @@ -22,81 +22,88 @@ #ifndef _ALPM_DB_H #define _ALPM_DB_H -#include "alpm.h" -#include "pkghash.h" - #include <time.h> /* libarchive */ #include <archive.h> #include <archive_entry.h> +#include "alpm.h" +#include "pkghash.h" +#include "signing.h" + /* Database entries */ -typedef enum _pmdbinfrq_t { +typedef enum _alpm_dbinfrq_t { INFRQ_BASE = 1, INFRQ_DESC = (1 << 1), INFRQ_FILES = (1 << 2), INFRQ_SCRIPTLET = (1 << 3), INFRQ_DSIZE = (1 << 4), /* ALL should be info stored in the package or database */ - INFRQ_ALL = 0x1F -} pmdbinfrq_t; + INFRQ_ALL = 0x1F, + INFRQ_ERROR = (1 << 31) +} alpm_dbinfrq_t; + +/** Database status. Bitflags. */ +enum _alpm_dbstatus_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 *); - int (*version) (pmdb_t *); + int (*validate) (alpm_db_t *); + int (*populate) (alpm_db_t *); + void (*unregister) (alpm_db_t *); }; /* Database */ -struct __pmdb_t { +struct __alpm_db_t { + alpm_handle_t *handle; 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; - pmpkghash_t *pkgcache; + /* flags determining validity, loaded caches, etc. */ + enum _alpm_dbstatus_t status; + alpm_pkghash_t *pkgcache; alpm_list_t *grpcache; alpm_list_t *servers; + alpm_siglevel_t siglevel; struct db_operations *ops; }; /* db.c, database general calls */ -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); -int _alpm_db_version(pmdb_t *db); +alpm_db_t *_alpm_db_new(const char *treename, int is_local); +void _alpm_db_free(alpm_db_t *db); +const char *_alpm_db_path(alpm_db_t *db); +char *_alpm_db_sig_path(alpm_db_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(void); -pmdb_t *_alpm_db_register_sync(const char *treename); -void _alpm_db_unregister(pmdb_t *db); +alpm_list_t *_alpm_db_search(alpm_db_t *db, const alpm_list_t *needles); +alpm_db_t *_alpm_db_register_local(alpm_handle_t *handle); +alpm_db_t *_alpm_db_register_sync(alpm_handle_t *handle, const char *treename, + alpm_siglevel_t level); +void _alpm_db_unregister(alpm_db_t *db); /* be_*.c, backend specific calls */ -int _alpm_local_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq); -int _alpm_local_db_prepare(pmdb_t *db, pmpkg_t *info); -int _alpm_local_db_write(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq); -int _alpm_local_db_remove(pmdb_t *db, pmpkg_t *info); +int _alpm_local_db_prepare(alpm_db_t *db, alpm_pkg_t *info); +int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, alpm_dbinfrq_t inforeq); +int _alpm_local_db_remove(alpm_db_t *db, alpm_pkg_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); -pmpkghash_t *_alpm_db_get_pkgcache_hash(pmdb_t *db); -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); +void _alpm_db_free_pkgcache(alpm_db_t *db); +int _alpm_db_add_pkgincache(alpm_db_t *db, alpm_pkg_t *pkg); +int _alpm_db_remove_pkgfromcache(alpm_db_t *db, alpm_pkg_t *pkg); +alpm_pkghash_t *_alpm_db_get_pkgcache_hash(alpm_db_t *db); +alpm_list_t *_alpm_db_get_pkgcache(alpm_db_t *db); +alpm_pkg_t *_alpm_db_get_pkgfromcache(alpm_db_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); +alpm_list_t *_alpm_db_get_groupcache(alpm_db_t *db); +alpm_group_t *_alpm_db_get_groupfromcache(alpm_db_t *db, const char *target); #endif /* _ALPM_DB_H */ diff --git a/lib/libalpm/delta.c b/lib/libalpm/delta.c index 10c982f2..1b7e3eec 100644 --- a/lib/libalpm/delta.c +++ b/lib/libalpm/delta.c @@ -34,51 +34,18 @@ #include "log.h" #include "graph.h" -/** \addtogroup alpm_deltas Delta Functions - * @brief Functions to manipulate libalpm deltas - * @{ - */ - -const char SYMEXPORT *alpm_delta_get_from(pmdelta_t *delta) -{ - ASSERT(delta != NULL, return(NULL)); - return(delta->from); -} - -const char SYMEXPORT *alpm_delta_get_to(pmdelta_t *delta) -{ - ASSERT(delta != NULL, return(NULL)); - return(delta->to); -} - -const char SYMEXPORT *alpm_delta_get_filename(pmdelta_t *delta) -{ - ASSERT(delta != NULL, return(NULL)); - return(delta->delta); -} - -const char SYMEXPORT *alpm_delta_get_md5sum(pmdelta_t *delta) -{ - ASSERT(delta != NULL, return(NULL)); - return(delta->delta_md5); -} - -off_t SYMEXPORT alpm_delta_get_size(pmdelta_t *delta) -{ - ASSERT(delta != NULL, return(-1)); - return(delta->delta_size); -} - -/** @} */ - static alpm_list_t *graph_init(alpm_list_t *deltas, int reverse) { alpm_list_t *i, *j; alpm_list_t *vertices = NULL; /* create the vertices */ for(i = deltas; i; i = i->next) { - pmgraph_t *v = _alpm_graph_new(); - pmdelta_t *vdelta = i->data; + alpm_graph_t *v = _alpm_graph_new(); + if(!v) { + alpm_list_free(vertices); + return NULL; + } + alpm_delta_t *vdelta = i->data; vdelta->download_size = vdelta->delta_size; v->weight = LONG_MAX; v->data = vdelta; @@ -87,12 +54,12 @@ static alpm_list_t *graph_init(alpm_list_t *deltas, int reverse) /* compute the edges */ for(i = vertices; i; i = i->next) { - pmgraph_t *v_i = i->data; - pmdelta_t *d_i = v_i->data; + alpm_graph_t *v_i = i->data; + alpm_delta_t *d_i = v_i->data; /* loop a second time so we make all possible comparisons */ for(j = vertices; j; j = j->next) { - pmgraph_t *v_j = j->data; - pmdelta_t *d_j = v_j->data; + alpm_graph_t *v_j = j->data; + alpm_delta_t *d_j = v_j->data; /* We want to create a delta tree like the following: * 1_to_2 * | @@ -108,20 +75,20 @@ static alpm_list_t *graph_init(alpm_list_t *deltas, int reverse) } v_i->childptr = v_i->children; } - return(vertices); + return vertices; } -static void graph_init_size(alpm_list_t *vertices) +static void graph_init_size(alpm_handle_t *handle, alpm_list_t *vertices) { alpm_list_t *i; for(i = vertices; i; i = i->next) { char *fpath, *md5sum; - pmgraph_t *v = i->data; - pmdelta_t *vdelta = v->data; + alpm_graph_t *v = i->data; + alpm_delta_t *vdelta = v->data; /* determine whether the delta file already exists */ - fpath = _alpm_filecache_find(vdelta->delta); + fpath = _alpm_filecache_find(handle, vdelta->delta); md5sum = alpm_compute_md5sum(fpath); if(fpath && md5sum && strcmp(md5sum, vdelta->delta_md5) == 0) { vdelta->download_size = 0; @@ -130,7 +97,7 @@ static void graph_init_size(alpm_list_t *vertices) FREE(md5sum); /* determine whether a base 'from' file exists */ - fpath = _alpm_filecache_find(vdelta->from); + fpath = _alpm_filecache_find(handle, vdelta->from); if(fpath) { v->weight = vdelta->download_size; } @@ -142,12 +109,12 @@ static void graph_init_size(alpm_list_t *vertices) static void dijkstra(alpm_list_t *vertices) { alpm_list_t *i; - pmgraph_t *v; + alpm_graph_t *v; while(1) { v = NULL; /* find the smallest vertice not visited yet */ for(i = vertices; i; i = i->next) { - pmgraph_t *v_i = i->data; + alpm_graph_t *v_i = i->data; if(v_i->state == -1) { continue; @@ -165,8 +132,8 @@ static void dijkstra(alpm_list_t *vertices) v->childptr = v->children; while(v->childptr) { - pmgraph_t *v_c = v->childptr->data; - pmdelta_t *d_c = v_c->data; + alpm_graph_t *v_c = v->childptr->data; + alpm_delta_t *d_c = v_c->data; if(v_c->weight > v->weight + d_c->download_size) { v_c->weight = v->weight + d_c->download_size; v_c->parent = v; @@ -181,13 +148,13 @@ static void dijkstra(alpm_list_t *vertices) static off_t shortest_path(alpm_list_t *vertices, const char *to, alpm_list_t **path) { alpm_list_t *i; - pmgraph_t *v = NULL; + alpm_graph_t *v = NULL; off_t bestsize = 0; alpm_list_t *rpath = NULL; for(i = vertices; i; i = i->next) { - pmgraph_t *v_i = i->data; - pmdelta_t *d_i = v_i->data; + alpm_graph_t *v_i = i->data; + alpm_delta_t *d_i = v_i->data; if(strcmp(d_i->to, to) == 0) { if(v == NULL || v_i->weight < v->weight) { @@ -198,54 +165,53 @@ static off_t shortest_path(alpm_list_t *vertices, const char *to, alpm_list_t ** } while(v != NULL) { - pmdelta_t *vdelta = v->data; + alpm_delta_t *vdelta = v->data; rpath = alpm_list_add(rpath, vdelta); v = v->parent; } *path = alpm_list_reverse(rpath); alpm_list_free(rpath); - return(bestsize); + return bestsize; } /** Calculates the shortest path from one version to another. * The shortest path is defined as the path with the smallest combined * size, not the length of the path. - * @param deltas the list of pmdelta_t * objects that a file has + * @param handle the context handle + * @param deltas the list of alpm_delta_t * objects that a file has * @param to the file to start the search at - * @param path the pointer to a list location where pmdelta_t * objects that + * @param path the pointer to a list location where alpm_delta_t * objects that * have the smallest size are placed. NULL is set if there is no path * possible with the files available. * @return the size of the path stored, or LONG_MAX if path is unfindable */ -off_t _alpm_shortest_delta_path(alpm_list_t *deltas, +off_t _alpm_shortest_delta_path(alpm_handle_t *handle, alpm_list_t *deltas, const char *to, alpm_list_t **path) { alpm_list_t *bestpath = NULL; alpm_list_t *vertices; off_t bestsize = LONG_MAX; - ALPM_LOG_FUNC; - if(deltas == NULL) { *path = NULL; - return(bestsize); + return bestsize; } - _alpm_log(PM_LOG_DEBUG, "started delta shortest-path search for '%s'\n", to); + _alpm_log(handle, ALPM_LOG_DEBUG, "started delta shortest-path search for '%s'\n", to); vertices = graph_init(deltas, 0); - graph_init_size(vertices); + graph_init_size(handle, vertices); dijkstra(vertices); bestsize = shortest_path(vertices, to, &bestpath); - _alpm_log(PM_LOG_DEBUG, "delta shortest-path search complete : '%jd'\n", (intmax_t)bestsize); + _alpm_log(handle, ALPM_LOG_DEBUG, "delta shortest-path search complete : '%jd'\n", (intmax_t)bestsize); alpm_list_free_inner(vertices, _alpm_graph_free); alpm_list_free(vertices); *path = bestpath; - return(bestsize); + return bestsize; } static alpm_list_t *find_unused(alpm_list_t *deltas, const char *to, off_t quota) @@ -256,8 +222,8 @@ static alpm_list_t *find_unused(alpm_list_t *deltas, const char *to, off_t quota vertices = graph_init(deltas, 1); for(i = vertices; i; i = i->next) { - pmgraph_t *v = i->data; - pmdelta_t *vdelta = v->data; + alpm_graph_t *v = i->data; + alpm_delta_t *vdelta = v->data; if(strcmp(vdelta->to, to) == 0) { v->weight = vdelta->download_size; @@ -265,39 +231,45 @@ static alpm_list_t *find_unused(alpm_list_t *deltas, const char *to, off_t quota } dijkstra(vertices); for(i = vertices; i; i = i->next) { - pmgraph_t *v = i->data; - pmdelta_t *vdelta = v->data; + alpm_graph_t *v = i->data; + alpm_delta_t *vdelta = v->data; if(v->weight > quota) { unused = alpm_list_add(unused, vdelta->delta); } } alpm_list_free_inner(vertices, _alpm_graph_free); alpm_list_free(vertices); - return(unused); + return unused; } -alpm_list_t SYMEXPORT *alpm_pkg_unused_deltas(pmpkg_t *pkg) +/** \addtogroup alpm_deltas Delta Functions + * @brief Functions to manipulate libalpm deltas + * @{ + */ + +alpm_list_t SYMEXPORT *alpm_pkg_unused_deltas(alpm_pkg_t *pkg) { off_t pkgsize = alpm_pkg_get_size(pkg); alpm_list_t *unused = find_unused( alpm_pkg_get_deltas(pkg), alpm_pkg_get_filename(pkg), pkgsize * MAX_DELTA_RATIO); - return(unused); + return unused; } +/** @} */ -/** Parses the string representation of a pmdelta_t object. +/** Parses the string representation of a alpm_delta_t object. * This function assumes that the string is in the correct format. * This format is as follows: * $deltafile $deltamd5 $deltasize $oldfile $newfile * @param line the string to parse - * @return A pointer to the new pmdelta_t object + * @return A pointer to the new alpm_delta_t object */ /* TODO this does not really belong here, but in a parsing lib */ -pmdelta_t *_alpm_delta_parse(char *line) +alpm_delta_t *_alpm_delta_parse(char *line) { - pmdelta_t *delta; + alpm_delta_t *delta; char *tmp = line, *tmp2; regex_t reg; @@ -308,21 +280,21 @@ pmdelta_t *_alpm_delta_parse(char *line) if(regexec(®, line, 0, 0, 0) != 0) { /* delta line is invalid, return NULL */ regfree(®); - return(NULL); + return NULL; } regfree(®); - CALLOC(delta, 1, sizeof(pmdelta_t), RET_ERR(PM_ERR_MEMORY, NULL)); + CALLOC(delta, 1, sizeof(alpm_delta_t), return NULL); tmp2 = tmp; tmp = strchr(tmp, ' '); *(tmp++) = '\0'; - STRDUP(delta->delta, tmp2, RET_ERR(PM_ERR_MEMORY, NULL)); + STRDUP(delta->delta, tmp2, return NULL); tmp2 = tmp; tmp = strchr(tmp, ' '); *(tmp++) = '\0'; - STRDUP(delta->delta_md5, tmp2, RET_ERR(PM_ERR_MEMORY, NULL)); + STRDUP(delta->delta_md5, tmp2, return NULL); tmp2 = tmp; tmp = strchr(tmp, ' '); @@ -332,23 +304,35 @@ pmdelta_t *_alpm_delta_parse(char *line) tmp2 = tmp; tmp = strchr(tmp, ' '); *(tmp++) = '\0'; - STRDUP(delta->from, tmp2, RET_ERR(PM_ERR_MEMORY, NULL)); + STRDUP(delta->from, tmp2, return NULL); tmp2 = tmp; - STRDUP(delta->to, tmp2, RET_ERR(PM_ERR_MEMORY, NULL)); - - _alpm_log(PM_LOG_DEBUG, "delta : %s %s '%jd'\n", delta->from, delta->to, (intmax_t)delta->delta_size); + STRDUP(delta->to, tmp2, return NULL); - return(delta); + return delta; } -void _alpm_delta_free(pmdelta_t *delta) +void _alpm_delta_free(alpm_delta_t *delta) { - FREE(delta->from); - FREE(delta->to); FREE(delta->delta); FREE(delta->delta_md5); + FREE(delta->from); + FREE(delta->to); FREE(delta); } +alpm_delta_t *_alpm_delta_dup(const alpm_delta_t *delta) +{ + alpm_delta_t *newdelta; + CALLOC(newdelta, 1, sizeof(alpm_delta_t), return NULL); + STRDUP(newdelta->delta, delta->delta, return NULL); + STRDUP(newdelta->delta_md5, delta->delta_md5, return NULL); + STRDUP(newdelta->from, delta->from, return NULL); + STRDUP(newdelta->to, delta->to, return NULL); + newdelta->delta_size = delta->delta_size; + newdelta->download_size = delta->download_size; + + return newdelta; +} + /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/delta.h b/lib/libalpm/delta.h index d7a81c47..05df4207 100644 --- a/lib/libalpm/delta.h +++ b/lib/libalpm/delta.h @@ -20,28 +20,16 @@ #ifndef _ALPM_DELTA_H #define _ALPM_DELTA_H +#include "config.h" /* ensure off_t is correct length */ + #include <sys/types.h> /* off_t */ #include "alpm.h" -struct __pmdelta_t { - /** filename of the delta patch */ - char *delta; - /** md5sum of the delta file */ - char *delta_md5; - /** filesize of the delta file */ - off_t delta_size; - /** filename of the 'before' file */ - char *from; - /** filename of the 'after' file */ - char *to; - /** download filesize of the delta file */ - off_t download_size; -}; - -pmdelta_t *_alpm_delta_parse(char *line); -void _alpm_delta_free(pmdelta_t *delta); -off_t _alpm_shortest_delta_path(alpm_list_t *deltas, +alpm_delta_t *_alpm_delta_parse(char *line); +void _alpm_delta_free(alpm_delta_t *delta); +alpm_delta_t *_alpm_delta_dup(const alpm_delta_t *delta); +off_t _alpm_shortest_delta_path(alpm_handle_t *handle, alpm_list_t *deltas, const char *to, alpm_list_t **path); /* max percent of package size to download deltas */ diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c index 36d6e1aa..c3681b34 100644 --- a/lib/libalpm/deps.c +++ b/lib/libalpm/deps.c @@ -35,31 +35,30 @@ #include "package.h" #include "db.h" #include "handle.h" +#include "trans.h" -void _alpm_dep_free(pmdepend_t *dep) +void _alpm_dep_free(alpm_depend_t *dep) { FREE(dep->name); FREE(dep->version); FREE(dep); } -static pmdepmissing_t *depmiss_new(const char *target, pmdepend_t *dep, +static alpm_depmissing_t *depmiss_new(const char *target, alpm_depend_t *dep, const char *causingpkg) { - pmdepmissing_t *miss; + alpm_depmissing_t *miss; - ALPM_LOG_FUNC; + MALLOC(miss, sizeof(alpm_depmissing_t), return NULL); - MALLOC(miss, sizeof(pmdepmissing_t), RET_ERR(PM_ERR_MEMORY, NULL)); - - STRDUP(miss->target, target, RET_ERR(PM_ERR_MEMORY, NULL)); + STRDUP(miss->target, target, return NULL); miss->depend = _alpm_dep_dup(dep); - STRDUP(miss->causingpkg, causingpkg, RET_ERR(PM_ERR_MEMORY, NULL)); + STRDUP(miss->causingpkg, causingpkg, return NULL); - return(miss); + return miss; } -void _alpm_depmiss_free(pmdepmissing_t *miss) +void _alpm_depmiss_free(alpm_depmissing_t *miss) { _alpm_dep_free(miss->depend); FREE(miss->target); @@ -68,18 +67,18 @@ void _alpm_depmiss_free(pmdepmissing_t *miss) } /* Does pkg1 depend on pkg2, ie. does pkg2 satisfy a dependency of pkg1? */ -static int _alpm_dep_edge(pmpkg_t *pkg1, pmpkg_t *pkg2) +static int _alpm_dep_edge(alpm_pkg_t *pkg1, alpm_pkg_t *pkg2) { alpm_list_t *i; for(i = alpm_pkg_get_depends(pkg1); i; i = i->next) { if(_alpm_depcmp(pkg2, i->data)) { - return(1); + return 1; } } - return(0); + return 0; } -/* Convert a list of pmpkg_t * to a graph structure, +/* Convert a list of alpm_pkg_t * to a graph structure, * with a edge for each dependency. * Returns a list of vertices (one vertex = one package) * (used by alpm_sortbydeps) @@ -90,19 +89,19 @@ static alpm_list_t *dep_graph_init(alpm_list_t *targets) alpm_list_t *vertices = NULL; /* We create the vertices */ for(i = targets; i; i = i->next) { - pmgraph_t *vertex = _alpm_graph_new(); + alpm_graph_t *vertex = _alpm_graph_new(); vertex->data = (void *)i->data; vertices = alpm_list_add(vertices, vertex); } /* We compute the edges */ for(i = vertices; i; i = i->next) { - pmgraph_t *vertex_i = i->data; - pmpkg_t *p_i = vertex_i->data; + alpm_graph_t *vertex_i = i->data; + alpm_pkg_t *p_i = vertex_i->data; /* TODO this should be somehow combined with alpm_checkdeps */ for(j = vertices; j; j = j->next) { - pmgraph_t *vertex_j = j->data; - pmpkg_t *p_j = vertex_j->data; + alpm_graph_t *vertex_j = j->data; + alpm_pkg_t *p_j = vertex_j->data; if(_alpm_dep_edge(p_i, p_j)) { vertex_i->children = alpm_list_add(vertex_i->children, vertex_j); @@ -110,7 +109,7 @@ static alpm_list_t *dep_graph_init(alpm_list_t *targets) } vertex_i->childptr = vertex_i->children; } - return(vertices); + return vertices; } /* Re-order a list of target packages with respect to their dependencies. @@ -127,20 +126,19 @@ static alpm_list_t *dep_graph_init(alpm_list_t *targets) * This function returns the new alpm_list_t* target list. * */ -alpm_list_t *_alpm_sortbydeps(alpm_list_t *targets, int reverse) +alpm_list_t *_alpm_sortbydeps(alpm_handle_t *handle, + alpm_list_t *targets, int reverse) { alpm_list_t *newtargs = NULL; alpm_list_t *vertices = NULL; alpm_list_t *vptr; - pmgraph_t *vertex; - - ALPM_LOG_FUNC; + alpm_graph_t *vertex; if(targets == NULL) { - return(NULL); + return NULL; } - _alpm_log(PM_LOG_DEBUG, "started sorting dependencies\n"); + _alpm_log(handle, ALPM_LOG_DEBUG, "started sorting dependencies\n"); vertices = dep_graph_init(targets); @@ -151,25 +149,25 @@ alpm_list_t *_alpm_sortbydeps(alpm_list_t *targets, int reverse) vertex->state = -1; int found = 0; while(vertex->childptr && !found) { - pmgraph_t *nextchild = vertex->childptr->data; + alpm_graph_t *nextchild = vertex->childptr->data; vertex->childptr = vertex->childptr->next; - if (nextchild->state == 0) { + if(nextchild->state == 0) { found = 1; nextchild->parent = vertex; vertex = nextchild; } else if(nextchild->state == -1) { - pmpkg_t *vertexpkg = vertex->data; - pmpkg_t *childpkg = nextchild->data; + alpm_pkg_t *vertexpkg = vertex->data; + alpm_pkg_t *childpkg = nextchild->data; const char *message; - _alpm_log(PM_LOG_WARNING, _("dependency cycle detected:\n")); + _alpm_log(handle, ALPM_LOG_WARNING, _("dependency cycle detected:\n")); if(reverse) { message =_("%s will be removed after its %s dependency\n"); } else { message =_("%s will be installed before its %s dependency\n"); } - _alpm_log(PM_LOG_WARNING, message, vertexpkg->name, childpkg->name); + _alpm_log(handle, ALPM_LOG_WARNING, message, vertexpkg->name, childpkg->name); } } if(!found) { @@ -181,14 +179,14 @@ alpm_list_t *_alpm_sortbydeps(alpm_list_t *targets, int reverse) vptr = vptr->next; while(vptr) { vertex = vptr->data; - if (vertex->state == 0) break; + if(vertex->state == 0) break; vptr = vptr->next; } } } } - _alpm_log(PM_LOG_DEBUG, "sorting dependencies finished\n"); + _alpm_log(handle, ALPM_LOG_DEBUG, "sorting dependencies finished\n"); if(reverse) { /* reverse the order */ @@ -201,108 +199,110 @@ alpm_list_t *_alpm_sortbydeps(alpm_list_t *targets, int reverse) alpm_list_free_inner(vertices, _alpm_graph_free); alpm_list_free(vertices); - return(newtargs); + return newtargs; } -static int no_dep_version(void) +static int no_dep_version(alpm_handle_t *handle) { - int flags = alpm_trans_get_flags(); - return flags != -1 && (flags & PM_TRANS_FLAG_NODEPVERSION); + int flags = alpm_trans_get_flags(handle); + return flags != -1 && (flags & ALPM_TRANS_FLAG_NODEPVERSION); } -static pmdepend_t *filtered_depend(pmdepend_t *dep, int nodepversion) +static alpm_depend_t *filtered_depend(alpm_depend_t *dep, int nodepversion) { if(nodepversion) { - pmdepend_t *newdep = _alpm_dep_dup(dep); - ASSERT(newdep, return(dep)); - newdep->mod = PM_DEP_MOD_ANY; + alpm_depend_t *newdep = _alpm_dep_dup(dep); + ASSERT(newdep, return dep); + newdep->mod = ALPM_DEP_MOD_ANY; dep = newdep; } return dep; } -static void release_filtered_depend(pmdepend_t *dep, int nodepversion) +static void release_filtered_depend(alpm_depend_t *dep, int nodepversion) { if(nodepversion) { free(dep); } } -static pmpkg_t *find_dep_satisfier(alpm_list_t *pkgs, pmdepend_t *dep) +static alpm_pkg_t *find_dep_satisfier(alpm_list_t *pkgs, alpm_depend_t *dep) { alpm_list_t *i; for(i = pkgs; i; i = alpm_list_next(i)) { - pmpkg_t *pkg = i->data; + alpm_pkg_t *pkg = i->data; if(_alpm_depcmp(pkg, dep)) { - return(pkg); + return pkg; } } - return(NULL); + return NULL; } /** Find a package satisfying a specified dependency. * The dependency can include versions with depmod operators. - * @param pkgs an alpm_list_t* of pmpkg_t where the satisfier will be searched + * @param pkgs an alpm_list_t* of alpm_pkg_t where the satisfier will be searched * @param depstring package or provision name, versioned or not - * @return a pmpkg_t* satisfying depstring + * @return a alpm_pkg_t* satisfying depstring */ -pmpkg_t SYMEXPORT *alpm_find_satisfier(alpm_list_t *pkgs, const char *depstring) +alpm_pkg_t SYMEXPORT *alpm_find_satisfier(alpm_list_t *pkgs, const char *depstring) { - pmdepend_t *dep = _alpm_splitdep(depstring); - pmpkg_t *pkg = find_dep_satisfier(pkgs, dep); + alpm_depend_t *dep = _alpm_splitdep(depstring); + if(!dep) { + return NULL; + } + alpm_pkg_t *pkg = find_dep_satisfier(pkgs, dep); _alpm_dep_free(dep); - return(pkg); + return pkg; } /** Checks dependencies and returns missing ones in a list. * Dependencies can include versions with depmod operators. + * @param handle the context handle * @param pkglist the list of local packages - * @param reversedeps handles the backward dependencies * @param remove an alpm_list_t* of packages to be removed * @param upgrade an alpm_list_t* of packages to be upgraded (remove-then-upgrade) - * @return an alpm_list_t* of pmdepmissing_t pointers. + * @param reversedeps handles the backward dependencies + * @return an alpm_list_t* of alpm_depmissing_t pointers. */ -alpm_list_t SYMEXPORT *alpm_checkdeps(alpm_list_t *pkglist, int reversedeps, - alpm_list_t *remove, alpm_list_t *upgrade) +alpm_list_t SYMEXPORT *alpm_checkdeps(alpm_handle_t *handle, alpm_list_t *pkglist, + alpm_list_t *remove, alpm_list_t *upgrade, int reversedeps) { alpm_list_t *i, *j; - alpm_list_t *targets, *dblist = NULL, *modified = NULL; + alpm_list_t *dblist = NULL, *modified = NULL; alpm_list_t *baddeps = NULL; int nodepversion; - ALPM_LOG_FUNC; + CHECK_HANDLE(handle, return NULL); - targets = alpm_list_join(alpm_list_copy(remove), alpm_list_copy(upgrade)); for(i = pkglist; i; i = i->next) { - pmpkg_t *pkg = i->data; - if(_alpm_pkg_find(targets, pkg->name)) { + alpm_pkg_t *pkg = i->data; + if(_alpm_pkg_find(remove, pkg->name) || _alpm_pkg_find(upgrade, pkg->name)) { modified = alpm_list_add(modified, pkg); } else { dblist = alpm_list_add(dblist, pkg); } } - alpm_list_free(targets); - nodepversion = no_dep_version(); + nodepversion = no_dep_version(handle); /* look for unsatisfied dependencies of the upgrade list */ for(i = upgrade; i; i = i->next) { - pmpkg_t *tp = i->data; - _alpm_log(PM_LOG_DEBUG, "checkdeps: package %s-%s\n", + alpm_pkg_t *tp = i->data; + _alpm_log(handle, ALPM_LOG_DEBUG, "checkdeps: package %s-%s\n", alpm_pkg_get_name(tp), alpm_pkg_get_version(tp)); for(j = alpm_pkg_get_depends(tp); j; j = j->next) { - pmdepend_t *depend = j->data; + alpm_depend_t *depend = j->data; depend = filtered_depend(depend, nodepversion); /* 1. we check the upgrade list */ /* 2. we check database for untouched satisfying packages */ if(!find_dep_satisfier(upgrade, depend) && !find_dep_satisfier(dblist, depend)) { /* Unsatisfied dependency in the upgrade list */ - pmdepmissing_t *miss; + alpm_depmissing_t *miss; char *missdepstring = alpm_dep_compute_string(depend); - _alpm_log(PM_LOG_DEBUG, "checkdeps: missing dependency '%s' for package '%s'\n", + _alpm_log(handle, ALPM_LOG_DEBUG, "checkdeps: missing dependency '%s' for package '%s'\n", missdepstring, alpm_pkg_get_name(tp)); free(missdepstring); miss = depmiss_new(alpm_pkg_get_name(tp), depend, NULL); @@ -316,20 +316,20 @@ alpm_list_t SYMEXPORT *alpm_checkdeps(alpm_list_t *pkglist, int reversedeps, /* reversedeps handles the backwards dependencies, ie, * the packages listed in the requiredby field. */ for(i = dblist; i; i = i->next) { - pmpkg_t *lp = i->data; + alpm_pkg_t *lp = i->data; for(j = alpm_pkg_get_depends(lp); j; j = j->next) { - pmdepend_t *depend = j->data; + alpm_depend_t *depend = j->data; depend = filtered_depend(depend, nodepversion); - pmpkg_t *causingpkg = find_dep_satisfier(modified, depend); + alpm_pkg_t *causingpkg = find_dep_satisfier(modified, depend); /* we won't break this depend, if it is already broken, we ignore it */ /* 1. check upgrade list for satisfiers */ /* 2. check dblist for satisfiers */ if(causingpkg && !find_dep_satisfier(upgrade, depend) && !find_dep_satisfier(dblist, depend)) { - pmdepmissing_t *miss; + alpm_depmissing_t *miss; char *missdepstring = alpm_dep_compute_string(depend); - _alpm_log(PM_LOG_DEBUG, "checkdeps: transaction would break '%s' dependency of '%s'\n", + _alpm_log(handle, ALPM_LOG_DEBUG, "checkdeps: transaction would break '%s' dependency of '%s'\n", missdepstring, alpm_pkg_get_name(lp)); free(missdepstring); miss = depmiss_new(lp->name, depend, alpm_pkg_get_name(causingpkg)); @@ -343,31 +343,31 @@ alpm_list_t SYMEXPORT *alpm_checkdeps(alpm_list_t *pkglist, int reversedeps, alpm_list_free(modified); alpm_list_free(dblist); - return(baddeps); + return baddeps; } -static int dep_vercmp(const char *version1, pmdepmod_t mod, +static int dep_vercmp(const char *version1, alpm_depmod_t mod, const char *version2) { int equal = 0; - if(mod == PM_DEP_MOD_ANY) { + if(mod == ALPM_DEP_MOD_ANY) { equal = 1; } else { int cmp = alpm_pkg_vercmp(version1, version2); switch(mod) { - case PM_DEP_MOD_EQ: equal = (cmp == 0); break; - case PM_DEP_MOD_GE: equal = (cmp >= 0); break; - case PM_DEP_MOD_LE: equal = (cmp <= 0); break; - case PM_DEP_MOD_LT: equal = (cmp < 0); break; - case PM_DEP_MOD_GT: equal = (cmp > 0); break; + case ALPM_DEP_MOD_EQ: equal = (cmp == 0); break; + case ALPM_DEP_MOD_GE: equal = (cmp >= 0); break; + case ALPM_DEP_MOD_LE: equal = (cmp <= 0); break; + case ALPM_DEP_MOD_LT: equal = (cmp < 0); break; + case ALPM_DEP_MOD_GT: equal = (cmp > 0); break; default: equal = 1; break; } } - return(equal); + return equal; } -int _alpm_depcmp(pmpkg_t *pkg, pmdepend_t *dep) +int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep) { alpm_list_t *i; int satisfy = 0; @@ -380,7 +380,7 @@ int _alpm_depcmp(pmpkg_t *pkg, pmdepend_t *dep) satisfy = (strcmp(pkg->name, dep->name) == 0 && dep_vercmp(pkg->version, dep->mod, dep->version)); if(satisfy) { - return(satisfy); + return satisfy; } } @@ -390,7 +390,7 @@ int _alpm_depcmp(pmpkg_t *pkg, pmdepend_t *dep) const char *provver = strchr(provision, '='); if(provver == NULL) { /* no provision version */ - satisfy = (dep->mod == PM_DEP_MOD_ANY + satisfy = (dep->mod == ALPM_DEP_MOD_ANY && strcmp(provision, dep->name) == 0); } else { /* This is a bit tricker than the old code for performance reasons. To @@ -406,86 +406,85 @@ int _alpm_depcmp(pmpkg_t *pkg, pmdepend_t *dep) } } - return(satisfy); + return satisfy; } -pmdepend_t *_alpm_splitdep(const char *depstring) +alpm_depend_t *_alpm_splitdep(const char *depstring) { - pmdepend_t *depend; + alpm_depend_t *depend; const char *ptr, *version = NULL; if(depstring == NULL) { - return(NULL); + return NULL; } - CALLOC(depend, 1, sizeof(pmdepend_t), RET_ERR(PM_ERR_MEMORY, NULL)); + CALLOC(depend, 1, sizeof(alpm_depend_t), return NULL); /* Find a version comparator if one exists. If it does, set the type and * increment the ptr accordingly so we can copy the right strings. */ if((ptr = strstr(depstring, ">="))) { - depend->mod = PM_DEP_MOD_GE; + depend->mod = ALPM_DEP_MOD_GE; version = ptr + 2; } else if((ptr = strstr(depstring, "<="))) { - depend->mod = PM_DEP_MOD_LE; + depend->mod = ALPM_DEP_MOD_LE; version = ptr + 2; } else if((ptr = strstr(depstring, "="))) { /* Note: we must do =,<,> checks after <=, >= checks */ - depend->mod = PM_DEP_MOD_EQ; + depend->mod = ALPM_DEP_MOD_EQ; version = ptr + 1; } else if((ptr = strstr(depstring, "<"))) { - depend->mod = PM_DEP_MOD_LT; + depend->mod = ALPM_DEP_MOD_LT; version = ptr + 1; } else if((ptr = strstr(depstring, ">"))) { - depend->mod = PM_DEP_MOD_GT; + depend->mod = ALPM_DEP_MOD_GT; version = ptr + 1; } else { /* no version specified, leave version and ptr NULL */ - depend->mod = PM_DEP_MOD_ANY; + depend->mod = ALPM_DEP_MOD_ANY; } /* copy the right parts to the right places */ - STRNDUP(depend->name, depstring, ptr - depstring, - RET_ERR(PM_ERR_MEMORY, NULL)); + STRNDUP(depend->name, depstring, ptr - depstring, return NULL); depend->name_hash = _alpm_hash_sdbm(depend->name); if(version) { - STRDUP(depend->version, version, RET_ERR(PM_ERR_MEMORY, NULL)); + STRDUP(depend->version, version, return NULL); } - return(depend); + return depend; } -pmdepend_t *_alpm_dep_dup(const pmdepend_t *dep) +alpm_depend_t *_alpm_dep_dup(const alpm_depend_t *dep) { - pmdepend_t *newdep; - CALLOC(newdep, 1, sizeof(pmdepend_t), RET_ERR(PM_ERR_MEMORY, NULL)); + alpm_depend_t *newdep; + CALLOC(newdep, 1, sizeof(alpm_depend_t), return NULL); - STRDUP(newdep->name, dep->name, RET_ERR(PM_ERR_MEMORY, NULL)); + STRDUP(newdep->name, dep->name, return NULL); newdep->name_hash = dep->name_hash; - STRDUP(newdep->version, dep->version, RET_ERR(PM_ERR_MEMORY, NULL)); + STRDUP(newdep->version, dep->version, return NULL); newdep->mod = dep->mod; - return(newdep); + return newdep; } /* These parameters are messy. We check if this package, given a list of * targets and a db is safe to remove. We do NOT remove it if it is in the * target list, or if if the package was explictly installed and * include_explicit == 0 */ -static int can_remove_package(pmdb_t *db, pmpkg_t *pkg, alpm_list_t *targets, +static int can_remove_package(alpm_db_t *db, alpm_pkg_t *pkg, alpm_list_t *targets, int include_explicit) { alpm_list_t *i; if(_alpm_pkg_find(targets, alpm_pkg_get_name(pkg))) { - return(0); + return 0; } if(!include_explicit) { /* see if it was explicitly installed */ - if(alpm_pkg_get_reason(pkg) == PM_PKG_REASON_EXPLICIT) { - _alpm_log(PM_LOG_DEBUG, "excluding %s -- explicitly installed\n", + if(alpm_pkg_get_reason(pkg) == ALPM_PKG_REASON_EXPLICIT) { + _alpm_log(db->handle, ALPM_LOG_DEBUG, "excluding %s -- explicitly installed\n", alpm_pkg_get_name(pkg)); - return(0); + return 0; } } @@ -497,14 +496,14 @@ static int can_remove_package(pmdb_t *db, pmpkg_t *pkg, alpm_list_t *targets, /* see if other packages need it */ for(i = _alpm_db_get_pkgcache(db); i; i = i->next) { - pmpkg_t *lpkg = i->data; + alpm_pkg_t *lpkg = i->data; if(_alpm_dep_edge(lpkg, pkg) && !_alpm_pkg_find(targets, lpkg->name)) { - return(0); + return 0; } } /* it's ok to remove */ - return(1); + return 1; } /** @@ -517,23 +516,21 @@ static int can_remove_package(pmdb_t *db, pmpkg_t *pkg, alpm_list_t *targets, * @param *targs pointer to a list of packages * @param include_explicit if 0, explicitly installed packages are not included */ -void _alpm_recursedeps(pmdb_t *db, alpm_list_t *targs, int include_explicit) +void _alpm_recursedeps(alpm_db_t *db, alpm_list_t *targs, int include_explicit) { alpm_list_t *i, *j; - ALPM_LOG_FUNC; - if(db == NULL || targs == NULL) { return; } for(i = targs; i; i = i->next) { - pmpkg_t *pkg = i->data; + alpm_pkg_t *pkg = i->data; for(j = _alpm_db_get_pkgcache(db); j; j = j->next) { - pmpkg_t *deppkg = j->data; + alpm_pkg_t *deppkg = j->data; if(_alpm_dep_edge(pkg, deppkg) && can_remove_package(db, deppkg, targs, include_explicit)) { - _alpm_log(PM_LOG_DEBUG, "adding '%s' to the targets\n", + _alpm_log(db->handle, ALPM_LOG_DEBUG, "adding '%s' to the targets\n", alpm_pkg_get_name(deppkg)); /* add it to the target list */ targs = alpm_list_add(targs, _alpm_pkg_dup(deppkg)); @@ -545,6 +542,7 @@ void _alpm_recursedeps(pmdb_t *db, alpm_list_t *targs, int include_explicit) /** * helper function for resolvedeps: search for dep satisfier in dbs * + * @param handle the context handle * @param dep is the dependency to search for * @param dbs are the databases to search * @param excluding are the packages to exclude from the search @@ -554,8 +552,8 @@ void _alpm_recursedeps(pmdb_t *db, alpm_list_t *targs, int include_explicit) * an error code without prompting * @return the resolved package **/ -static pmpkg_t *resolvedep(pmdepend_t *dep, alpm_list_t *dbs, - alpm_list_t *excluding, int prompt) +static alpm_pkg_t *resolvedep(alpm_handle_t *handle, alpm_depend_t *dep, + alpm_list_t *dbs, alpm_list_t *excluding, int prompt) { alpm_list_t *i, *j; int ignored = 0; @@ -565,44 +563,44 @@ static pmpkg_t *resolvedep(pmdepend_t *dep, alpm_list_t *dbs, /* 1. literals */ for(i = dbs; i; i = i->next) { - pmpkg_t *pkg = _alpm_db_get_pkgfromcache(i->data, dep->name); + alpm_pkg_t *pkg = _alpm_db_get_pkgfromcache(i->data, dep->name); if(pkg && _alpm_depcmp(pkg, dep) && !_alpm_pkg_find(excluding, pkg->name)) { - if(_alpm_pkg_should_ignore(pkg)) { + if(_alpm_pkg_should_ignore(handle, pkg)) { int install = 0; - if (prompt) { - QUESTION(handle->trans, PM_TRANS_CONV_INSTALL_IGNOREPKG, pkg, + if(prompt) { + QUESTION(handle->trans, ALPM_TRANS_CONV_INSTALL_IGNOREPKG, pkg, NULL, NULL, &install); } else { - _alpm_log(PM_LOG_WARNING, _("ignoring package %s-%s\n"), pkg->name, pkg->version); + _alpm_log(handle, ALPM_LOG_WARNING, _("ignoring package %s-%s\n"), pkg->name, pkg->version); } if(!install) { ignored = 1; continue; } } - return(pkg); + return pkg; } } /* 2. satisfiers (skip literals here) */ for(i = dbs; i; i = i->next) { for(j = _alpm_db_get_pkgcache(i->data); j; j = j->next) { - pmpkg_t *pkg = j->data; + alpm_pkg_t *pkg = j->data; if(_alpm_depcmp(pkg, dep) && strcmp(pkg->name, dep->name) != 0 && !_alpm_pkg_find(excluding, pkg->name)) { - if(_alpm_pkg_should_ignore(pkg)) { + if(_alpm_pkg_should_ignore(handle, pkg)) { int install = 0; - if (prompt) { - QUESTION(handle->trans, PM_TRANS_CONV_INSTALL_IGNOREPKG, + if(prompt) { + QUESTION(handle->trans, ALPM_TRANS_CONV_INSTALL_IGNOREPKG, pkg, NULL, NULL, &install); } else { - _alpm_log(PM_LOG_WARNING, _("ignoring package %s-%s\n"), pkg->name, pkg->version); + _alpm_log(handle, ALPM_LOG_WARNING, _("ignoring package %s-%s\n"), pkg->name, pkg->version); } if(!install) { ignored = 1; continue; } } - _alpm_log(PM_LOG_DEBUG, "provider found (%s provides %s)\n", + _alpm_log(handle, ALPM_LOG_DEBUG, "provider found (%s provides %s)\n", pkg->name, dep->name); providers = alpm_list_add(providers, pkg); /* keep looking for other providers in the all dbs */ @@ -612,66 +610,69 @@ static pmpkg_t *resolvedep(pmdepend_t *dep, alpm_list_t *dbs, /* first check if one provider is already installed locally */ for(i = providers; i; i = i->next) { - pmpkg_t *pkg = i->data; - if (_alpm_pkghash_find(_alpm_db_get_pkgcache_hash(handle->db_local), pkg->name)) { + alpm_pkg_t *pkg = i->data; + if(_alpm_pkghash_find(_alpm_db_get_pkgcache_hash(handle->db_local), pkg->name)) { alpm_list_free(providers); - return(pkg); + return pkg; } } count = alpm_list_count(providers); - if (count >= 1) { + if(count >= 1) { /* default to first provider if there is no QUESTION callback */ int index = 0; if(count > 1) { /* if there is more than one provider, we ask the user */ - QUESTION(handle->trans, PM_TRANS_CONV_SELECT_PROVIDER, + QUESTION(handle->trans, ALPM_TRANS_CONV_SELECT_PROVIDER, providers, dep, NULL, &index); } if(index >= 0 && index < count) { - pmpkg_t *pkg = alpm_list_getdata(alpm_list_nth(providers, index)); + alpm_pkg_t *pkg = alpm_list_getdata(alpm_list_nth(providers, index)); alpm_list_free(providers); - return(pkg); + return pkg; } alpm_list_free(providers); providers = NULL; } if(ignored) { /* resolvedeps will override these */ - pm_errno = PM_ERR_PKG_IGNORED; + handle->pm_errno = ALPM_ERR_PKG_IGNORED; } else { - pm_errno = PM_ERR_PKG_NOT_FOUND; + handle->pm_errno = ALPM_ERR_PKG_NOT_FOUND; } - return(NULL); + return NULL; } /** Find a package satisfying a specified dependency. * First look for a literal, going through each db one by one. Then look for * providers. The first satisfier found is returned. * The dependency can include versions with depmod operators. - * @param dbs an alpm_list_t* of pmdb_t where the satisfier will be searched + * @param handle the context handle + * @param dbs an alpm_list_t* of alpm_db_t where the satisfier will be searched * @param depstring package or provision name, versioned or not - * @return a pmpkg_t* satisfying depstring + * @return a alpm_pkg_t* satisfying depstring */ -pmpkg_t SYMEXPORT *alpm_find_dbs_satisfier(alpm_list_t *dbs, const char *depstring) +alpm_pkg_t SYMEXPORT *alpm_find_dbs_satisfier(alpm_handle_t *handle, + alpm_list_t *dbs, const char *depstring) { - pmdepend_t *dep; - pmpkg_t *pkg; + alpm_depend_t *dep; + alpm_pkg_t *pkg; - ASSERT(dbs, return(NULL)); + CHECK_HANDLE(handle, return NULL); + ASSERT(dbs, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, NULL)); dep = _alpm_splitdep(depstring); - ASSERT(dep, return(NULL)); - pkg = resolvedep(dep, dbs, NULL, 1); + ASSERT(dep, return NULL); + pkg = resolvedep(handle, dep, dbs, NULL, 1); _alpm_dep_free(dep); - return(pkg); + return pkg; } /** * Computes resolvable dependencies for a given package and adds that package * and those resolvable dependencies to a list. * + * @param handle the context handle * @param localpkgs is the list of local packages - * @param dbs_sync are the sync databases * @param pkg is the package to resolve * @param packages is a pointer to a list of packages which will be * searched first for any dependency packages needed to complete the @@ -686,7 +687,7 @@ pmpkg_t SYMEXPORT *alpm_find_dbs_satisfier(alpm_list_t *dbs, const char *depstri * unresolvable dependency, in which case the [*packages] list will be * unmodified by this function */ -int _alpm_resolvedeps(alpm_list_t *localpkgs, alpm_list_t *dbs_sync, pmpkg_t *pkg, +int _alpm_resolvedeps(alpm_handle_t *handle, alpm_list_t *localpkgs, alpm_pkg_t *pkg, alpm_list_t *preferred, alpm_list_t **packages, alpm_list_t *remove, alpm_list_t **data) { @@ -696,10 +697,8 @@ int _alpm_resolvedeps(alpm_list_t *localpkgs, alpm_list_t *dbs_sync, pmpkg_t *pk alpm_list_t *deps = NULL; alpm_list_t *packages_copy; - ALPM_LOG_FUNC; - if(_alpm_pkg_find(*packages, pkg->name) != NULL) { - return(0); + return 0; } /* Create a copy of the packages list, so that it can be restored @@ -709,16 +708,16 @@ int _alpm_resolvedeps(alpm_list_t *localpkgs, alpm_list_t *dbs_sync, pmpkg_t *pk on that list */ *packages = alpm_list_add(*packages, pkg); - _alpm_log(PM_LOG_DEBUG, "started resolving dependencies\n"); + _alpm_log(handle, ALPM_LOG_DEBUG, "started resolving dependencies\n"); for(i = alpm_list_last(*packages); i; i = i->next) { - pmpkg_t *tpkg = i->data; + alpm_pkg_t *tpkg = i->data; targ = alpm_list_add(NULL, tpkg); - deps = alpm_checkdeps(localpkgs, 0, remove, targ); + deps = alpm_checkdeps(handle, localpkgs, remove, targ, 0); alpm_list_free(targ); for(j = deps; j; j = j->next) { - pmdepmissing_t *miss = j->data; - pmdepend_t *missdep = alpm_miss_get_dep(miss); + alpm_depmissing_t *miss = j->data; + alpm_depend_t *missdep = miss->depend; /* check if one of the packages in the [*packages] list already satisfies * this dependency */ if(find_dep_satisfier(*packages, missdep)) { @@ -727,15 +726,15 @@ int _alpm_resolvedeps(alpm_list_t *localpkgs, alpm_list_t *dbs_sync, pmpkg_t *pk } /* check if one of the packages in the [preferred] list already satisfies * this dependency */ - pmpkg_t *spkg = find_dep_satisfier(preferred, missdep); + alpm_pkg_t *spkg = find_dep_satisfier(preferred, missdep); if(!spkg) { /* find a satisfier package in the given repositories */ - spkg = resolvedep(missdep, dbs_sync, *packages, 0); + spkg = resolvedep(handle, missdep, handle->dbs_sync, *packages, 0); } if(!spkg) { - pm_errno = PM_ERR_UNSATISFIED_DEPS; + handle->pm_errno = ALPM_ERR_UNSATISFIED_DEPS; char *missdepstring = alpm_dep_compute_string(missdep); - _alpm_log(PM_LOG_WARNING, + _alpm_log(handle, ALPM_LOG_WARNING, _("cannot resolve \"%s\", a dependency of \"%s\"\n"), missdepstring, tpkg->name); free(missdepstring); @@ -744,7 +743,7 @@ int _alpm_resolvedeps(alpm_list_t *localpkgs, alpm_list_t *dbs_sync, pmpkg_t *pk } ret = -1; } else { - _alpm_log(PM_LOG_DEBUG, "pulling dependency %s (needed by %s)\n", + _alpm_log(handle, ALPM_LOG_DEBUG, "pulling dependency %s (needed by %s)\n", alpm_pkg_get_name(spkg), alpm_pkg_get_name(tpkg)); *packages = alpm_list_add(*packages, spkg); _alpm_depmiss_free(miss); @@ -759,85 +758,22 @@ int _alpm_resolvedeps(alpm_list_t *localpkgs, alpm_list_t *dbs_sync, pmpkg_t *pk } else { alpm_list_free(packages_copy); } - _alpm_log(PM_LOG_DEBUG, "finished resolving dependencies\n"); - return(ret); -} - -const char SYMEXPORT *alpm_miss_get_target(const pmdepmissing_t *miss) -{ - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(miss != NULL, return(NULL)); - - return(miss->target); -} - -const char SYMEXPORT *alpm_miss_get_causingpkg(const pmdepmissing_t *miss) -{ - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(miss != NULL, return(NULL)); - - return miss->causingpkg; -} - -pmdepend_t SYMEXPORT *alpm_miss_get_dep(pmdepmissing_t *miss) -{ - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(miss != NULL, return(NULL)); - - return(miss->depend); -} - -pmdepmod_t SYMEXPORT alpm_dep_get_mod(const pmdepend_t *dep) -{ - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(dep != NULL, return(-1)); - - return(dep->mod); + _alpm_log(handle, ALPM_LOG_DEBUG, "finished resolving dependencies\n"); + return ret; } -const char SYMEXPORT *alpm_dep_get_name(const pmdepend_t *dep) -{ - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(dep != NULL, return(NULL)); - - return(dep->name); -} - -const char SYMEXPORT *alpm_dep_get_version(const pmdepend_t *dep) -{ - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(dep != NULL, return(NULL)); - - return(dep->version); -} - -/** Reverse of splitdep; make a dep string from a pmdepend_t struct. +/** Reverse of splitdep; make a dep string from a alpm_depend_t struct. * The string must be freed! * @param dep the depend to turn into a string * @return a string-formatted dependency with operator if necessary */ -char SYMEXPORT *alpm_dep_compute_string(const pmdepend_t *dep) +char SYMEXPORT *alpm_dep_compute_string(const alpm_depend_t *dep) { const char *name, *opr, *ver; char *str; size_t len; - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(dep != NULL, return(NULL)); + ASSERT(dep != NULL, return NULL); if(dep->name) { name = dep->name; @@ -846,22 +782,22 @@ char SYMEXPORT *alpm_dep_compute_string(const pmdepend_t *dep) } switch(dep->mod) { - case PM_DEP_MOD_ANY: + case ALPM_DEP_MOD_ANY: opr = ""; break; - case PM_DEP_MOD_GE: + case ALPM_DEP_MOD_GE: opr = ">="; break; - case PM_DEP_MOD_LE: + case ALPM_DEP_MOD_LE: opr = "<="; break; - case PM_DEP_MOD_EQ: + case ALPM_DEP_MOD_EQ: opr = "="; break; - case PM_DEP_MOD_LT: + case ALPM_DEP_MOD_LT: opr = "<"; break; - case PM_DEP_MOD_GT: + case ALPM_DEP_MOD_GT: opr = ">"; break; default: @@ -869,19 +805,19 @@ char SYMEXPORT *alpm_dep_compute_string(const pmdepend_t *dep) break; } - if(dep->mod != PM_DEP_MOD_ANY && dep->version) { + if(dep->mod != ALPM_DEP_MOD_ANY && dep->version) { ver = dep->version; } else { ver = ""; } /* we can always compute len and print the string like this because opr - * and ver will be empty when PM_DEP_MOD_ANY is the depend type. the + * and ver will be empty when ALPM_DEP_MOD_ANY is the depend type. the * reassignments above also ensure we do not do a strlen(NULL). */ len = strlen(name) + strlen(opr) + strlen(ver) + 1; - MALLOC(str, len, RET_ERR(PM_ERR_MEMORY, NULL)); + MALLOC(str, len, return NULL); snprintf(str, len, "%s%s%s", name, opr, ver); - return(str); + return str; } /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/deps.h b/lib/libalpm/deps.h index f728cad0..6ef4cbbe 100644 --- a/lib/libalpm/deps.h +++ b/lib/libalpm/deps.h @@ -27,31 +27,16 @@ #include "package.h" #include "alpm.h" -/* Dependency */ -struct __pmdepend_t { - char *name; - char *version; - unsigned long name_hash; - pmdepmod_t mod; -}; - -/* Missing dependency */ -struct __pmdepmissing_t { - char *target; - pmdepend_t *depend; - char *causingpkg; /* this is used in case of remove dependency error only */ -}; - -void _alpm_dep_free(pmdepend_t *dep); -pmdepend_t *_alpm_dep_dup(const pmdepend_t *dep); -void _alpm_depmiss_free(pmdepmissing_t *miss); -alpm_list_t *_alpm_sortbydeps(alpm_list_t *targets, int reverse); -void _alpm_recursedeps(pmdb_t *db, alpm_list_t *targs, int include_explicit); -int _alpm_resolvedeps(alpm_list_t *localpkgs, alpm_list_t *dbs_sync, pmpkg_t *pkg, +void _alpm_dep_free(alpm_depend_t *dep); +alpm_depend_t *_alpm_dep_dup(const alpm_depend_t *dep); +void _alpm_depmiss_free(alpm_depmissing_t *miss); +alpm_list_t *_alpm_sortbydeps(alpm_handle_t *handle, alpm_list_t *targets, int reverse); +void _alpm_recursedeps(alpm_db_t *db, alpm_list_t *targs, int include_explicit); +int _alpm_resolvedeps(alpm_handle_t *handle, alpm_list_t *localpkgs, alpm_pkg_t *pkg, alpm_list_t *preferred, alpm_list_t **packages, alpm_list_t *remove, alpm_list_t **data); -pmdepend_t *_alpm_splitdep(const char *depstring); -int _alpm_depcmp(pmpkg_t *pkg, pmdepend_t *dep); +alpm_depend_t *_alpm_splitdep(const char *depstring); +int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep); #endif /* _ALPM_DEPS_H */ diff --git a/lib/libalpm/diskspace.c b/lib/libalpm/diskspace.c index 066107d7..b28b88ab 100644 --- a/lib/libalpm/diskspace.c +++ b/lib/libalpm/diskspace.c @@ -39,10 +39,6 @@ #include <sys/types.h> #endif -/* libarchive */ -#include <archive.h> -#include <archive_entry.h> - /* libalpm */ #include "diskspace.h" #include "alpm_list.h" @@ -56,10 +52,10 @@ static int mount_point_cmp(const void *p1, const void *p2) const alpm_mountpoint_t *mp1 = p1; const alpm_mountpoint_t *mp2 = p2; /* the negation will sort all mountpoints before their parent */ - return(-strcmp(mp1->mount_dir, mp2->mount_dir)); + return -strcmp(mp1->mount_dir, mp2->mount_dir); } -static alpm_list_t *mount_point_list(void) +static alpm_list_t *mount_point_list(alpm_handle_t *handle) { alpm_list_t *mount_points = NULL, *ptr; alpm_mountpoint_t *mp; @@ -71,23 +67,23 @@ static alpm_list_t *mount_point_list(void) fp = setmntent(MOUNTED, "r"); - if (fp == NULL) { - return(NULL); + if(fp == NULL) { + return NULL; } while((mnt = getmntent(fp))) { if(!mnt) { - _alpm_log(PM_LOG_WARNING, _("could not get filesystem information\n")); + _alpm_log(handle, ALPM_LOG_WARNING, _("could not get filesystem information\n")); continue; } if(statvfs(mnt->mnt_dir, &fsp) != 0) { - _alpm_log(PM_LOG_WARNING, + _alpm_log(handle, ALPM_LOG_WARNING, _("could not get filesystem information for %s: %s\n"), mnt->mnt_dir, strerror(errno)); continue; } - CALLOC(mp, 1, sizeof(alpm_mountpoint_t), RET_ERR(PM_ERR_MEMORY, NULL)); + CALLOC(mp, 1, sizeof(alpm_mountpoint_t), RET_ERR(handle, ALPM_ERR_MEMORY, NULL)); mp->mount_dir = strdup(mnt->mnt_dir); mp->mount_dir_len = strlen(mp->mount_dir); memcpy(&(mp->fsp), &fsp, sizeof(struct statvfs)); @@ -103,12 +99,12 @@ static alpm_list_t *mount_point_list(void) entries = getmntinfo(&fsp, MNT_NOWAIT); - if (entries < 0) { - return(NULL); + if(entries < 0) { + return NULL; } for(; entries-- > 0; fsp++) { - CALLOC(mp, 1, sizeof(alpm_mountpoint_t), RET_ERR(PM_ERR_MEMORY, NULL)); + CALLOC(mp, 1, sizeof(alpm_mountpoint_t), RET_ERR(ALPM_ERR_MEMORY, NULL)); mp->mount_dir = strdup(fsp->f_mntonname); mp->mount_dir_len = strlen(mp->mount_dir); memcpy(&(mp->fsp), fsp, sizeof(FSSTATSTYPE)); @@ -126,9 +122,9 @@ static alpm_list_t *mount_point_list(void) mount_point_cmp); for(ptr = mount_points; ptr != NULL; ptr = ptr->next) { mp = ptr->data; - _alpm_log(PM_LOG_DEBUG, "mountpoint: %s\n", mp->mount_dir); + _alpm_log(handle, ALPM_LOG_DEBUG, "mountpoint: %s\n", mp->mount_dir); } - return(mount_points); + return mount_points; } static alpm_mountpoint_t *match_mount_point(const alpm_list_t *mount_points, @@ -140,25 +136,30 @@ static alpm_mountpoint_t *match_mount_point(const alpm_list_t *mount_points, alpm_mountpoint_t *data = mp->data; if(strncmp(data->mount_dir, real_path, data->mount_dir_len) == 0) { - return(data); + return data; } } /* should not get here... */ - return(NULL); + return NULL; } -static int calculate_removed_size(const alpm_list_t *mount_points, - pmpkg_t *pkg) +static int calculate_removed_size(alpm_handle_t *handle, + const alpm_list_t *mount_points, alpm_pkg_t *pkg) { - alpm_list_t *file; + size_t i; + alpm_filelist_t *filelist = alpm_pkg_get_files(pkg); + + if(!filelist->count) { + return 0; + } - alpm_list_t *files = alpm_pkg_get_files(pkg); - for(file = files; file; file = file->next) { + for(i = 0; i < filelist->count; i++) { + const alpm_file_t *file = filelist->files + i; alpm_mountpoint_t *mp; struct stat st; char path[PATH_MAX]; - const char *filename = file->data; + const char *filename = file->name; snprintf(path, PATH_MAX, "%s%s", handle->root, filename); _alpm_lstat(path, &st); @@ -171,7 +172,7 @@ static int calculate_removed_size(const alpm_list_t *mount_points, mp = match_mount_point(mount_points, path); if(mp == NULL) { - _alpm_log(PM_LOG_WARNING, + _alpm_log(handle, ALPM_LOG_WARNING, _("could not determine mount point for file %s\n"), filename); continue; } @@ -182,129 +183,104 @@ static int calculate_removed_size(const alpm_list_t *mount_points, mp->used |= USED_REMOVE; } - return(0); + return 0; } -static int calculate_installed_size(const alpm_list_t *mount_points, - pmpkg_t *pkg) +static int calculate_installed_size(alpm_handle_t *handle, + const alpm_list_t *mount_points, alpm_pkg_t *pkg) { - int ret=0; - struct archive *archive; - struct archive_entry *entry; - - if ((archive = archive_read_new()) == NULL) { - pm_errno = PM_ERR_LIBARCHIVE; - ret = -1; - goto cleanup; - } - - archive_read_support_compression_all(archive); - archive_read_support_format_all(archive); + size_t i; + alpm_filelist_t *filelist = alpm_pkg_get_files(pkg); - if(archive_read_open_filename(archive, pkg->origin_data.file, - ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) { - pm_errno = PM_ERR_PKG_OPEN; - ret = -1; - goto cleanup; + if(!filelist->count) { + return 0; } - while(archive_read_next_header(archive, &entry) == ARCHIVE_OK) { + for(i = 0; i < filelist->count; i++) { + const alpm_file_t *file = filelist->files + i; alpm_mountpoint_t *mp; - const char *filename; - mode_t mode; char path[PATH_MAX]; - - filename = archive_entry_pathname(entry); - mode = archive_entry_mode(entry); + const char *filename = file->name; /* libarchive reports these as zero size anyways */ /* NOTE: if we do start accounting for directory size, a dir matching a * mountpoint needs to be attributed to the parent, not the mountpoint. */ - if(S_ISDIR(mode) || S_ISLNK(mode)) { + if(S_ISDIR(file->mode) || S_ISLNK(file->mode)) { continue; } /* approximate space requirements for db entries */ if(filename[0] == '.') { - filename = alpm_option_get_dbpath(); + filename = alpm_option_get_dbpath(handle); } snprintf(path, PATH_MAX, "%s%s", handle->root, filename); mp = match_mount_point(mount_points, path); if(mp == NULL) { - _alpm_log(PM_LOG_WARNING, + _alpm_log(handle, ALPM_LOG_WARNING, _("could not determine mount point for file %s\n"), filename); continue; } /* the addition of (divisor - 1) performs ceil() with integer division */ mp->blocks_needed += - (archive_entry_size(entry) + mp->fsp.f_bsize - 1l) / mp->fsp.f_bsize; + (file->size + mp->fsp.f_bsize - 1l) / mp->fsp.f_bsize; mp->used |= USED_INSTALL; - - if(archive_read_data_skip(archive)) { - _alpm_log(PM_LOG_ERROR, _("error while reading package %s: %s\n"), - pkg->name, archive_error_string(archive)); - pm_errno = PM_ERR_LIBARCHIVE; - break; - } } - archive_read_finish(archive); - -cleanup: - return(ret); + return 0; } -int _alpm_check_diskspace(pmtrans_t *trans, pmdb_t *db_local) +int _alpm_check_diskspace(alpm_handle_t *handle) { alpm_list_t *mount_points, *i; alpm_mountpoint_t *root_mp; size_t replaces = 0, current = 0, numtargs; - int abort = 0; + int error = 0; alpm_list_t *targ; + alpm_trans_t *trans = handle->trans; numtargs = alpm_list_count(trans->add); - mount_points = mount_point_list(); + mount_points = mount_point_list(handle); if(mount_points == NULL) { - _alpm_log(PM_LOG_ERROR, _("could not determine filesystem mount points\n")); - return(-1); + _alpm_log(handle, ALPM_LOG_ERROR, _("could not determine filesystem mount points\n")); + return -1; } root_mp = match_mount_point(mount_points, handle->root); if(root_mp == NULL) { - _alpm_log(PM_LOG_ERROR, _("could not determine root mount point %s\n"), + _alpm_log(handle, ALPM_LOG_ERROR, _("could not determine root mount point %s\n"), handle->root); - return(-1); + return -1; } replaces = alpm_list_count(trans->remove); if(replaces) { numtargs += replaces; for(targ = trans->remove; targ; targ = targ->next, current++) { - pmpkg_t *local_pkg; + alpm_pkg_t *local_pkg; int percent = (current * 100) / numtargs; - PROGRESS(trans, PM_TRANS_PROGRESS_DISKSPACE_START, "", percent, + PROGRESS(trans, ALPM_TRANS_PROGRESS_DISKSPACE_START, "", percent, numtargs, current); local_pkg = targ->data; - calculate_removed_size(mount_points, local_pkg); + calculate_removed_size(handle, mount_points, local_pkg); } } for(targ = trans->add; targ; targ = targ->next, current++) { - pmpkg_t *pkg, *local_pkg; + alpm_pkg_t *pkg, *local_pkg; int percent = (current * 100) / numtargs; - PROGRESS(trans, PM_TRANS_PROGRESS_DISKSPACE_START, "", percent, + PROGRESS(trans, ALPM_TRANS_PROGRESS_DISKSPACE_START, "", percent, numtargs, current); pkg = targ->data; /* is this package already installed? */ - local_pkg = _alpm_db_get_pkgfromcache(db_local, pkg->name); + local_pkg = _alpm_db_get_pkgfromcache(handle->db_local, pkg->name); if(local_pkg) { - calculate_removed_size(mount_points, local_pkg); + calculate_removed_size(handle, mount_points, local_pkg); } - calculate_installed_size(mount_points, pkg); + calculate_installed_size(handle, mount_points, pkg); for(i = mount_points; i; i = alpm_list_next(i)) { alpm_mountpoint_t *data = i->data; @@ -314,30 +290,30 @@ int _alpm_check_diskspace(pmtrans_t *trans, pmdb_t *db_local) } } - PROGRESS(trans, PM_TRANS_PROGRESS_DISKSPACE_START, "", 100, + PROGRESS(trans, ALPM_TRANS_PROGRESS_DISKSPACE_START, "", 100, numtargs, current); for(i = mount_points; i; i = alpm_list_next(i)) { alpm_mountpoint_t *data = i->data; if(data->used && data->read_only) { - _alpm_log(PM_LOG_ERROR, _("Partition %s is mounted read only\n"), + _alpm_log(handle, ALPM_LOG_ERROR, _("Partition %s is mounted read only\n"), data->mount_dir); - abort = 1; + error = 1; } else if(data->used & USED_INSTALL) { /* cushion is roughly min(5% capacity, 20MiB) */ long fivepc = ((long)data->fsp.f_blocks / 20) + 1; long twentymb = (20 * 1024 * 1024 / (long)data->fsp.f_bsize) + 1; long cushion = fivepc < twentymb ? fivepc : twentymb; - _alpm_log(PM_LOG_DEBUG, "partition %s, needed %ld, cushion %ld, free %ld\n", + _alpm_log(handle, ALPM_LOG_DEBUG, "partition %s, needed %ld, cushion %ld, free %ld\n", data->mount_dir, data->max_blocks_needed, cushion, (unsigned long)data->fsp.f_bfree); if(data->max_blocks_needed + cushion >= 0 && (unsigned long)(data->max_blocks_needed + cushion) > data->fsp.f_bfree) { - _alpm_log(PM_LOG_ERROR, _("Partition %s too full: %ld blocks needed, %ld blocks free\n"), + _alpm_log(handle, ALPM_LOG_ERROR, _("Partition %s too full: %ld blocks needed, %ld blocks free\n"), data->mount_dir, data->max_blocks_needed + cushion, (unsigned long)data->fsp.f_bfree); - abort = 1; + error = 1; } } } @@ -348,11 +324,11 @@ int _alpm_check_diskspace(pmtrans_t *trans, pmdb_t *db_local) } FREELIST(mount_points); - if(abort) { - RET_ERR(PM_ERR_DISK_SPACE, -1); + if(error) { + RET_ERR(handle, ALPM_ERR_DISK_SPACE, -1); } - return(0); + return 0; } /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/diskspace.h b/lib/libalpm/diskspace.h index 2894a0c2..79e16772 100644 --- a/lib/libalpm/diskspace.h +++ b/lib/libalpm/diskspace.h @@ -46,7 +46,7 @@ typedef struct __alpm_mountpoint_t { FSSTATSTYPE fsp; } alpm_mountpoint_t; -int _alpm_check_diskspace(pmtrans_t *trans, pmdb_t *db_local); +int _alpm_check_diskspace(alpm_handle_t *handle); #endif /* _ALPM_DISKSPACE_H */ diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c index e3d30f23..dc4f91e5 100644 --- a/lib/libalpm/dload.c +++ b/lib/libalpm/dload.c @@ -29,14 +29,9 @@ #include <sys/types.h> #include <sys/stat.h> #include <signal.h> -/* the following two are needed for FreeBSD's libfetch */ -#include <limits.h> /* PATH_MAX */ -#if defined(HAVE_SYS_PARAM_H) -#include <sys/param.h> /* MAXHOSTNAMELEN */ -#endif -#ifdef HAVE_LIBFETCH -#include <fetch.h> +#ifdef HAVE_LIBCURL +#include <curl/curl.h> #endif /* libalpm */ @@ -47,112 +42,244 @@ #include "util.h" #include "handle.h" -static char *get_filename(const char *url) { +static const char *get_filename(const char *url) +{ char *filename = strrchr(url, '/'); if(filename != NULL) { filename++; } - return(filename); + return filename; } -#ifdef HAVE_LIBFETCH -static char *get_destfile(const char *path, const char *filename) { - char *destfile; - /* len = localpath len + filename len + null */ - size_t len = strlen(path) + strlen(filename) + 1; - CALLOC(destfile, len, sizeof(char), RET_ERR(PM_ERR_MEMORY, NULL)); - snprintf(destfile, len, "%s%s", path, filename); +#ifdef HAVE_LIBCURL +static double prevprogress; /* last download amount */ - return(destfile); +static char *get_fullpath(const char *path, const char *filename, + const char *suffix) +{ + char *filepath; + /* len = localpath len + filename len + suffix len + null */ + size_t len = strlen(path) + strlen(filename) + strlen(suffix) + 1; + CALLOC(filepath, len, sizeof(char), return NULL); + snprintf(filepath, len, "%s%s%s", path, filename, suffix); + + return filepath; } -static char *get_tempfile(const char *path, const char *filename) { - char *tempfile; - /* len = localpath len + filename len + '.part' len + null */ - size_t len = strlen(path) + strlen(filename) + 6; - CALLOC(tempfile, len, sizeof(char), RET_ERR(PM_ERR_MEMORY, NULL)); - snprintf(tempfile, len, "%s%s.part", path, filename); +#define check_stop() if(dload_interrupted) { ret = -1; goto cleanup; } +enum sighandlers { OLD = 0, NEW = 1 }; - return(tempfile); +static int dload_interrupted; +static void inthandler(int UNUSED signum) +{ + dload_interrupted = 1; } -static const char *gethost(struct url *fileurl) +static int curl_progress(void *file, double dltotal, double dlnow, + double UNUSED ultotal, double UNUSED ulnow) { - const char *host = _("disk"); - if(strcmp(SCHEME_FILE, fileurl->scheme) != 0) { - host = fileurl->host; + struct dload_payload *payload = (struct dload_payload *)file; + double current_size, total_size; + + /* SIGINT sent, abort by alerting curl */ + if(dload_interrupted) { + return 1; + } + + /* none of what follows matters if the front end has no callback */ + if(payload->handle->dlcb == NULL) { + return 0; + } + + current_size = payload->initial_size + dlnow; + total_size = payload->initial_size + dltotal; + + if(DOUBLE_EQ(dltotal, 0) || DOUBLE_EQ(prevprogress, total_size)) { + return 0; + } + + /* initialize the progress bar here to avoid displaying it when + * a repo is up to date and nothing gets downloaded */ + if(DOUBLE_EQ(prevprogress, 0)) { + payload->handle->dlcb(payload->filename, 0, (long)dltotal); } - return(host); + + payload->handle->dlcb(payload->filename, (long)current_size, (long)total_size); + + prevprogress = current_size; + + return 0; } -int dload_interrupted; -static void inthandler(int signum) +static int curl_gethost(const char *url, char *buffer) { - dload_interrupted = 1; + size_t hostlen; + char *p; + + if(strncmp(url, "file://", 7) == 0) { + strcpy(buffer, _("disk")); + } else { + p = strstr(url, "//"); + if(!p) { + return 1; + } + p += 2; /* jump over the found // */ + hostlen = strcspn(p, "/"); + if(hostlen > 255) { + /* buffer overflow imminent */ + return 1; + } + snprintf(buffer, hostlen + 1, "%s", p); + } + + return 0; } -#define check_stop() if(dload_interrupted) { ret = -1; goto cleanup; } -enum sighandlers { OLD = 0, NEW = 1 }; +static int utimes_long(const char *path, long seconds) +{ + if(seconds != -1) { + struct timeval tv[2]; + memset(&tv, 0, sizeof(tv)); + tv[0].tv_sec = tv[1].tv_sec = seconds; + return utimes(path, tv); + } + return 0; +} + +static size_t parse_headers(void *ptr, size_t size, size_t nmemb, void *user) +{ + size_t realsize = size * nmemb; + const char *fptr, *endptr = NULL; + const char * const cd_header = "Content-Disposition:"; + const char * const fn_key = "filename="; + struct dload_payload *payload = (struct dload_payload *)user; + + if(_alpm_raw_ncmp(cd_header, ptr, strlen(cd_header)) == 0) { + if((fptr = strstr(ptr, fn_key))) { + fptr += strlen(fn_key); + + /* find the end of the field, which is either a semi-colon, or the end of + * the data. As per curl_easy_setopt(3), we cannot count on headers being + * null terminated, so we look for the closing \r\n */ + endptr = fptr + strcspn(fptr, ";\r\n") - 1; + + /* remove quotes */ + if(*fptr == '"' && *endptr == '"') { + fptr++; + endptr--; + } + + STRNDUP(payload->cd_filename, fptr, endptr - fptr + 1, + RET_ERR(payload->handle, ALPM_ERR_MEMORY, realsize)); + } + } -static int download_internal(const char *url, const char *localpath, - int force) { + return realsize; +} + +static int curl_download_internal(struct dload_payload *payload, + const char *localpath, char **final_file) +{ + int ret = -1, should_unlink = 0; FILE *localf = NULL; + const char *useragent; + const char *open_mode = "wb"; + char *destfile = NULL, *tempfile = NULL, *effective_url; + /* RFC1123 states applications should support this length */ + char hostname[256]; + char error_buffer[CURL_ERROR_SIZE]; struct stat st; - int ret = 0; - off_t dl_thisfile = 0; - ssize_t nread = 0; - char *tempfile, *destfile, *filename; + long timecond, remote_time = -1; + double remote_size, bytes_dl; struct sigaction sig_pipe[2], sig_int[2]; + /* shortcut to our handle within the payload */ + alpm_handle_t *handle = payload->handle; - off_t local_size = 0; - time_t local_time = 0; - - struct url *fileurl; - struct url_stat ust; - fetchIO *dlf = NULL; - - char buffer[PM_DLBUF_LEN]; + if(!payload->filename) { + payload->filename = get_filename(payload->fileurl); + } + if(!payload->filename || curl_gethost(payload->fileurl, hostname) != 0) { + _alpm_log(handle, ALPM_LOG_ERROR, _("url '%s' is invalid\n"), payload->fileurl); + RET_ERR(handle, ALPM_ERR_SERVER_BAD_URL, -1); + } - filename = get_filename(url); - if(!filename) { - _alpm_log(PM_LOG_ERROR, _("url '%s' is invalid\n"), url); - RET_ERR(PM_ERR_SERVER_BAD_URL, -1); + if(strlen(payload->filename) > 0 && strcmp(payload->filename, ".sig") != 0) { + destfile = get_fullpath(localpath, payload->filename, ""); + tempfile = get_fullpath(localpath, payload->filename, ".part"); + if(!destfile || !tempfile) { + goto cleanup; + } + } else { + /* URL isn't to a file and ended with a slash */ + int fd; + char randpath[PATH_MAX]; + + /* we can't support resuming this kind of download, so a partial transfer + * will be destroyed */ + should_unlink = 1; + + /* create a random filename, which is opened with O_EXCL */ + snprintf(randpath, PATH_MAX, "%salpmtmp.XXXXXX", localpath); + if((fd = mkstemp(randpath)) == -1 || !(localf = fdopen(fd, open_mode))) { + unlink(randpath); + close(fd); + _alpm_log(handle, ALPM_LOG_ERROR, + _("failed to create temporary file for download\n")); + goto cleanup; + } + /* localf now points to our alpmtmp.XXXXXX */ + STRDUP(tempfile, randpath, RET_ERR(handle, ALPM_ERR_MEMORY, -1)); + payload->filename = strrchr(randpath, '/') + 1; } - fileurl = fetchParseURL(url); - if(!fileurl) { - _alpm_log(PM_LOG_ERROR, _("url '%s' is invalid\n"), url); - RET_ERR(PM_ERR_LIBFETCH, -1); + error_buffer[0] = '\0'; + + /* the curl_easy handle is initialized with the alpm handle, so we only need + * to reset the curl handle set parameters for each time it's used. */ + curl_easy_reset(handle->curl); + curl_easy_setopt(handle->curl, CURLOPT_URL, payload->fileurl); + curl_easy_setopt(handle->curl, CURLOPT_FAILONERROR, 1L); + curl_easy_setopt(handle->curl, CURLOPT_ERRORBUFFER, error_buffer); + curl_easy_setopt(handle->curl, CURLOPT_CONNECTTIMEOUT, 10L); + curl_easy_setopt(handle->curl, CURLOPT_FILETIME, 1L); + curl_easy_setopt(handle->curl, CURLOPT_NOPROGRESS, 0L); + curl_easy_setopt(handle->curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(handle->curl, CURLOPT_PROGRESSFUNCTION, curl_progress); + curl_easy_setopt(handle->curl, CURLOPT_PROGRESSDATA, (void *)payload); + curl_easy_setopt(handle->curl, CURLOPT_LOW_SPEED_LIMIT, 1024L); + curl_easy_setopt(handle->curl, CURLOPT_LOW_SPEED_TIME, 10L); + curl_easy_setopt(handle->curl, CURLOPT_HEADERFUNCTION, parse_headers); + curl_easy_setopt(handle->curl, CURLOPT_WRITEHEADER, (void *)payload); + + if(payload->max_size) { + curl_easy_setopt(handle->curl, CURLOPT_MAXFILESIZE, payload->max_size); } - destfile = get_destfile(localpath, filename); - tempfile = get_tempfile(localpath, filename); - - if(stat(tempfile, &st) == 0 && S_ISREG(st.st_mode) && st.st_size > 0) { - _alpm_log(PM_LOG_DEBUG, "tempfile found, attempting continuation\n"); - local_time = fileurl->last_modified = st.st_mtime; - local_size = fileurl->offset = (off_t)st.st_size; - dl_thisfile = st.st_size; - localf = fopen(tempfile, "ab"); - } else if(!force && stat(destfile, &st) == 0 && S_ISREG(st.st_mode) && st.st_size > 0) { - _alpm_log(PM_LOG_DEBUG, "destfile found, using mtime only\n"); - local_time = fileurl->last_modified = st.st_mtime; - local_size = /* no fu->off here */ (off_t)st.st_size; - } else { - _alpm_log(PM_LOG_DEBUG, "no file found matching criteria, starting from scratch\n"); + useragent = getenv("HTTP_USER_AGENT"); + if(useragent != NULL) { + curl_easy_setopt(handle->curl, CURLOPT_USERAGENT, useragent); } - /* pass the raw filename for passing to the callback function */ - _alpm_log(PM_LOG_DEBUG, "using '%s' for download progress\n", filename); + if(!payload->allow_resume && !payload->force && stat(destfile, &st) == 0) { + /* start from scratch, but only download if our local is out of date. */ + curl_easy_setopt(handle->curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE); + curl_easy_setopt(handle->curl, CURLOPT_TIMEVALUE, (long)st.st_mtime); + } else if(stat(tempfile, &st) == 0 && payload->allow_resume) { + /* a previous partial download exists, resume from end of file. */ + open_mode = "ab"; + curl_easy_setopt(handle->curl, CURLOPT_RESUME_FROM, (long)st.st_size); + _alpm_log(handle, ALPM_LOG_DEBUG, "tempfile found, attempting continuation\n"); + payload->initial_size = (double)st.st_size; + } - /* print proxy info for debug purposes */ - _alpm_log(PM_LOG_DEBUG, "HTTP_PROXY: %s\n", getenv("HTTP_PROXY")); - _alpm_log(PM_LOG_DEBUG, "http_proxy: %s\n", getenv("http_proxy")); - _alpm_log(PM_LOG_DEBUG, "FTP_PROXY: %s\n", getenv("FTP_PROXY")); - _alpm_log(PM_LOG_DEBUG, "ftp_proxy: %s\n", getenv("ftp_proxy")); + if(localf == NULL) { + localf = fopen(tempfile, open_mode); + if(localf == NULL) { + goto cleanup; + } + } - /* 10s timeout */ - fetchTimeout = 10; + curl_easy_setopt(handle->curl, CURLOPT_WRITEDATA, localf); /* ignore any SIGPIPE signals- these may occur if our FTP socket dies or * something along those lines. Store the old signal handler first. */ @@ -169,169 +296,98 @@ static int download_internal(const char *url, const char *localpath, sigaction(SIGINT, NULL, &sig_int[OLD]); sigaction(SIGINT, &sig_int[NEW], NULL); - /* NOTE: libfetch does not reset the error code, be sure to do it before - * calls into the library */ - - /* TODO: if we call fetchStat() and get a redirect (disabling automagic - * redirect following), we should repeat the file locator stuff and get a new - * filename rather than only base if off the first URL, and then verify - * get_filename() didn't return ''. Of course, libfetch might not even allow - * us to even get that URL...FS#22645. This would allow us to download things - * without totally puking like - * http://www.archlinux.org/packages/community/x86_64/exim/download/ */ - - /* find out the remote size *and* mtime in one go. there is a lot of - * trouble in trying to do both size and "if-modified-since" logic in a - * non-stat request, so avoid it. */ - fetchLastErrCode = 0; - if(fetchStat(fileurl, &ust, "") == -1) { - pm_errno = PM_ERR_LIBFETCH; - _alpm_log(PM_LOG_ERROR, _("failed retrieving file '%s' from %s : %s\n"), - filename, gethost(fileurl), fetchLastErrString); - ret = -1; + /* Progress 0 - initialize */ + prevprogress = 0; + + /* perform transfer */ + handle->curlerr = curl_easy_perform(handle->curl); + + /* was it a success? */ + if(handle->curlerr == CURLE_ABORTED_BY_CALLBACK) { goto cleanup; - } - check_stop(); - - _alpm_log(PM_LOG_DEBUG, "ust.mtime: %ld local_time: %ld compare: %ld\n", - ust.mtime, local_time, local_time - ust.mtime); - _alpm_log(PM_LOG_DEBUG, "ust.size: %jd local_size: %jd compare: %jd\n", - (intmax_t)ust.size, (intmax_t)local_size, (intmax_t)(local_size - ust.size)); - if(!force && ust.mtime && ust.mtime == local_time - && ust.size && ust.size == local_size) { - /* the remote time and size values agreed with what we have, so move on - * because there is nothing more to do. */ - _alpm_log(PM_LOG_DEBUG, "files are identical, skipping %s\n", filename); - ret = 1; + } else if(handle->curlerr != CURLE_OK) { + if(!payload->errors_ok) { + handle->pm_errno = ALPM_ERR_LIBCURL; + _alpm_log(handle, ALPM_LOG_ERROR, _("failed retrieving file '%s' from %s : %s\n"), + payload->filename, hostname, error_buffer); + } else { + _alpm_log(handle, ALPM_LOG_DEBUG, "failed retrieving file '%s' from %s : %s\n", + payload->filename, hostname, error_buffer); + } + unlink(tempfile); goto cleanup; } - if(!ust.mtime || ust.mtime != local_time) { - _alpm_log(PM_LOG_DEBUG, "mtimes were different or unavailable, downloading %s from beginning\n", filename); - fileurl->offset = 0; - } - fetchLastErrCode = 0; - dlf = fetchGet(fileurl, ""); - check_stop(); + /* retrieve info about the state of the transfer */ + curl_easy_getinfo(handle->curl, CURLINFO_FILETIME, &remote_time); + curl_easy_getinfo(handle->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &remote_size); + curl_easy_getinfo(handle->curl, CURLINFO_SIZE_DOWNLOAD, &bytes_dl); + curl_easy_getinfo(handle->curl, CURLINFO_CONDITION_UNMET, &timecond); + curl_easy_getinfo(handle->curl, CURLINFO_EFFECTIVE_URL, &effective_url); - if(fetchLastErrCode != 0 || dlf == NULL) { - pm_errno = PM_ERR_LIBFETCH; - _alpm_log(PM_LOG_ERROR, _("failed retrieving file '%s' from %s : %s\n"), - filename, gethost(fileurl), fetchLastErrString); - ret = -1; + /* time condition was met and we didn't download anything. we need to + * clean up the 0 byte .part file that's left behind. */ + if(timecond == 1 && DOUBLE_EQ(bytes_dl, 0)) { + ret = 1; + unlink(tempfile); goto cleanup; - } else { - _alpm_log(PM_LOG_DEBUG, "connected to %s successfully\n", fileurl->host); } - if(localf && fileurl->offset == 0) { - _alpm_log(PM_LOG_WARNING, _("resuming download of %s not possible; starting over\n"), filename); - fclose(localf); - localf = NULL; - } else if(fileurl->offset) { - _alpm_log(PM_LOG_DEBUG, "resuming download at position %jd\n", (intmax_t)fileurl->offset); + /* remote_size isn't necessarily the full size of the file, just what the + * server reported as remaining to download. compare it to what curl reported + * as actually being transferred during curl_easy_perform() */ + if(!DOUBLE_EQ(remote_size, -1) && !DOUBLE_EQ(bytes_dl, -1) && + !DOUBLE_EQ(bytes_dl, remote_size)) { + handle->pm_errno = ALPM_ERR_RETRIEVE; + _alpm_log(handle, ALPM_LOG_ERROR, _("%s appears to be truncated: %jd/%jd bytes\n"), + payload->filename, (intmax_t)bytes_dl, (intmax_t)remote_size); + goto cleanup; } - - if(localf == NULL) { - _alpm_rmrf(tempfile); - fileurl->offset = (off_t)0; - dl_thisfile = 0; - localf = fopen(tempfile, "wb"); - if(localf == NULL) { /* still null? */ - pm_errno = PM_ERR_RETRIEVE; - _alpm_log(PM_LOG_ERROR, _("error writing to file '%s': %s\n"), - tempfile, strerror(errno)); - ret = -1; - goto cleanup; + if(payload->cd_filename) { + /* content-disposition header has a better name for our file */ + free(destfile); + destfile = get_fullpath(localpath, payload->cd_filename, ""); + } else { + const char *effective_filename = strrchr(effective_url, '/'); + if(effective_filename) { + effective_filename++; + + /* if destfile was never set, we wrote to a tempfile. even if destfile is + * set, we may have followed some redirects and the effective url may + * have a better suggestion as to what to name our file. in either case, + * refactor destfile to this newly derived name. */ + if(!destfile || strcmp(effective_filename, strrchr(destfile, '/') + 1) != 0) { + free(destfile); + destfile = get_fullpath(localpath, effective_filename, ""); + } } } - /* Progress 0 - initialize */ - if(handle->dlcb) { - handle->dlcb(filename, 0, ust.size); + ret = 0; + +cleanup: + if(localf != NULL) { + fclose(localf); + utimes_long(tempfile, remote_time); } - while((nread = fetchIO_read(dlf, buffer, PM_DLBUF_LEN)) > 0) { - check_stop(); - size_t nwritten = 0; - nwritten = fwrite(buffer, 1, (size_t)nread, localf); - if((nwritten != (size_t)nread) || ferror(localf)) { - pm_errno = PM_ERR_RETRIEVE; - _alpm_log(PM_LOG_ERROR, _("error writing to file '%s': %s\n"), - tempfile, strerror(errno)); + if(ret == 0) { + if(rename(tempfile, destfile)) { + _alpm_log(handle, ALPM_LOG_ERROR, _("could not rename %s to %s (%s)\n"), + tempfile, destfile, strerror(errno)); ret = -1; - goto cleanup; - } - dl_thisfile += nread; - - if(handle->dlcb) { - handle->dlcb(filename, dl_thisfile, ust.size); + } else if(final_file) { + *final_file = strdup(strrchr(destfile, '/') + 1); } } - /* did the transfer complete normally? */ - if (nread == -1) { - /* not PM_ERR_LIBFETCH here because libfetch error string might be empty */ - pm_errno = PM_ERR_RETRIEVE; - _alpm_log(PM_LOG_ERROR, _("failed retrieving file '%s' from %s\n"), - filename, gethost(fileurl)); - ret = -1; - goto cleanup; + if(dload_interrupted && should_unlink) { + unlink(tempfile); } - if (ust.size != -1 && dl_thisfile < ust.size) { - pm_errno = PM_ERR_RETRIEVE; - _alpm_log(PM_LOG_ERROR, _("%s appears to be truncated: %jd/%jd bytes\n"), - filename, (intmax_t)dl_thisfile, (intmax_t)ust.size); - ret = -1; - goto cleanup; - } - - /* probably safer to close the file descriptors now before renaming the file, - * for example to make sure the buffers are flushed. - */ - fclose(localf); - localf = NULL; - fetchIO_close(dlf); - dlf = NULL; - - /* set the times on the file to the same as that of the remote file */ - if(ust.mtime) { - struct timeval tv[2]; - memset(&tv, 0, sizeof(tv)); - tv[0].tv_sec = ust.atime; - tv[1].tv_sec = ust.mtime; - utimes(tempfile, tv); - } - if(rename(tempfile, destfile)) { - _alpm_log(PM_LOG_ERROR, _("could not rename %s to %s (%s)\n"), - tempfile, destfile, strerror(errno)); - ret = -1; - goto cleanup; - } - ret = 0; - -cleanup: FREE(tempfile); FREE(destfile); - if(localf != NULL) { - /* if we still had a local file open, we got interrupted. set the mtimes on - * the file accordingly. */ - fflush(localf); - if(ust.mtime) { - struct timeval tv[2]; - memset(&tv, 0, sizeof(tv)); - tv[0].tv_sec = ust.atime; - tv[1].tv_sec = ust.mtime; - futimes(fileno(localf), tv); - } - fclose(localf); - } - if(dlf != NULL) { - fetchIO_close(dlf); - } - fetchFreeURL(fileurl); /* restore the old signal handlers */ sigaction(SIGINT, &sig_int[OLD], NULL); @@ -341,106 +397,106 @@ cleanup: raise(SIGINT); } - return(ret); + return ret; } #endif -static int download(const char *url, const char *localpath, - int force) { +/** Download a file given by a URL to a local directory. + * Does not overwrite an existing file if the download fails. + * @param payload the payload context + * @param localpath the directory to save the file in + * @param final_file the real name of the downloaded file (may be NULL) + * @return 0 on success, -1 on error (pm_errno is set accordingly if errors_ok == 0) + */ +int _alpm_download(struct dload_payload *payload, const char *localpath, + char **final_file) +{ + alpm_handle_t *handle = payload->handle; + if(handle->fetchcb == NULL) { -#ifdef HAVE_LIBFETCH - return(download_internal(url, localpath, force)); +#ifdef HAVE_LIBCURL + return curl_download_internal(payload, localpath, final_file); #else - RET_ERR(PM_ERR_EXTERNAL_DOWNLOAD, -1); + RET_ERR(handle, ALPM_ERR_EXTERNAL_DOWNLOAD, -1); #endif } else { - int ret = handle->fetchcb(url, localpath, force); - if(ret == -1) { - RET_ERR(PM_ERR_EXTERNAL_DOWNLOAD, -1); + int ret = handle->fetchcb(payload->fileurl, localpath, payload->force); + if(ret == -1 && !payload->errors_ok) { + RET_ERR(handle, ALPM_ERR_EXTERNAL_DOWNLOAD, -1); } - return(ret); + return ret; } } -/* - * Download a single file - * - servers must be a list of urls WITHOUT trailing slashes. - * - * RETURN: 0 for successful download - * 1 if the files are identical - * -1 on error - */ -int _alpm_download_single_file(const char *filename, - alpm_list_t *servers, const char *localpath, - int force) +/** Fetch a remote pkg. */ +char SYMEXPORT *alpm_fetch_pkgurl(alpm_handle_t *handle, const char *url) { - alpm_list_t *i; - int ret = -1; + char *filepath; + const char *cachedir; + char *final_file = NULL; + struct dload_payload *payload; + int ret; - ASSERT(servers != NULL, RET_ERR(PM_ERR_SERVER_NONE, -1)); + CHECK_HANDLE(handle, return NULL); - for(i = servers; i; i = i->next) { - const char *server = i->data; - char *fileurl = NULL; - size_t len; + /* find a valid cache dir to download to */ + cachedir = _alpm_filecache_setup(handle); - /* print server + filename into a buffer */ - len = strlen(server) + strlen(filename) + 2; - CALLOC(fileurl, len, sizeof(char), RET_ERR(PM_ERR_MEMORY, -1)); - snprintf(fileurl, len, "%s/%s", server, filename); + CALLOC(payload, 1, sizeof(*payload), RET_ERR(handle, ALPM_ERR_MEMORY, NULL)); + payload->handle = handle; + payload->fileurl = strdup(url); + payload->allow_resume = 1; - ret = download(fileurl, localpath, force); - FREE(fileurl); - if(ret != -1) { - break; - } + /* download the file */ + ret = _alpm_download(payload, cachedir, &final_file); + if(ret == -1) { + _alpm_log(handle, ALPM_LOG_WARNING, _("failed to download %s\n"), url); + return NULL; } + _alpm_log(handle, ALPM_LOG_DEBUG, "successfully downloaded %s\n", url); - return(ret); -} - -int _alpm_download_files(alpm_list_t *files, - alpm_list_t *servers, const char *localpath) -{ - int ret = 0; - alpm_list_t *lp; - - for(lp = files; lp; lp = lp->next) { - char *filename = lp->data; - if(_alpm_download_single_file(filename, servers, - localpath, 0) == -1) { - ret++; + /* attempt to download the signature */ + if(ret == 0 && (handle->siglevel & ALPM_SIG_PACKAGE)) { + char *sig_final_file = NULL; + size_t len; + struct dload_payload *sig_payload; + + CALLOC(sig_payload, 1, sizeof(*sig_payload), RET_ERR(handle, ALPM_ERR_MEMORY, NULL)); + len = strlen(url) + 5; + CALLOC(sig_payload->fileurl, len, sizeof(char), RET_ERR(handle, ALPM_ERR_MEMORY, NULL)); + snprintf(sig_payload->fileurl, len, "%s.sig", url); + sig_payload->handle = handle; + sig_payload->force = 1; + sig_payload->errors_ok = (handle->siglevel & ALPM_SIG_PACKAGE_OPTIONAL); + + ret = _alpm_download(sig_payload, cachedir, &sig_final_file); + if(ret == -1 && !sig_payload->errors_ok) { + _alpm_log(handle, ALPM_LOG_WARNING, _("failed to download %s\n"), sig_payload->fileurl); + /* Warn now, but don't return NULL. We will fail later during package + * load time. */ + } else if(ret == 0) { + _alpm_log(handle, ALPM_LOG_DEBUG, "successfully downloaded %s\n", sig_payload->fileurl); } + FREE(sig_final_file); + _alpm_dload_payload_free(sig_payload); } - return(ret); -} - -/** Fetch a remote pkg. */ -char SYMEXPORT *alpm_fetch_pkgurl(const char *url) -{ - char *filename, *filepath; - const char *cachedir; - int ret; - - ALPM_LOG_FUNC; + /* we should be able to find the file the second time around */ + filepath = _alpm_filecache_find(handle, final_file); + FREE(final_file); + _alpm_dload_payload_free(payload); - filename = get_filename(url); + return filepath; +} - /* find a valid cache dir to download to */ - cachedir = _alpm_filecache_setup(); +void _alpm_dload_payload_free(struct dload_payload *payload) { + struct dload_payload *load = (struct dload_payload *)payload; - /* download the file */ - ret = download(url, cachedir, 0); - if(ret == -1) { - _alpm_log(PM_LOG_WARNING, _("failed to download %s\n"), url); - return(NULL); - } - _alpm_log(PM_LOG_DEBUG, "successfully downloaded %s\n", url); + ASSERT(load, return); - /* we should be able to find the file the second time around */ - filepath = _alpm_filecache_find(filename); - return(filepath); + FREE(load->fileurl); + FREE(load->cd_filename); + FREE(load); } /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/dload.h b/lib/libalpm/dload.h index 63266491..341a4a1a 100644 --- a/lib/libalpm/dload.h +++ b/lib/libalpm/dload.h @@ -25,14 +25,22 @@ #include <time.h> -#define PM_DLBUF_LEN (1024 * 16) +struct dload_payload { + alpm_handle_t *handle; + const char *filename; + char *cd_filename; + char *fileurl; + double initial_size; + long max_size; + int force; + int allow_resume; + int errors_ok; +}; -int _alpm_download_single_file(const char *filename, - alpm_list_t *servers, const char *localpath, - int force); +void _alpm_dload_payload_free(struct dload_payload *payload); -int _alpm_download_files(alpm_list_t *files, - alpm_list_t *servers, const char *localpath); +int _alpm_download(struct dload_payload *payload, const char *localpath, + char **final_file); #endif /* _ALPM_DLOAD_H */ diff --git a/lib/libalpm/error.c b/lib/libalpm/error.c index 21fbb48f..7e0e5c85 100644 --- a/lib/libalpm/error.c +++ b/lib/libalpm/error.c @@ -20,141 +20,140 @@ #include "config.h" -/* TODO: needed for the libfetch stuff, unfortunately- we should kill it */ -#include <stdio.h> -/* the following two are needed for FreeBSD's libfetch */ -#include <limits.h> /* PATH_MAX */ -#if defined(HAVE_SYS_PARAM_H) -#include <sys/param.h> /* MAXHOSTNAMELEN */ -#endif - -#ifdef HAVE_LIBFETCH -#include <fetch.h> /* fetchLastErrString */ +#ifdef HAVE_LIBCURL +#include <curl/curl.h> #endif /* libalpm */ #include "util.h" #include "alpm.h" +#include "handle.h" -const char SYMEXPORT *alpm_strerrorlast(void) +enum _alpm_errno_t SYMEXPORT alpm_errno(alpm_handle_t *handle) { - return alpm_strerror(pm_errno); + return handle->pm_errno; } -const char SYMEXPORT *alpm_strerror(int err) +const char SYMEXPORT *alpm_strerror(enum _alpm_errno_t err) { switch(err) { /* System */ - case PM_ERR_MEMORY: + case ALPM_ERR_MEMORY: return _("out of memory!"); - case PM_ERR_SYSTEM: + case ALPM_ERR_SYSTEM: return _("unexpected system error"); - case PM_ERR_BADPERMS: + case ALPM_ERR_BADPERMS: return _("insufficient privileges"); - case PM_ERR_NOT_A_FILE: + case ALPM_ERR_NOT_A_FILE: return _("could not find or read file"); - case PM_ERR_NOT_A_DIR: + case ALPM_ERR_NOT_A_DIR: return _("could not find or read directory"); - case PM_ERR_WRONG_ARGS: + case ALPM_ERR_WRONG_ARGS: return _("wrong or NULL argument passed"); - case PM_ERR_DISK_SPACE: + case ALPM_ERR_DISK_SPACE: return _("not enough free disk space"); /* Interface */ - case PM_ERR_HANDLE_NULL: + case ALPM_ERR_HANDLE_NULL: return _("library not initialized"); - case PM_ERR_HANDLE_NOT_NULL: + case ALPM_ERR_HANDLE_NOT_NULL: return _("library already initialized"); - case PM_ERR_HANDLE_LOCK: + case ALPM_ERR_HANDLE_LOCK: return _("unable to lock database"); /* Databases */ - case PM_ERR_DB_OPEN: + case ALPM_ERR_DB_OPEN: return _("could not open database"); - case PM_ERR_DB_CREATE: + case ALPM_ERR_DB_CREATE: return _("could not create database"); - case PM_ERR_DB_NULL: + case ALPM_ERR_DB_NULL: return _("database not initialized"); - case PM_ERR_DB_NOT_NULL: + case ALPM_ERR_DB_NOT_NULL: return _("database already registered"); - case PM_ERR_DB_NOT_FOUND: + case ALPM_ERR_DB_NOT_FOUND: return _("could not find database"); - case PM_ERR_DB_VERSION: + case ALPM_ERR_DB_INVALID: + return _("invalid or corrupted database"); + case ALPM_ERR_DB_INVALID_SIG: + return _("invalid or corrupted database (PGP signature)"); + case ALPM_ERR_DB_VERSION: return _("database is incorrect version"); - case PM_ERR_DB_WRITE: + case ALPM_ERR_DB_WRITE: return _("could not update database"); - case PM_ERR_DB_REMOVE: + case ALPM_ERR_DB_REMOVE: return _("could not remove database entry"); /* Servers */ - case PM_ERR_SERVER_BAD_URL: + case ALPM_ERR_SERVER_BAD_URL: return _("invalid url for server"); - case PM_ERR_SERVER_NONE: + case ALPM_ERR_SERVER_NONE: return _("no servers configured for repository"); /* Transactions */ - case PM_ERR_TRANS_NOT_NULL: + case ALPM_ERR_TRANS_NOT_NULL: return _("transaction already initialized"); - case PM_ERR_TRANS_NULL: + case ALPM_ERR_TRANS_NULL: return _("transaction not initialized"); - case PM_ERR_TRANS_DUP_TARGET: + case ALPM_ERR_TRANS_DUP_TARGET: return _("duplicate target"); - case PM_ERR_TRANS_NOT_INITIALIZED: + case ALPM_ERR_TRANS_NOT_INITIALIZED: return _("transaction not initialized"); - case PM_ERR_TRANS_NOT_PREPARED: + case ALPM_ERR_TRANS_NOT_PREPARED: return _("transaction not prepared"); - case PM_ERR_TRANS_ABORT: + case ALPM_ERR_TRANS_ABORT: return _("transaction aborted"); - case PM_ERR_TRANS_TYPE: + case ALPM_ERR_TRANS_TYPE: return _("operation not compatible with the transaction type"); - case PM_ERR_TRANS_NOT_LOCKED: + case ALPM_ERR_TRANS_NOT_LOCKED: return _("transaction commit attempt when database is not locked"); /* Packages */ - case PM_ERR_PKG_NOT_FOUND: + case ALPM_ERR_PKG_NOT_FOUND: return _("could not find or read package"); - case PM_ERR_PKG_IGNORED: + case ALPM_ERR_PKG_IGNORED: return _("operation cancelled due to ignorepkg"); - case PM_ERR_PKG_INVALID: - return _("invalid or corrupted package"); - case PM_ERR_PKG_OPEN: + case ALPM_ERR_PKG_INVALID: + return _("invalid or corrupted package (checksum)"); + case ALPM_ERR_PKG_INVALID_SIG: + return _("invalid or corrupted package (PGP signature)"); + case ALPM_ERR_PKG_OPEN: return _("cannot open package file"); - case PM_ERR_PKG_CANT_REMOVE: + case ALPM_ERR_PKG_CANT_REMOVE: return _("cannot remove all files for package"); - case PM_ERR_PKG_INVALID_NAME: + case ALPM_ERR_PKG_INVALID_NAME: return _("package filename is not valid"); - case PM_ERR_PKG_INVALID_ARCH: + case ALPM_ERR_PKG_INVALID_ARCH: return _("package architecture is not valid"); - case PM_ERR_PKG_REPO_NOT_FOUND: + case ALPM_ERR_PKG_REPO_NOT_FOUND: return _("could not find repository for target"); + /* Signatures */ + case ALPM_ERR_SIG_MISSING: + return _("missing PGP signature"); + case ALPM_ERR_SIG_INVALID: + return _("invalid PGP signature"); /* Deltas */ - case PM_ERR_DLT_INVALID: + case ALPM_ERR_DLT_INVALID: return _("invalid or corrupted delta"); - case PM_ERR_DLT_PATCHFAILED: + case ALPM_ERR_DLT_PATCHFAILED: return _("delta patch failed"); /* Dependencies */ - case PM_ERR_UNSATISFIED_DEPS: + case ALPM_ERR_UNSATISFIED_DEPS: return _("could not satisfy dependencies"); - case PM_ERR_CONFLICTING_DEPS: + case ALPM_ERR_CONFLICTING_DEPS: return _("conflicting dependencies"); - case PM_ERR_FILE_CONFLICTS: + case ALPM_ERR_FILE_CONFLICTS: return _("conflicting files"); /* Miscellaenous */ - case PM_ERR_RETRIEVE: + case ALPM_ERR_RETRIEVE: return _("failed to retrieve some files"); - case PM_ERR_WRITE: - return _("failed to copy some file"); - case PM_ERR_INVALID_REGEX: + case ALPM_ERR_INVALID_REGEX: return _("invalid regular expression"); /* Errors from external libraries- our own wrapper error */ - case PM_ERR_LIBARCHIVE: + case ALPM_ERR_LIBARCHIVE: /* it would be nice to use archive_error_string() here, but that * requires the archive struct, so we can't. Just use a generic * error string instead. */ return _("libarchive error"); - case PM_ERR_LIBFETCH: -#ifdef HAVE_LIBFETCH - return fetchLastErrString; -#else - /* obviously shouldn't get here... */ + case ALPM_ERR_LIBCURL: return _("download library error"); -#endif - case PM_ERR_EXTERNAL_DOWNLOAD: + case ALPM_ERR_GPGME: + return _("gpgme error"); + case ALPM_ERR_EXTERNAL_DOWNLOAD: return _("error invoking external downloader"); /* Unknown error! */ default: diff --git a/lib/libalpm/graph.c b/lib/libalpm/graph.c new file mode 100644 index 00000000..3a7f24b8 --- /dev/null +++ b/lib/libalpm/graph.c @@ -0,0 +1,41 @@ +/* + * graph.c - helpful graph structure and setup/teardown methods + * + * Copyright (c) 2007-2011 Pacman Development Team <pacman-dev@archlinux.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include "graph.h" +#include "util.h" +#include "log.h" + +alpm_graph_t *_alpm_graph_new(void) +{ + alpm_graph_t *graph = NULL; + + CALLOC(graph, 1, sizeof(alpm_graph_t), return NULL); + return graph; +} + +void _alpm_graph_free(void *data) +{ + alpm_graph_t *graph = data; + alpm_list_free(graph->children); + free(graph); +} + +/* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/graph.h b/lib/libalpm/graph.h index 07986f66..d4d134b5 100644 --- a/lib/libalpm/graph.h +++ b/lib/libalpm/graph.h @@ -1,8 +1,7 @@ /* * graph.h - helpful graph structure and setup/teardown methods * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> - * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> + * Copyright (c) 2007-2011 Pacman Development Team <pacman-dev@archlinux.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,34 +16,27 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#ifndef _ALPM_GRAPH_H +#define _ALPM_GRAPH_H + +#include "config.h" /* ensure off_t is correct length */ #include <sys/types.h> /* off_t */ #include "alpm_list.h" -#include "util.h" /* CALLOC() */ -struct __pmgraph_t { +typedef struct __alpm_graph_t { char state; /* 0: untouched, -1: entered, other: leaving time */ - void *data; off_t weight; /* weight of the node */ - struct __pmgraph_t *parent; /* where did we come from? */ + void *data; + struct __alpm_graph_t *parent; /* where did we come from? */ alpm_list_t *children; alpm_list_t *childptr; /* points to a child in children list */ -}; -typedef struct __pmgraph_t pmgraph_t; - -static pmgraph_t *_alpm_graph_new(void) -{ - pmgraph_t *graph = NULL; +} alpm_graph_t; - CALLOC(graph, 1, sizeof(pmgraph_t), RET_ERR(PM_ERR_MEMORY, NULL)); - return(graph); -} +alpm_graph_t *_alpm_graph_new(void); +void _alpm_graph_free(void *data); -static void _alpm_graph_free(void *data) -{ - pmgraph_t *graph = data; - alpm_list_free(graph->children); - free(graph); -} +#endif /* _ALPM_GRAPH_H */ +/* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/group.c b/lib/libalpm/group.c index 398c2588..47458df2 100644 --- a/lib/libalpm/group.c +++ b/lib/libalpm/group.c @@ -21,7 +21,6 @@ #include "config.h" #include <stdlib.h> -#include <stdio.h> #include <string.h> /* libalpm */ @@ -31,22 +30,18 @@ #include "log.h" #include "alpm.h" -pmgrp_t *_alpm_grp_new(const char *name) +alpm_group_t *_alpm_group_new(const char *name) { - pmgrp_t* grp; + alpm_group_t* grp; - ALPM_LOG_FUNC; + CALLOC(grp, 1, sizeof(alpm_group_t), return NULL); + STRDUP(grp->name, name, free(grp); return NULL); - CALLOC(grp, 1, sizeof(pmgrp_t), RET_ERR(PM_ERR_MEMORY, NULL)); - STRDUP(grp->name, name, RET_ERR(PM_ERR_MEMORY, NULL)); - - return(grp); + return grp; } -void _alpm_grp_free(pmgrp_t *grp) +void _alpm_group_free(alpm_group_t *grp) { - ALPM_LOG_FUNC; - if(grp == NULL) { return; } @@ -57,23 +52,4 @@ void _alpm_grp_free(pmgrp_t *grp) FREE(grp); } -const char SYMEXPORT *alpm_grp_get_name(const pmgrp_t *grp) -{ - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(grp != NULL, return(NULL)); - - return grp->name; -} - -alpm_list_t SYMEXPORT *alpm_grp_get_pkgs(const pmgrp_t *grp) -{ - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(grp != NULL, return(NULL)); - - return grp->packages; -} /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/group.h b/lib/libalpm/group.h index c92684e3..078c9af7 100644 --- a/lib/libalpm/group.h +++ b/lib/libalpm/group.h @@ -22,15 +22,8 @@ #include "alpm.h" -struct __pmgrp_t { - /** group name */ - char *name; - /** list of pmpkg_t packages */ - alpm_list_t *packages; -}; - -pmgrp_t *_alpm_grp_new(const char *name); -void _alpm_grp_free(pmgrp_t *grp); +alpm_group_t *_alpm_group_new(const char *name); +void _alpm_group_free(alpm_group_t *grp); #endif /* _ALPM_GROUP_H */ diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c index 586aad1e..266b4bc8 100644 --- a/lib/libalpm/handle.c +++ b/lib/libalpm/handle.c @@ -22,14 +22,14 @@ #include "config.h" +#include <errno.h> #include <stdlib.h> #include <string.h> #include <limits.h> #include <sys/types.h> #include <syslog.h> -#include <time.h> #include <sys/stat.h> -#include <errno.h> +#include <fcntl.h> /* libalpm */ #include "handle.h" @@ -39,22 +39,22 @@ #include "trans.h" #include "alpm.h" -/* global var for handle (private to libalpm) */ -pmhandle_t *handle = NULL; - -pmhandle_t *_alpm_handle_new() +alpm_handle_t *_alpm_handle_new() { - pmhandle_t *handle; + alpm_handle_t *handle; - CALLOC(handle, 1, sizeof(pmhandle_t), RET_ERR(PM_ERR_MEMORY, NULL)); + CALLOC(handle, 1, sizeof(alpm_handle_t), return NULL); - return(handle); +#ifdef HAVE_LIBGPGME + handle->siglevel = ALPM_SIG_PACKAGE | ALPM_SIG_PACKAGE_OPTIONAL | + ALPM_SIG_DATABASE | ALPM_SIG_DATABASE_OPTIONAL; +#endif + + return handle; } -void _alpm_handle_free(pmhandle_t *handle) +void _alpm_handle_free(alpm_handle_t *handle) { - ALPM_LOG_FUNC; - if(handle == NULL) { return; } @@ -69,6 +69,11 @@ void _alpm_handle_free(pmhandle_t *handle) closelog(); } +#ifdef HAVE_LIBCURL + /* release curl handle */ + curl_easy_cleanup(handle->curl); +#endif + /* free memory */ _alpm_trans_free(handle->trans); FREE(handle->root); @@ -77,371 +82,326 @@ void _alpm_handle_free(pmhandle_t *handle) FREE(handle->logfile); FREE(handle->lockfile); FREE(handle->arch); + FREE(handle->gpgdir); FREELIST(handle->dbs_sync); FREELIST(handle->noupgrade); FREELIST(handle->noextract); FREELIST(handle->ignorepkg); - FREELIST(handle->ignoregrp); + FREELIST(handle->ignoregroup); FREE(handle); } -alpm_cb_log SYMEXPORT alpm_option_get_logcb() +/** Lock the database */ +int _alpm_handle_lock(alpm_handle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return NULL; + int fd; + char *dir, *ptr; + + ASSERT(handle->lockfile != NULL, return -1); + ASSERT(handle->lckstream == NULL, return 0); + + /* create the dir of the lockfile first */ + dir = strdup(handle->lockfile); + ptr = strrchr(dir, '/'); + if(ptr) { + *ptr = '\0'; } - return handle->logcb; + if(_alpm_makepath(dir)) { + FREE(dir); + return -1; + } + FREE(dir); + + do { + fd = open(handle->lockfile, O_WRONLY | O_CREAT | O_EXCL, 0000); + } while(fd == -1 && errno == EINTR); + if(fd > 0) { + FILE *f = fdopen(fd, "w"); + fprintf(f, "%ld\n", (long)getpid()); + fflush(f); + fsync(fd); + handle->lckstream = f; + return 0; + } + return -1; } -alpm_cb_download SYMEXPORT alpm_option_get_dlcb() +/** Remove a lock file */ +int _alpm_handle_unlock(alpm_handle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return NULL; + ASSERT(handle->lockfile != NULL, return -1); + ASSERT(handle->lckstream != NULL, return 0); + + if(handle->lckstream != NULL) { + fclose(handle->lckstream); + handle->lckstream = NULL; + } + if(unlink(handle->lockfile) && errno != ENOENT) { + return -1; } + return 0; +} + + +alpm_cb_log SYMEXPORT alpm_option_get_logcb(alpm_handle_t *handle) +{ + CHECK_HANDLE(handle, return NULL); + return handle->logcb; +} + +alpm_cb_download SYMEXPORT alpm_option_get_dlcb(alpm_handle_t *handle) +{ + CHECK_HANDLE(handle, return NULL); return handle->dlcb; } -alpm_cb_fetch SYMEXPORT alpm_option_get_fetchcb() +alpm_cb_fetch SYMEXPORT alpm_option_get_fetchcb(alpm_handle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return NULL; - } + CHECK_HANDLE(handle, return NULL); return handle->fetchcb; } -alpm_cb_totaldl SYMEXPORT alpm_option_get_totaldlcb() +alpm_cb_totaldl SYMEXPORT alpm_option_get_totaldlcb(alpm_handle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return NULL; - } + CHECK_HANDLE(handle, return NULL); return handle->totaldlcb; } -const char SYMEXPORT *alpm_option_get_root() +const char SYMEXPORT *alpm_option_get_root(alpm_handle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return NULL; - } + CHECK_HANDLE(handle, return NULL); return handle->root; } -const char SYMEXPORT *alpm_option_get_dbpath() +const char SYMEXPORT *alpm_option_get_dbpath(alpm_handle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return NULL; - } + CHECK_HANDLE(handle, return NULL); return handle->dbpath; } -alpm_list_t SYMEXPORT *alpm_option_get_cachedirs() +alpm_list_t SYMEXPORT *alpm_option_get_cachedirs(alpm_handle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return NULL; - } + CHECK_HANDLE(handle, return NULL); return handle->cachedirs; } -const char SYMEXPORT *alpm_option_get_logfile() +const char SYMEXPORT *alpm_option_get_logfile(alpm_handle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return NULL; - } + CHECK_HANDLE(handle, return NULL); return handle->logfile; } -const char SYMEXPORT *alpm_option_get_lockfile() +const char SYMEXPORT *alpm_option_get_lockfile(alpm_handle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return NULL; - } + CHECK_HANDLE(handle, return NULL); return handle->lockfile; } -int SYMEXPORT alpm_option_get_usesyslog() +const char SYMEXPORT *alpm_option_get_gpgdir(alpm_handle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return -1; - } + CHECK_HANDLE(handle, return NULL); + return handle->gpgdir; +} + +int SYMEXPORT alpm_option_get_usesyslog(alpm_handle_t *handle) +{ + CHECK_HANDLE(handle, return -1); return handle->usesyslog; } -alpm_list_t SYMEXPORT *alpm_option_get_noupgrades() +alpm_list_t SYMEXPORT *alpm_option_get_noupgrades(alpm_handle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return NULL; - } + CHECK_HANDLE(handle, return NULL); return handle->noupgrade; } -alpm_list_t SYMEXPORT *alpm_option_get_noextracts() +alpm_list_t SYMEXPORT *alpm_option_get_noextracts(alpm_handle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return NULL; - } + CHECK_HANDLE(handle, return NULL); return handle->noextract; } -alpm_list_t SYMEXPORT *alpm_option_get_ignorepkgs() +alpm_list_t SYMEXPORT *alpm_option_get_ignorepkgs(alpm_handle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return NULL; - } + CHECK_HANDLE(handle, return NULL); return handle->ignorepkg; } -alpm_list_t SYMEXPORT *alpm_option_get_ignoregrps() +alpm_list_t SYMEXPORT *alpm_option_get_ignoregroups(alpm_handle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return NULL; - } - return handle->ignoregrp; + CHECK_HANDLE(handle, return NULL); + return handle->ignoregroup; } -const char SYMEXPORT *alpm_option_get_arch() +const char SYMEXPORT *alpm_option_get_arch(alpm_handle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return NULL; - } + CHECK_HANDLE(handle, return NULL); return handle->arch; } -int SYMEXPORT alpm_option_get_usedelta() +int SYMEXPORT alpm_option_get_usedelta(alpm_handle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return -1; - } + CHECK_HANDLE(handle, return -1); return handle->usedelta; } -int SYMEXPORT alpm_option_get_checkspace() +int SYMEXPORT alpm_option_get_checkspace(alpm_handle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return -1; - } + CHECK_HANDLE(handle, return -1); return handle->checkspace; } -pmdb_t SYMEXPORT *alpm_option_get_localdb() +alpm_db_t SYMEXPORT *alpm_option_get_localdb(alpm_handle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return NULL; - } + CHECK_HANDLE(handle, return NULL); return handle->db_local; } -alpm_list_t SYMEXPORT *alpm_option_get_syncdbs() +alpm_list_t SYMEXPORT *alpm_option_get_syncdbs(alpm_handle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return NULL; - } + CHECK_HANDLE(handle, return NULL); return handle->dbs_sync; } -void SYMEXPORT alpm_option_set_logcb(alpm_cb_log cb) +int SYMEXPORT alpm_option_set_logcb(alpm_handle_t *handle, alpm_cb_log cb) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return; - } + CHECK_HANDLE(handle, return -1); handle->logcb = cb; + return 0; } -void SYMEXPORT alpm_option_set_dlcb(alpm_cb_download cb) +int SYMEXPORT alpm_option_set_dlcb(alpm_handle_t *handle, alpm_cb_download cb) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return; - } + CHECK_HANDLE(handle, return -1); handle->dlcb = cb; + return 0; } -void SYMEXPORT alpm_option_set_fetchcb(alpm_cb_fetch cb) +int SYMEXPORT alpm_option_set_fetchcb(alpm_handle_t *handle, alpm_cb_fetch cb) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return; - } + CHECK_HANDLE(handle, return -1); handle->fetchcb = cb; + return 0; } -void SYMEXPORT alpm_option_set_totaldlcb(alpm_cb_totaldl cb) +int SYMEXPORT alpm_option_set_totaldlcb(alpm_handle_t *handle, alpm_cb_totaldl cb) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return; - } + CHECK_HANDLE(handle, return -1); handle->totaldlcb = cb; + return 0; } -int SYMEXPORT alpm_option_set_root(const char *root) -{ - struct stat st; - char *realroot; - size_t rootlen; - - ALPM_LOG_FUNC; - - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); +static char *canonicalize_path(const char *path) { + char *new_path; + size_t len; - if(!root) { - pm_errno = PM_ERR_WRONG_ARGS; - return(-1); + /* verify path ends in a '/' */ + len = strlen(path); + if(path[len - 1] != '/') { + len += 1; } - if(stat(root, &st) == -1 || !S_ISDIR(st.st_mode)) { - pm_errno = PM_ERR_NOT_A_DIR; - return(-1); - } - - realroot = calloc(PATH_MAX+1, sizeof(char)); - if(!realpath(root, realroot)) { - FREE(realroot); - pm_errno = PM_ERR_NOT_A_DIR; - return(-1); - } - - /* verify root ends in a '/' */ - rootlen = strlen(realroot); - if(realroot[rootlen-1] != '/') { - rootlen += 1; - } - if(handle->root) { - FREE(handle->root); - } - handle->root = calloc(rootlen + 1, sizeof(char)); - strncpy(handle->root, realroot, rootlen); - handle->root[rootlen-1] = '/'; - FREE(realroot); - _alpm_log(PM_LOG_DEBUG, "option 'root' = %s\n", handle->root); - return(0); + CALLOC(new_path, len + 1, sizeof(char), return NULL); + strcpy(new_path, path); + new_path[len - 1] = '/'; + return new_path; } -int SYMEXPORT alpm_option_set_dbpath(const char *dbpath) -{ +enum _alpm_errno_t _alpm_set_directory_option(const char *value, + char **storage, int must_exist) + { struct stat st; - size_t dbpathlen, lockfilelen; - const char *lf = "db.lck"; - - ALPM_LOG_FUNC; + char *real = NULL; + const char *path; - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); - if(!dbpath) { - pm_errno = PM_ERR_WRONG_ARGS; - return(-1); - } - if(stat(dbpath, &st) == -1 || !S_ISDIR(st.st_mode)) { - pm_errno = PM_ERR_NOT_A_DIR; - return(-1); + path = value; + if(!path) { + return ALPM_ERR_WRONG_ARGS; } - /* verify dbpath ends in a '/' */ - dbpathlen = strlen(dbpath); - if(dbpath[dbpathlen-1] != '/') { - dbpathlen += 1; + if(must_exist) { + if(stat(path, &st) == -1 || !S_ISDIR(st.st_mode)) { + return ALPM_ERR_NOT_A_DIR; + } + CALLOC(real, PATH_MAX, sizeof(char), return ALPM_ERR_MEMORY); + if(!realpath(path, real)) { + free(real); + return ALPM_ERR_NOT_A_DIR; + } + path = real; } - if(handle->dbpath) { - FREE(handle->dbpath); - } - handle->dbpath = calloc(dbpathlen+1, sizeof(char)); - strncpy(handle->dbpath, dbpath, dbpathlen); - handle->dbpath[dbpathlen-1] = '/'; - _alpm_log(PM_LOG_DEBUG, "option 'dbpath' = %s\n", handle->dbpath); - if(handle->lockfile) { - FREE(handle->lockfile); + if(*storage) { + FREE(*storage); + } + *storage = canonicalize_path(path); + if(!*storage) { + return ALPM_ERR_MEMORY; } - lockfilelen = strlen(handle->dbpath) + strlen(lf) + 1; - handle->lockfile = calloc(lockfilelen, sizeof(char)); - snprintf(handle->lockfile, lockfilelen, "%s%s", handle->dbpath, lf); - _alpm_log(PM_LOG_DEBUG, "option 'lockfile' = %s\n", handle->lockfile); - return(0); + free(real); + return 0; } -int SYMEXPORT alpm_option_add_cachedir(const char *cachedir) +int SYMEXPORT alpm_option_add_cachedir(alpm_handle_t *handle, const char *cachedir) { char *newcachedir; - size_t cachedirlen; - ALPM_LOG_FUNC; - - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); - if(!cachedir) { - pm_errno = PM_ERR_WRONG_ARGS; - return(-1); - } + CHECK_HANDLE(handle, return -1); + ASSERT(cachedir != NULL, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1)); /* don't stat the cachedir yet, as it may not even be needed. we can * fail later if it is needed and the path is invalid. */ - /* verify cachedir ends in a '/' */ - cachedirlen = strlen(cachedir); - if(cachedir[cachedirlen-1] != '/') { - cachedirlen += 1; + newcachedir = canonicalize_path(cachedir); + if(!newcachedir) { + RET_ERR(handle, ALPM_ERR_MEMORY, -1); } - newcachedir = calloc(cachedirlen + 1, sizeof(char)); - strncpy(newcachedir, cachedir, cachedirlen); - newcachedir[cachedirlen-1] = '/'; handle->cachedirs = alpm_list_add(handle->cachedirs, newcachedir); - _alpm_log(PM_LOG_DEBUG, "option 'cachedir' = %s\n", newcachedir); - return(0); + _alpm_log(handle, ALPM_LOG_DEBUG, "option 'cachedir' = %s\n", newcachedir); + return 0; } -void SYMEXPORT alpm_option_set_cachedirs(alpm_list_t *cachedirs) +int SYMEXPORT alpm_option_set_cachedirs(alpm_handle_t *handle, alpm_list_t *cachedirs) { - ASSERT(handle != NULL, RET_ERR_VOID(PM_ERR_HANDLE_NULL)); - if(handle->cachedirs) FREELIST(handle->cachedirs); - if(cachedirs) handle->cachedirs = cachedirs; + alpm_list_t *i; + CHECK_HANDLE(handle, return -1); + if(handle->cachedirs) { + FREELIST(handle->cachedirs); + } + for(i = cachedirs; i; i = i->next) { + int ret = alpm_option_add_cachedir(handle, i->data); + if(ret) { + return ret; + } + } + return 0; } -int SYMEXPORT alpm_option_remove_cachedir(const char *cachedir) +int SYMEXPORT alpm_option_remove_cachedir(alpm_handle_t *handle, const char *cachedir) { char *vdata = NULL; char *newcachedir; - size_t cachedirlen; - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); - /* verify cachedir ends in a '/' */ - cachedirlen = strlen(cachedir); - if(cachedir[cachedirlen-1] != '/') { - cachedirlen += 1; + CHECK_HANDLE(handle, return -1); + ASSERT(cachedir != NULL, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1)); + + newcachedir = canonicalize_path(cachedir); + if(!newcachedir) { + RET_ERR(handle, ALPM_ERR_MEMORY, -1); } - newcachedir = calloc(cachedirlen + 1, sizeof(char)); - strncpy(newcachedir, cachedir, cachedirlen); - newcachedir[cachedirlen-1] = '/'; handle->cachedirs = alpm_list_remove_str(handle->cachedirs, newcachedir, &vdata); FREE(newcachedir); if(vdata != NULL) { FREE(vdata); - return(1); + return 1; } - return(0); + return 0; } -int SYMEXPORT alpm_option_set_logfile(const char *logfile) +int SYMEXPORT alpm_option_set_logfile(alpm_handle_t *handle, const char *logfile) { char *oldlogfile = handle->logfile; - ALPM_LOG_FUNC; - - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + CHECK_HANDLE(handle, return -1); if(!logfile) { - pm_errno = PM_ERR_WRONG_ARGS; - return(-1); + handle->pm_errno = ALPM_ERR_WRONG_ARGS; + return -1; } handle->logfile = strdup(logfile); @@ -455,133 +415,186 @@ int SYMEXPORT alpm_option_set_logfile(const char *logfile) fclose(handle->logstream); handle->logstream = NULL; } - _alpm_log(PM_LOG_DEBUG, "option 'logfile' = %s\n", handle->logfile); - return(0); + _alpm_log(handle, ALPM_LOG_DEBUG, "option 'logfile' = %s\n", handle->logfile); + return 0; } -void SYMEXPORT alpm_option_set_usesyslog(int usesyslog) +int SYMEXPORT alpm_option_set_gpgdir(alpm_handle_t *handle, const char *gpgdir) { - ASSERT(handle != NULL, RET_ERR_VOID(PM_ERR_HANDLE_NULL)); + CHECK_HANDLE(handle, return -1); + if(!gpgdir) { + handle->pm_errno = ALPM_ERR_WRONG_ARGS; + return -1; + } + + if(handle->gpgdir) { + FREE(handle->gpgdir); + } + handle->gpgdir = strdup(gpgdir); + + _alpm_log(handle, ALPM_LOG_DEBUG, "option 'gpgdir' = %s\n", handle->gpgdir); + return 0; +} + +int SYMEXPORT alpm_option_set_usesyslog(alpm_handle_t *handle, int usesyslog) +{ + CHECK_HANDLE(handle, return -1); handle->usesyslog = usesyslog; + return 0; } -void SYMEXPORT alpm_option_add_noupgrade(const char *pkg) +int SYMEXPORT alpm_option_add_noupgrade(alpm_handle_t *handle, const char *pkg) { - ASSERT(handle != NULL, RET_ERR_VOID(PM_ERR_HANDLE_NULL)); + CHECK_HANDLE(handle, return -1); handle->noupgrade = alpm_list_add(handle->noupgrade, strdup(pkg)); + return 0; } -void SYMEXPORT alpm_option_set_noupgrades(alpm_list_t *noupgrade) +int SYMEXPORT alpm_option_set_noupgrades(alpm_handle_t *handle, alpm_list_t *noupgrade) { - ASSERT(handle != NULL, RET_ERR_VOID(PM_ERR_HANDLE_NULL)); + CHECK_HANDLE(handle, return -1); if(handle->noupgrade) FREELIST(handle->noupgrade); - if(noupgrade) handle->noupgrade = noupgrade; + handle->noupgrade = alpm_list_strdup(noupgrade); + return 0; } -int SYMEXPORT alpm_option_remove_noupgrade(const char *pkg) +int SYMEXPORT alpm_option_remove_noupgrade(alpm_handle_t *handle, const char *pkg) { char *vdata = NULL; - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + CHECK_HANDLE(handle, return -1); handle->noupgrade = alpm_list_remove_str(handle->noupgrade, pkg, &vdata); if(vdata != NULL) { FREE(vdata); - return(1); + return 1; } - return(0); + return 0; } -void SYMEXPORT alpm_option_add_noextract(const char *pkg) +int SYMEXPORT alpm_option_add_noextract(alpm_handle_t *handle, const char *pkg) { - ASSERT(handle != NULL, RET_ERR_VOID(PM_ERR_HANDLE_NULL)); + CHECK_HANDLE(handle, return -1); handle->noextract = alpm_list_add(handle->noextract, strdup(pkg)); + return 0; } -void SYMEXPORT alpm_option_set_noextracts(alpm_list_t *noextract) +int SYMEXPORT alpm_option_set_noextracts(alpm_handle_t *handle, alpm_list_t *noextract) { - ASSERT(handle != NULL, RET_ERR_VOID(PM_ERR_HANDLE_NULL)); + CHECK_HANDLE(handle, return -1); if(handle->noextract) FREELIST(handle->noextract); - if(noextract) handle->noextract = noextract; + handle->noextract = alpm_list_strdup(noextract); + return 0; } -int SYMEXPORT alpm_option_remove_noextract(const char *pkg) +int SYMEXPORT alpm_option_remove_noextract(alpm_handle_t *handle, const char *pkg) { char *vdata = NULL; - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + CHECK_HANDLE(handle, return -1); handle->noextract = alpm_list_remove_str(handle->noextract, pkg, &vdata); if(vdata != NULL) { FREE(vdata); - return(1); + return 1; } - return(0); + return 0; } -void SYMEXPORT alpm_option_add_ignorepkg(const char *pkg) +int SYMEXPORT alpm_option_add_ignorepkg(alpm_handle_t *handle, const char *pkg) { - ASSERT(handle != NULL, RET_ERR_VOID(PM_ERR_HANDLE_NULL)); + CHECK_HANDLE(handle, return -1); handle->ignorepkg = alpm_list_add(handle->ignorepkg, strdup(pkg)); + return 0; } -void SYMEXPORT alpm_option_set_ignorepkgs(alpm_list_t *ignorepkgs) +int SYMEXPORT alpm_option_set_ignorepkgs(alpm_handle_t *handle, alpm_list_t *ignorepkgs) { - ASSERT(handle != NULL, RET_ERR_VOID(PM_ERR_HANDLE_NULL)); + CHECK_HANDLE(handle, return -1); if(handle->ignorepkg) FREELIST(handle->ignorepkg); - if(ignorepkgs) handle->ignorepkg = ignorepkgs; + handle->ignorepkg = alpm_list_strdup(ignorepkgs); + return 0; } -int SYMEXPORT alpm_option_remove_ignorepkg(const char *pkg) +int SYMEXPORT alpm_option_remove_ignorepkg(alpm_handle_t *handle, const char *pkg) { char *vdata = NULL; - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + CHECK_HANDLE(handle, return -1); handle->ignorepkg = alpm_list_remove_str(handle->ignorepkg, pkg, &vdata); if(vdata != NULL) { FREE(vdata); - return(1); + return 1; } - return(0); + return 0; } -void SYMEXPORT alpm_option_add_ignoregrp(const char *grp) +int SYMEXPORT alpm_option_add_ignoregroup(alpm_handle_t *handle, const char *grp) { - ASSERT(handle != NULL, RET_ERR_VOID(PM_ERR_HANDLE_NULL)); - handle->ignoregrp = alpm_list_add(handle->ignoregrp, strdup(grp)); + CHECK_HANDLE(handle, return -1); + handle->ignoregroup = alpm_list_add(handle->ignoregroup, strdup(grp)); + return 0; } -void SYMEXPORT alpm_option_set_ignoregrps(alpm_list_t *ignoregrps) +int SYMEXPORT alpm_option_set_ignoregroups(alpm_handle_t *handle, alpm_list_t *ignoregrps) { - ASSERT(handle != NULL, RET_ERR_VOID(PM_ERR_HANDLE_NULL)); - if(handle->ignoregrp) FREELIST(handle->ignoregrp); - if(ignoregrps) handle->ignoregrp = ignoregrps; + CHECK_HANDLE(handle, return -1); + if(handle->ignoregroup) FREELIST(handle->ignoregroup); + handle->ignoregroup = alpm_list_strdup(ignoregrps); + return 0; } -int SYMEXPORT alpm_option_remove_ignoregrp(const char *grp) +int SYMEXPORT alpm_option_remove_ignoregroup(alpm_handle_t *handle, const char *grp) { char *vdata = NULL; - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); - handle->ignoregrp = alpm_list_remove_str(handle->ignoregrp, grp, &vdata); + CHECK_HANDLE(handle, return -1); + handle->ignoregroup = alpm_list_remove_str(handle->ignoregroup, grp, &vdata); if(vdata != NULL) { FREE(vdata); - return(1); + return 1; } - return(0); + return 0; } -void SYMEXPORT alpm_option_set_arch(const char *arch) +int SYMEXPORT alpm_option_set_arch(alpm_handle_t *handle, const char *arch) { - ASSERT(handle != NULL, RET_ERR_VOID(PM_ERR_HANDLE_NULL)); + CHECK_HANDLE(handle, return -1); if(handle->arch) FREE(handle->arch); - if(arch) handle->arch = strdup(arch); + if(arch) { + handle->arch = strdup(arch); + } else { + handle->arch = NULL; + } + return 0; } -void SYMEXPORT alpm_option_set_usedelta(int usedelta) +int SYMEXPORT alpm_option_set_usedelta(alpm_handle_t *handle, int usedelta) { - ASSERT(handle != NULL, RET_ERR_VOID(PM_ERR_HANDLE_NULL)); + CHECK_HANDLE(handle, return -1); handle->usedelta = usedelta; + return 0; } -void SYMEXPORT alpm_option_set_checkspace(int checkspace) +int SYMEXPORT alpm_option_set_checkspace(alpm_handle_t *handle, int checkspace) { - ASSERT(handle != NULL, RET_ERR_VOID(PM_ERR_HANDLE_NULL)); + CHECK_HANDLE(handle, return -1); handle->checkspace = checkspace; + return 0; +} + +int SYMEXPORT alpm_option_set_default_siglevel(alpm_handle_t *handle, + alpm_siglevel_t level) +{ + CHECK_HANDLE(handle, return -1); +#ifdef HAVE_LIBGPGME + handle->siglevel = level; +#else + if(level != 0 && level != ALPM_SIG_USE_DEFAULT) { + RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1); + } +#endif + return 0; +} + +alpm_siglevel_t SYMEXPORT alpm_option_get_default_siglevel(alpm_handle_t *handle) +{ + CHECK_HANDLE(handle, return -1); + return handle->siglevel; } /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/handle.h b/lib/libalpm/handle.h index 2d962fe6..9e038581 100644 --- a/lib/libalpm/handle.h +++ b/lib/libalpm/handle.h @@ -24,18 +24,25 @@ #include <sys/types.h> #include "alpm_list.h" -#include "db.h" -#include "log.h" #include "alpm.h" -#include "trans.h" -typedef struct _pmhandle_t { +#ifdef HAVE_LIBCURL +#include <curl/curl.h> +#endif + +struct __alpm_handle_t { /* internal usage */ - pmdb_t *db_local; /* local db pointer */ - alpm_list_t *dbs_sync; /* List of (pmdb_t *) */ + alpm_db_t *db_local; /* local db pointer */ + alpm_list_t *dbs_sync; /* List of (alpm_db_t *) */ FILE *logstream; /* log file stream pointer */ FILE *lckstream; /* lock file stream pointer if one exists */ - pmtrans_t *trans; + alpm_trans_t *trans; + +#ifdef HAVE_LIBCURL + /* libcurl handle */ + CURL *curl; /* reusable curl_easy handle */ + CURLcode curlerr; /* last error produced by curl */ +#endif /* callback functions */ alpm_cb_log logcb; /* Log callback function */ @@ -48,26 +55,34 @@ typedef struct _pmhandle_t { char *dbpath; /* Base path to pacman's DBs */ char *logfile; /* Name of the log file */ char *lockfile; /* Name of the lock file */ + char *gpgdir; /* Directory where GnuPG files are stored */ alpm_list_t *cachedirs; /* Paths to pacman cache directories */ /* package lists */ alpm_list_t *noupgrade; /* List of packages NOT to be upgraded */ alpm_list_t *noextract; /* List of files NOT to extract */ alpm_list_t *ignorepkg; /* List of packages to ignore */ - alpm_list_t *ignoregrp; /* List of groups to ignore */ + alpm_list_t *ignoregroup; /* List of groups to ignore */ /* options */ - int usesyslog; /* Use syslog instead of logfile? */ /* TODO move to frontend */ - char *arch; /* Architecture of packages we should allow */ - int usedelta; /* Download deltas if possible */ - int checkspace; /* Check disk space before installing */ -} pmhandle_t; + int usesyslog; /* Use syslog instead of logfile? */ /* TODO move to frontend */ + char *arch; /* Architecture of packages we should allow */ + int usedelta; /* Download deltas if possible */ + int checkspace; /* Check disk space before installing */ + alpm_siglevel_t siglevel; /* Default signature verification level */ + + /* error code */ + enum _alpm_errno_t pm_errno; +}; + +alpm_handle_t *_alpm_handle_new(void); +void _alpm_handle_free(alpm_handle_t *handle); -/* global handle variable */ -extern pmhandle_t *handle; +int _alpm_handle_lock(alpm_handle_t *handle); +int _alpm_handle_unlock(alpm_handle_t *handle); -pmhandle_t *_alpm_handle_new(void); -void _alpm_handle_free(pmhandle_t *handle); +enum _alpm_errno_t _alpm_set_directory_option(const char *value, + char **storage, int must_exist); #endif /* _ALPM_HANDLE_H */ diff --git a/lib/libalpm/log.c b/lib/libalpm/log.c index 09c6fb84..692ff79c 100644 --- a/lib/libalpm/log.c +++ b/lib/libalpm/log.c @@ -22,10 +22,7 @@ #include <stdio.h> #include <stdarg.h> -#include <sys/types.h> -#include <sys/stat.h> #include <errno.h> -#include <time.h> /* libalpm */ #include "log.h" @@ -39,18 +36,16 @@ */ /** A printf-like function for logging. + * @param handle the context handle * @param fmt output format * @return 0 on success, -1 on error (pm_errno is set accordingly) */ -int SYMEXPORT alpm_logaction(const char *fmt, ...) +int SYMEXPORT alpm_logaction(alpm_handle_t *handle, const char *fmt, ...) { int ret; va_list args; - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + ASSERT(handle != NULL, return -1); /* check if the logstream is open already, opening it if needed */ if(handle->logstream == NULL) { @@ -58,18 +53,18 @@ int SYMEXPORT alpm_logaction(const char *fmt, ...) /* if we couldn't open it, we have an issue */ if(handle->logstream == NULL) { if(errno == EACCES) { - pm_errno = PM_ERR_BADPERMS; + handle->pm_errno = ALPM_ERR_BADPERMS; } else if(errno == ENOENT) { - pm_errno = PM_ERR_NOT_A_DIR; + handle->pm_errno = ALPM_ERR_NOT_A_DIR; } else { - pm_errno = PM_ERR_SYSTEM; + handle->pm_errno = ALPM_ERR_SYSTEM; } - return(-1); + return -1; } } va_start(args, fmt); - ret = _alpm_logaction(handle->usesyslog, handle->logstream, fmt, args); + ret = _alpm_logaction(handle, fmt, args); va_end(args); /* TODO We should add a prefix to log strings depending on who called us. @@ -83,22 +78,21 @@ int SYMEXPORT alpm_logaction(const char *fmt, ...) * kpacman: "KPACMAN" * This would allow us to share the log file between several frontends * and know who does what */ - return(ret); + return ret; } /** @} */ -void _alpm_log(pmloglevel_t flag, const char *fmt, ...) +void _alpm_log(alpm_handle_t *handle, alpm_loglevel_t flag, const char *fmt, ...) { va_list args; - alpm_cb_log logcb = alpm_option_get_logcb(); - if(logcb == NULL) { + if(handle == NULL || handle->logcb == NULL) { return; } va_start(args, fmt); - logcb(flag, fmt, args); + handle->logcb(flag, fmt, args); va_end(args); } diff --git a/lib/libalpm/log.h b/lib/libalpm/log.h index 9a2961fb..a43290d8 100644 --- a/lib/libalpm/log.h +++ b/lib/libalpm/log.h @@ -22,14 +22,8 @@ #include "alpm.h" -#ifdef PACMAN_DEBUG -/* Log funtion entry points if debugging is enabled */ -#define ALPM_LOG_FUNC _alpm_log(PM_LOG_FUNCTION, "Enter %s\n", __func__) -#else -#define ALPM_LOG_FUNC -#endif - -void _alpm_log(pmloglevel_t flag, const char *fmt, ...) __attribute__((format(printf,2,3))); +void _alpm_log(alpm_handle_t *handle, alpm_loglevel_t flag, + const char *fmt, ...) __attribute__((format(printf,3,4))); #endif /* _ALPM_LOG_H */ diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c index f2f15af4..fd3d0c65 100644 --- a/lib/libalpm/package.c +++ b/lib/libalpm/package.c @@ -23,13 +23,9 @@ #include "config.h" -#include <stdio.h> #include <stdlib.h> #include <string.h> -#include <ctype.h> -#include <errno.h> #include <sys/types.h> -#include <sys/stat.h> /* libalpm */ #include "package.h" @@ -47,87 +43,96 @@ */ /** Free a package. */ -int SYMEXPORT alpm_pkg_free(pmpkg_t *pkg) +int SYMEXPORT alpm_pkg_free(alpm_pkg_t *pkg) { - ALPM_LOG_FUNC; - - ASSERT(pkg != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); + ASSERT(pkg != NULL, return -1); /* Only free packages loaded in user space */ if(pkg->origin == PKG_FROM_FILE) { _alpm_pkg_free(pkg); } - return(0); + return 0; } /** Check the integrity (with md5) of a package from the sync cache. */ -int SYMEXPORT alpm_pkg_checkmd5sum(pmpkg_t *pkg) +int SYMEXPORT alpm_pkg_checkmd5sum(alpm_pkg_t *pkg) { char *fpath; int retval; - ALPM_LOG_FUNC; - - ASSERT(pkg != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); + ASSERT(pkg != NULL, return -1); + pkg->handle->pm_errno = 0; /* We only inspect packages from sync repositories */ - ASSERT(pkg->origin == PKG_FROM_SYNCDB, RET_ERR(PM_ERR_PKG_INVALID, -1)); + ASSERT(pkg->origin == PKG_FROM_SYNCDB, + RET_ERR(pkg->handle, ALPM_ERR_WRONG_ARGS, -1)); - fpath = _alpm_filecache_find(alpm_pkg_get_filename(pkg)); + fpath = _alpm_filecache_find(pkg->handle, alpm_pkg_get_filename(pkg)); retval = _alpm_test_md5sum(fpath, alpm_pkg_get_md5sum(pkg)); if(retval == 0) { - return(0); - } else if (retval == 1) { - pm_errno = PM_ERR_PKG_INVALID; + return 0; + } else if(retval == 1) { + pkg->handle->pm_errno = ALPM_ERR_PKG_INVALID; retval = -1; } - return(retval); + return retval; } /* Default package accessor functions. These will get overridden by any * backend logic that needs lazy access, such as the local database through * a lazy-load cache. However, the defaults will work just fine for fully- * populated package structures. */ -static const char *_pkg_get_filename(pmpkg_t *pkg) { return pkg->filename; } -static const char *_pkg_get_name(pmpkg_t *pkg) { return pkg->name; } -static const char *_pkg_get_version(pmpkg_t *pkg) { return pkg->version; } -static const char *_pkg_get_desc(pmpkg_t *pkg) { return pkg->desc; } -static const char *_pkg_get_url(pmpkg_t *pkg) { return pkg->url; } -static time_t _pkg_get_builddate(pmpkg_t *pkg) { return pkg->builddate; } -static time_t _pkg_get_installdate(pmpkg_t *pkg) { return pkg->installdate; } -static const char *_pkg_get_packager(pmpkg_t *pkg) { return pkg->packager; } -static const char *_pkg_get_md5sum(pmpkg_t *pkg) { return pkg->md5sum; } -static const char *_pkg_get_arch(pmpkg_t *pkg) { return pkg->arch; } -static off_t _pkg_get_size(pmpkg_t *pkg) { return pkg->size; } -static off_t _pkg_get_isize(pmpkg_t *pkg) { return pkg->isize; } -static pmpkgreason_t _pkg_get_reason(pmpkg_t *pkg) { return pkg->reason; } -static int _pkg_has_scriptlet(pmpkg_t *pkg) { return pkg->scriptlet; } - -static alpm_list_t *_pkg_get_licenses(pmpkg_t *pkg) { return pkg->licenses; } -static alpm_list_t *_pkg_get_groups(pmpkg_t *pkg) { return pkg->groups; } -static alpm_list_t *_pkg_get_depends(pmpkg_t *pkg) { return pkg->depends; } -static alpm_list_t *_pkg_get_optdepends(pmpkg_t *pkg) { return pkg->optdepends; } -static alpm_list_t *_pkg_get_conflicts(pmpkg_t *pkg) { return pkg->conflicts; } -static alpm_list_t *_pkg_get_provides(pmpkg_t *pkg) { return pkg->provides; } -static alpm_list_t *_pkg_get_replaces(pmpkg_t *pkg) { return pkg->replaces; } -static alpm_list_t *_pkg_get_deltas(pmpkg_t *pkg) { return pkg->deltas; } -static alpm_list_t *_pkg_get_files(pmpkg_t *pkg) { return pkg->files; } -static alpm_list_t *_pkg_get_backup(pmpkg_t *pkg) { return pkg->backup; } - -static void *_pkg_changelog_open(pmpkg_t *pkg) { return NULL; } -static size_t _pkg_changelog_read(void *ptr, size_t size, const pmpkg_t *pkg, const void *fp) { return 0; } -static int _pkg_changelog_close(const pmpkg_t *pkg, void *fp) { return EOF; } +static const char *_pkg_get_filename(alpm_pkg_t *pkg) { return pkg->filename; } +static const char *_pkg_get_desc(alpm_pkg_t *pkg) { return pkg->desc; } +static const char *_pkg_get_url(alpm_pkg_t *pkg) { return pkg->url; } +static time_t _pkg_get_builddate(alpm_pkg_t *pkg) { return pkg->builddate; } +static time_t _pkg_get_installdate(alpm_pkg_t *pkg) { return pkg->installdate; } +static const char *_pkg_get_packager(alpm_pkg_t *pkg) { return pkg->packager; } +static const char *_pkg_get_md5sum(alpm_pkg_t *pkg) { return pkg->md5sum; } +static const char *_pkg_get_arch(alpm_pkg_t *pkg) { return pkg->arch; } +static off_t _pkg_get_size(alpm_pkg_t *pkg) { return pkg->size; } +static off_t _pkg_get_isize(alpm_pkg_t *pkg) { return pkg->isize; } +static alpm_pkgreason_t _pkg_get_reason(alpm_pkg_t *pkg) { return pkg->reason; } +static int _pkg_has_scriptlet(alpm_pkg_t *pkg) { return pkg->scriptlet; } + +static alpm_list_t *_pkg_get_licenses(alpm_pkg_t *pkg) { return pkg->licenses; } +static alpm_list_t *_pkg_get_groups(alpm_pkg_t *pkg) { return pkg->groups; } +static alpm_list_t *_pkg_get_depends(alpm_pkg_t *pkg) { return pkg->depends; } +static alpm_list_t *_pkg_get_optdepends(alpm_pkg_t *pkg) { return pkg->optdepends; } +static alpm_list_t *_pkg_get_conflicts(alpm_pkg_t *pkg) { return pkg->conflicts; } +static alpm_list_t *_pkg_get_provides(alpm_pkg_t *pkg) { return pkg->provides; } +static alpm_list_t *_pkg_get_replaces(alpm_pkg_t *pkg) { return pkg->replaces; } +static alpm_list_t *_pkg_get_deltas(alpm_pkg_t *pkg) { return pkg->deltas; } +static alpm_filelist_t *_pkg_get_files(alpm_pkg_t *pkg) { return &(pkg->files); } +static alpm_list_t *_pkg_get_backup(alpm_pkg_t *pkg) { return pkg->backup; } + +static void *_pkg_changelog_open(alpm_pkg_t UNUSED *pkg) +{ + return NULL; +} + +static size_t _pkg_changelog_read(void UNUSED *ptr, size_t UNUSED size, + const alpm_pkg_t UNUSED *pkg, const UNUSED void *fp) +{ + return 0; +} + +static int _pkg_changelog_close(const alpm_pkg_t UNUSED *pkg, + void UNUSED *fp) +{ + return EOF; +} + +static int _pkg_force_load(alpm_pkg_t UNUSED *pkg) { return 0; } /** The standard package operations struct. Get fields directly from the * struct itself with no abstraction layer or any type of lazy loading. */ struct pkg_operations default_pkg_ops = { .get_filename = _pkg_get_filename, - .get_name = _pkg_get_name, - .get_version = _pkg_get_version, .get_desc = _pkg_get_desc, .get_url = _pkg_get_url, .get_builddate = _pkg_get_builddate, @@ -154,174 +159,233 @@ struct pkg_operations default_pkg_ops = { .changelog_open = _pkg_changelog_open, .changelog_read = _pkg_changelog_read, .changelog_close = _pkg_changelog_close, + + .force_load = _pkg_force_load, }; /* Public functions for getting package information. These functions * delegate the hard work to the function callbacks attached to each * package, which depend on where the package was loaded from. */ -const char SYMEXPORT *alpm_pkg_get_filename(pmpkg_t *pkg) +const char SYMEXPORT *alpm_pkg_get_filename(alpm_pkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->get_filename(pkg); } -const char SYMEXPORT *alpm_pkg_get_name(pmpkg_t *pkg) +const char SYMEXPORT *alpm_pkg_get_name(alpm_pkg_t *pkg) { - return pkg->ops->get_name(pkg); + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; + return pkg->name; } -const char SYMEXPORT *alpm_pkg_get_version(pmpkg_t *pkg) +const char SYMEXPORT *alpm_pkg_get_version(alpm_pkg_t *pkg) { - return pkg->ops->get_version(pkg); + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; + return pkg->version; } -const char SYMEXPORT *alpm_pkg_get_desc(pmpkg_t *pkg) +const char SYMEXPORT *alpm_pkg_get_desc(alpm_pkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->get_desc(pkg); } -const char SYMEXPORT *alpm_pkg_get_url(pmpkg_t *pkg) +const char SYMEXPORT *alpm_pkg_get_url(alpm_pkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->get_url(pkg); } -time_t SYMEXPORT alpm_pkg_get_builddate(pmpkg_t *pkg) +time_t SYMEXPORT alpm_pkg_get_builddate(alpm_pkg_t *pkg) { + ASSERT(pkg != NULL, return -1); + pkg->handle->pm_errno = 0; return pkg->ops->get_builddate(pkg); } -time_t SYMEXPORT alpm_pkg_get_installdate(pmpkg_t *pkg) +time_t SYMEXPORT alpm_pkg_get_installdate(alpm_pkg_t *pkg) { + ASSERT(pkg != NULL, return -1); + pkg->handle->pm_errno = 0; return pkg->ops->get_installdate(pkg); } -const char SYMEXPORT *alpm_pkg_get_packager(pmpkg_t *pkg) +const char SYMEXPORT *alpm_pkg_get_packager(alpm_pkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->get_packager(pkg); } -const char SYMEXPORT *alpm_pkg_get_md5sum(pmpkg_t *pkg) +const char SYMEXPORT *alpm_pkg_get_md5sum(alpm_pkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->get_md5sum(pkg); } -const char SYMEXPORT *alpm_pkg_get_arch(pmpkg_t *pkg) +const char SYMEXPORT *alpm_pkg_get_arch(alpm_pkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->get_arch(pkg); } -off_t SYMEXPORT alpm_pkg_get_size(pmpkg_t *pkg) +off_t SYMEXPORT alpm_pkg_get_size(alpm_pkg_t *pkg) { + ASSERT(pkg != NULL, return -1); + pkg->handle->pm_errno = 0; return pkg->ops->get_size(pkg); } -off_t SYMEXPORT alpm_pkg_get_isize(pmpkg_t *pkg) +off_t SYMEXPORT alpm_pkg_get_isize(alpm_pkg_t *pkg) { + ASSERT(pkg != NULL, return -1); + pkg->handle->pm_errno = 0; return pkg->ops->get_isize(pkg); } -pmpkgreason_t SYMEXPORT alpm_pkg_get_reason(pmpkg_t *pkg) +alpm_pkgreason_t SYMEXPORT alpm_pkg_get_reason(alpm_pkg_t *pkg) { + ASSERT(pkg != NULL, return -1); + pkg->handle->pm_errno = 0; return pkg->ops->get_reason(pkg); } -alpm_list_t SYMEXPORT *alpm_pkg_get_licenses(pmpkg_t *pkg) +alpm_list_t SYMEXPORT *alpm_pkg_get_licenses(alpm_pkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->get_licenses(pkg); } -alpm_list_t SYMEXPORT *alpm_pkg_get_groups(pmpkg_t *pkg) +alpm_list_t SYMEXPORT *alpm_pkg_get_groups(alpm_pkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->get_groups(pkg); } -alpm_list_t SYMEXPORT *alpm_pkg_get_depends(pmpkg_t *pkg) +alpm_list_t SYMEXPORT *alpm_pkg_get_depends(alpm_pkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->get_depends(pkg); } -alpm_list_t SYMEXPORT *alpm_pkg_get_optdepends(pmpkg_t *pkg) +alpm_list_t SYMEXPORT *alpm_pkg_get_optdepends(alpm_pkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->get_optdepends(pkg); } -alpm_list_t SYMEXPORT *alpm_pkg_get_conflicts(pmpkg_t *pkg) +alpm_list_t SYMEXPORT *alpm_pkg_get_conflicts(alpm_pkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->get_conflicts(pkg); } -alpm_list_t SYMEXPORT *alpm_pkg_get_provides(pmpkg_t *pkg) +alpm_list_t SYMEXPORT *alpm_pkg_get_provides(alpm_pkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->get_provides(pkg); } -alpm_list_t SYMEXPORT *alpm_pkg_get_replaces(pmpkg_t *pkg) +alpm_list_t SYMEXPORT *alpm_pkg_get_replaces(alpm_pkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->get_replaces(pkg); } -alpm_list_t SYMEXPORT *alpm_pkg_get_deltas(pmpkg_t *pkg) +alpm_list_t SYMEXPORT *alpm_pkg_get_deltas(alpm_pkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->get_deltas(pkg); } -alpm_list_t SYMEXPORT *alpm_pkg_get_files(pmpkg_t *pkg) +alpm_filelist_t SYMEXPORT *alpm_pkg_get_files(alpm_pkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->get_files(pkg); } -alpm_list_t SYMEXPORT *alpm_pkg_get_backup(pmpkg_t *pkg) +alpm_list_t SYMEXPORT *alpm_pkg_get_backup(alpm_pkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->get_backup(pkg); } -pmdb_t SYMEXPORT *alpm_pkg_get_db(pmpkg_t *pkg) +alpm_db_t SYMEXPORT *alpm_pkg_get_db(alpm_pkg_t *pkg) { /* Sanity checks */ - ASSERT(pkg != NULL, return(NULL)); - ASSERT(pkg->origin != PKG_FROM_FILE, return(NULL)); + ASSERT(pkg != NULL, return NULL); + ASSERT(pkg->origin != PKG_FROM_FILE, return NULL); + pkg->handle->pm_errno = 0; - return(pkg->origin_data.db); + return pkg->origin_data.db; } /** Open a package changelog for reading. */ -void SYMEXPORT *alpm_pkg_changelog_open(pmpkg_t *pkg) +void SYMEXPORT *alpm_pkg_changelog_open(alpm_pkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->changelog_open(pkg); } /** Read data from an open changelog 'file stream'. */ size_t SYMEXPORT alpm_pkg_changelog_read(void *ptr, size_t size, - const pmpkg_t *pkg, const void *fp) + const alpm_pkg_t *pkg, const void *fp) { + ASSERT(pkg != NULL, return 0); + pkg->handle->pm_errno = 0; return pkg->ops->changelog_read(ptr, size, pkg, fp); } /* -int SYMEXPORT alpm_pkg_changelog_feof(const pmpkg_t *pkg, void *fp) +int SYMEXPORT alpm_pkg_changelog_feof(const alpm_pkg_t *pkg, void *fp) { return pkg->ops->changelog_feof(pkg, fp); } */ /** Close a package changelog for reading. */ -int SYMEXPORT alpm_pkg_changelog_close(const pmpkg_t *pkg, void *fp) +int SYMEXPORT alpm_pkg_changelog_close(const alpm_pkg_t *pkg, void *fp) { + ASSERT(pkg != NULL, return -1); + pkg->handle->pm_errno = 0; return pkg->ops->changelog_close(pkg, fp); } -int SYMEXPORT alpm_pkg_has_scriptlet(pmpkg_t *pkg) +int SYMEXPORT alpm_pkg_has_scriptlet(alpm_pkg_t *pkg) { + ASSERT(pkg != NULL, return -1); + pkg->handle->pm_errno = 0; return pkg->ops->has_scriptlet(pkg); } -static void find_requiredby(pmpkg_t *pkg, pmdb_t *db, alpm_list_t **reqs) +static void find_requiredby(alpm_pkg_t *pkg, alpm_db_t *db, alpm_list_t **reqs) { const alpm_list_t *i; + pkg->handle->pm_errno = 0; + for(i = _alpm_db_get_pkgcache(db); i; i = i->next) { - pmpkg_t *cachepkg = i->data; - alpm_list_t *i; - for(i = alpm_pkg_get_depends(cachepkg); i; i = i->next) { - if(_alpm_depcmp(pkg, i->data)) { + alpm_pkg_t *cachepkg = i->data; + alpm_list_t *j; + for(j = alpm_pkg_get_depends(cachepkg); j; j = j->next) { + if(_alpm_depcmp(pkg, j->data)) { const char *cachepkgname = cachepkg->name; if(alpm_list_find_str(*reqs, cachepkgname) == NULL) { *reqs = alpm_list_add(*reqs, strdup(cachepkgname)); @@ -332,16 +396,18 @@ static void find_requiredby(pmpkg_t *pkg, pmdb_t *db, alpm_list_t **reqs) } /** Compute the packages requiring a given package. */ -alpm_list_t SYMEXPORT *alpm_pkg_compute_requiredby(pmpkg_t *pkg) +alpm_list_t SYMEXPORT *alpm_pkg_compute_requiredby(alpm_pkg_t *pkg) { const alpm_list_t *i; alpm_list_t *reqs = NULL; - pmdb_t *db; + alpm_db_t *db; + + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; if(pkg->origin == PKG_FROM_FILE) { /* The sane option; search locally for things that require this. */ - db = alpm_option_get_localdb(); - find_requiredby(pkg, db, &reqs); + find_requiredby(pkg, pkg->handle->db_local, &reqs); } else { /* We have a DB package. if it is a local package, then we should * only search the local DB; else search all known sync databases. */ @@ -349,49 +415,68 @@ alpm_list_t SYMEXPORT *alpm_pkg_compute_requiredby(pmpkg_t *pkg) if(db->is_local) { find_requiredby(pkg, db, &reqs); } else { - for(i = handle->dbs_sync; i; i = i->next) { + for(i = pkg->handle->dbs_sync; i; i = i->next) { db = i->data; find_requiredby(pkg, db, &reqs); } reqs = alpm_list_msort(reqs, alpm_list_count(reqs), _alpm_str_cmp); } } - return(reqs); + return reqs; } /** @} */ -pmpkg_t *_alpm_pkg_new(void) +alpm_file_t *_alpm_file_copy(alpm_file_t *dest, + const alpm_file_t *src) +{ + STRDUP(dest->name, src->name, return NULL); + dest->size = src->size; + dest->mode = src->mode; + + return dest; +} + +/* Helper function for comparing files list entries + */ +int _alpm_files_cmp(const void *f1, const void *f2) { - pmpkg_t* pkg; + const alpm_file_t *file1 = f1; + const alpm_file_t *file2 = f2; + return strcmp(file1->name, file2->name); +} - ALPM_LOG_FUNC; +alpm_pkg_t *_alpm_pkg_new(void) +{ + alpm_pkg_t* pkg; - CALLOC(pkg, 1, sizeof(pmpkg_t), RET_ERR(PM_ERR_MEMORY, NULL)); + CALLOC(pkg, 1, sizeof(alpm_pkg_t), return NULL); - return(pkg); + return pkg; } -pmpkg_t *_alpm_pkg_dup(pmpkg_t *pkg) +alpm_pkg_t *_alpm_pkg_dup(alpm_pkg_t *pkg) { - pmpkg_t *newpkg; + alpm_pkg_t *newpkg; alpm_list_t *i; - ALPM_LOG_FUNC; + if(pkg->ops->force_load(pkg)) { + return NULL; + } - CALLOC(newpkg, 1, sizeof(pmpkg_t), RET_ERR(PM_ERR_MEMORY, NULL)); + CALLOC(newpkg, 1, sizeof(alpm_pkg_t), goto cleanup); newpkg->name_hash = pkg->name_hash; - STRDUP(newpkg->filename, pkg->filename, RET_ERR(PM_ERR_MEMORY, newpkg)); - STRDUP(newpkg->name, pkg->name, RET_ERR(PM_ERR_MEMORY, newpkg)); - STRDUP(newpkg->version, pkg->version, RET_ERR(PM_ERR_MEMORY, newpkg)); - STRDUP(newpkg->desc, pkg->desc, RET_ERR(PM_ERR_MEMORY, newpkg)); - STRDUP(newpkg->url, pkg->url, RET_ERR(PM_ERR_MEMORY, newpkg)); + STRDUP(newpkg->filename, pkg->filename, goto cleanup); + STRDUP(newpkg->name, pkg->name, goto cleanup); + STRDUP(newpkg->version, pkg->version, goto cleanup); + STRDUP(newpkg->desc, pkg->desc, goto cleanup); + STRDUP(newpkg->url, pkg->url, goto cleanup); newpkg->builddate = pkg->builddate; newpkg->installdate = pkg->installdate; - STRDUP(newpkg->packager, pkg->packager, RET_ERR(PM_ERR_MEMORY, newpkg)); - STRDUP(newpkg->md5sum, pkg->md5sum, RET_ERR(PM_ERR_MEMORY, newpkg)); - STRDUP(newpkg->arch, pkg->arch, RET_ERR(PM_ERR_MEMORY, newpkg)); + STRDUP(newpkg->packager, pkg->packager, goto cleanup); + STRDUP(newpkg->md5sum, pkg->md5sum, goto cleanup); + STRDUP(newpkg->arch, pkg->arch, goto cleanup); newpkg->size = pkg->size; newpkg->isize = pkg->isize; newpkg->scriptlet = pkg->scriptlet; @@ -400,33 +485,51 @@ pmpkg_t *_alpm_pkg_dup(pmpkg_t *pkg) newpkg->licenses = alpm_list_strdup(pkg->licenses); newpkg->replaces = alpm_list_strdup(pkg->replaces); newpkg->groups = alpm_list_strdup(pkg->groups); - newpkg->files = alpm_list_strdup(pkg->files); - newpkg->backup = alpm_list_strdup(pkg->backup); + if(pkg->files.count) { + size_t filenum; + size_t len = sizeof(alpm_file_t) * pkg->files.count; + MALLOC(newpkg->files.files, len, goto cleanup); + for(filenum = 0; filenum < pkg->files.count; filenum++) { + if(!_alpm_file_copy(newpkg->files.files + filenum, + pkg->files.files + filenum)) { + goto cleanup; + } + } + newpkg->files.count = pkg->files.count; + } + for(i = pkg->backup; i; i = alpm_list_next(i)) { + newpkg->backup = alpm_list_add(newpkg->backup, _alpm_backup_dup(i->data)); + } for(i = pkg->depends; i; i = alpm_list_next(i)) { newpkg->depends = alpm_list_add(newpkg->depends, _alpm_dep_dup(i->data)); } newpkg->optdepends = alpm_list_strdup(pkg->optdepends); newpkg->conflicts = alpm_list_strdup(pkg->conflicts); newpkg->provides = alpm_list_strdup(pkg->provides); - newpkg->deltas = alpm_list_copy_data(pkg->deltas, sizeof(pmdelta_t)); + for(i = pkg->deltas; i; i = alpm_list_next(i)) { + newpkg->deltas = alpm_list_add(newpkg->deltas, _alpm_delta_dup(i->data)); + } /* internal */ + newpkg->infolevel = pkg->infolevel; newpkg->origin = pkg->origin; - newpkg->ops = pkg->ops; if(newpkg->origin == PKG_FROM_FILE) { newpkg->origin_data.file = strdup(pkg->origin_data.file); } else { newpkg->origin_data.db = pkg->origin_data.db; } - newpkg->infolevel = pkg->infolevel; + newpkg->ops = pkg->ops; + newpkg->handle = pkg->handle; - return(newpkg); + return newpkg; + +cleanup: + _alpm_pkg_free(newpkg); + return NULL; } -void _alpm_pkg_free(pmpkg_t *pkg) +void _alpm_pkg_free(alpm_pkg_t *pkg) { - ALPM_LOG_FUNC; - if(pkg == NULL) { return; } @@ -438,12 +541,20 @@ void _alpm_pkg_free(pmpkg_t *pkg) FREE(pkg->url); FREE(pkg->packager); FREE(pkg->md5sum); + FREE(pkg->base64_sig); FREE(pkg->arch); FREELIST(pkg->licenses); FREELIST(pkg->replaces); FREELIST(pkg->groups); - FREELIST(pkg->files); - FREELIST(pkg->backup); + if(pkg->files.count) { + size_t i; + for(i = 0; i < pkg->files.count; i++) { + free(pkg->files.files[i].name); + } + free(pkg->files.files); + } + alpm_list_free_inner(pkg->backup, (alpm_list_fn_free)_alpm_backup_free); + alpm_list_free(pkg->backup); alpm_list_free_inner(pkg->depends, (alpm_list_fn_free)_alpm_dep_free); alpm_list_free(pkg->depends); FREELIST(pkg->optdepends); @@ -465,10 +576,8 @@ void _alpm_pkg_free(pmpkg_t *pkg) * Case 2: If pkg is a pkgcache entry (PKG_FROM_CACHE), it won't be freed, * only the transaction specific fields of pkg will be freed. */ -void _alpm_pkg_free_trans(pmpkg_t *pkg) +void _alpm_pkg_free_trans(alpm_pkg_t *pkg) { - ALPM_LOG_FUNC; - if(pkg == NULL) { return; } @@ -483,10 +592,8 @@ void _alpm_pkg_free_trans(pmpkg_t *pkg) } /* Is spkg an upgrade for localpkg? */ -int _alpm_pkg_compare_versions(pmpkg_t *spkg, pmpkg_t *localpkg) +int _alpm_pkg_compare_versions(alpm_pkg_t *spkg, alpm_pkg_t *localpkg) { - ALPM_LOG_FUNC; - return alpm_pkg_vercmp(alpm_pkg_get_version(spkg), alpm_pkg_get_version(localpkg)); } @@ -495,29 +602,27 @@ int _alpm_pkg_compare_versions(pmpkg_t *spkg, pmpkg_t *localpkg) */ int _alpm_pkg_cmp(const void *p1, const void *p2) { - pmpkg_t *pkg1 = (pmpkg_t *)p1; - pmpkg_t *pkg2 = (pmpkg_t *)p2; - return(strcoll(pkg1->name, pkg2->name)); + const alpm_pkg_t *pkg1 = p1; + const alpm_pkg_t *pkg2 = p2; + return strcoll(pkg1->name, pkg2->name); } /* Test for existence of a package in a alpm_list_t* - * of pmpkg_t* + * of alpm_pkg_t* */ -pmpkg_t *_alpm_pkg_find(alpm_list_t *haystack, const char *needle) +alpm_pkg_t *_alpm_pkg_find(alpm_list_t *haystack, const char *needle) { alpm_list_t *lp; unsigned long needle_hash; - ALPM_LOG_FUNC; - if(needle == NULL || haystack == NULL) { - return(NULL); + return NULL; } needle_hash = _alpm_hash_sdbm(needle); for(lp = haystack; lp; lp = lp->next) { - pmpkg_t *info = lp->data; + alpm_pkg_t *info = lp->data; if(info) { /* a zero hash will cause a fall-through just in case */ @@ -527,40 +632,41 @@ pmpkg_t *_alpm_pkg_find(alpm_list_t *haystack, const char *needle) /* finally: we had hash match, verify string match */ if(strcmp(info->name, needle) == 0) { - return(info); + return info; } } } - return(NULL); + return NULL; } /** Test if a package should be ignored. * * Checks if the package is ignored via IgnorePkg, or if the package is - * in a group ignored via IgnoreGrp. + * in a group ignored via IgnoreGroup. * + * @param handle the context handle * @param pkg the package to test * * @return 1 if the package should be ignored, 0 otherwise */ -int _alpm_pkg_should_ignore(pmpkg_t *pkg) +int _alpm_pkg_should_ignore(alpm_handle_t *handle, alpm_pkg_t *pkg) { alpm_list_t *groups = NULL; /* first see if the package is ignored */ if(alpm_list_find_str(handle->ignorepkg, alpm_pkg_get_name(pkg))) { - return(1); + return 1; } /* next see if the package is in a group that is ignored */ - for(groups = handle->ignoregrp; groups; groups = alpm_list_next(groups)) { + for(groups = handle->ignoregroup; groups; groups = alpm_list_next(groups)) { char *grp = (char *)alpm_list_getdata(groups); if(alpm_list_find_str(alpm_pkg_get_groups(pkg), grp)) { - return(1); + return 1; } } - return(0); + return 0; } /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/package.h b/lib/libalpm/package.h index b161d5f1..d19d8332 100644 --- a/lib/libalpm/package.h +++ b/lib/libalpm/package.h @@ -24,17 +24,21 @@ #ifndef _ALPM_PACKAGE_H #define _ALPM_PACKAGE_H +#include "config.h" /* ensure off_t is correct length */ + #include <sys/types.h> /* off_t */ #include <time.h> /* time_t */ #include "alpm.h" +#include "backup.h" #include "db.h" +#include "signing.h" -typedef enum _pmpkgfrom_t { +typedef enum _alpm_pkgfrom_t { PKG_FROM_FILE = 1, PKG_FROM_LOCALDB, PKG_FROM_SYNCDB -} pmpkgfrom_t; +} alpm_pkgfrom_t; /** Package operations struct. This struct contains function pointers to * all methods used to access data in a package to allow for things such @@ -44,35 +48,35 @@ typedef enum _pmpkgfrom_t { * defined default_pkg_ops struct to work just fine for their needs. */ struct pkg_operations { - const char *(*get_filename) (pmpkg_t *); - const char *(*get_name) (pmpkg_t *); - const char *(*get_version) (pmpkg_t *); - const char *(*get_desc) (pmpkg_t *); - const char *(*get_url) (pmpkg_t *); - time_t (*get_builddate) (pmpkg_t *); - time_t (*get_installdate) (pmpkg_t *); - const char *(*get_packager) (pmpkg_t *); - const char *(*get_md5sum) (pmpkg_t *); - const char *(*get_arch) (pmpkg_t *); - off_t (*get_size) (pmpkg_t *); - off_t (*get_isize) (pmpkg_t *); - pmpkgreason_t (*get_reason) (pmpkg_t *); - int (*has_scriptlet) (pmpkg_t *); - - alpm_list_t *(*get_licenses) (pmpkg_t *); - alpm_list_t *(*get_groups) (pmpkg_t *); - alpm_list_t *(*get_depends) (pmpkg_t *); - alpm_list_t *(*get_optdepends) (pmpkg_t *); - alpm_list_t *(*get_conflicts) (pmpkg_t *); - alpm_list_t *(*get_provides) (pmpkg_t *); - alpm_list_t *(*get_replaces) (pmpkg_t *); - alpm_list_t *(*get_deltas) (pmpkg_t *); - alpm_list_t *(*get_files) (pmpkg_t *); - alpm_list_t *(*get_backup) (pmpkg_t *); - - void *(*changelog_open) (pmpkg_t *); - size_t (*changelog_read) (void *, size_t, const pmpkg_t *, const void *); - int (*changelog_close) (const pmpkg_t *, void *); + const char *(*get_filename) (alpm_pkg_t *); + const char *(*get_desc) (alpm_pkg_t *); + const char *(*get_url) (alpm_pkg_t *); + time_t (*get_builddate) (alpm_pkg_t *); + time_t (*get_installdate) (alpm_pkg_t *); + const char *(*get_packager) (alpm_pkg_t *); + const char *(*get_md5sum) (alpm_pkg_t *); + const char *(*get_arch) (alpm_pkg_t *); + off_t (*get_size) (alpm_pkg_t *); + off_t (*get_isize) (alpm_pkg_t *); + alpm_pkgreason_t (*get_reason) (alpm_pkg_t *); + int (*has_scriptlet) (alpm_pkg_t *); + + alpm_list_t *(*get_licenses) (alpm_pkg_t *); + alpm_list_t *(*get_groups) (alpm_pkg_t *); + alpm_list_t *(*get_depends) (alpm_pkg_t *); + alpm_list_t *(*get_optdepends) (alpm_pkg_t *); + alpm_list_t *(*get_conflicts) (alpm_pkg_t *); + alpm_list_t *(*get_provides) (alpm_pkg_t *); + alpm_list_t *(*get_replaces) (alpm_pkg_t *); + alpm_list_t *(*get_deltas) (alpm_pkg_t *); + alpm_filelist_t *(*get_files) (alpm_pkg_t *); + alpm_list_t *(*get_backup) (alpm_pkg_t *); + + void *(*changelog_open) (alpm_pkg_t *); + size_t (*changelog_read) (void *, size_t, const alpm_pkg_t *, const void *); + int (*changelog_close) (const alpm_pkg_t *, void *); + + int (*force_load) (alpm_pkg_t *); /* still to add: * checkmd5sum() ? @@ -87,7 +91,7 @@ struct pkg_operations { */ extern struct pkg_operations default_pkg_ops; -struct __pmpkg_t { +struct __alpm_pkg_t { unsigned long name_hash; char *filename; char *name; @@ -96,6 +100,7 @@ struct __pmpkg_t { char *url; char *packager; char *md5sum; + char *base64_sig; char *arch; time_t builddate; @@ -107,20 +112,20 @@ struct __pmpkg_t { int scriptlet; - pmpkgreason_t reason; - pmpkgfrom_t origin; + alpm_pkgreason_t reason; + alpm_dbinfrq_t infolevel; + alpm_pkgfrom_t origin; /* origin == PKG_FROM_FILE, use pkg->origin_data.file * origin == PKG_FROM_*DB, use pkg->origin_data.db */ union { - pmdb_t *db; + alpm_db_t *db; char *file; } origin_data; - pmdbinfrq_t infolevel; + alpm_handle_t *handle; alpm_list_t *licenses; alpm_list_t *replaces; alpm_list_t *groups; - alpm_list_t *files; alpm_list_t *backup; alpm_list_t *depends; alpm_list_t *optdepends; @@ -131,16 +136,27 @@ struct __pmpkg_t { alpm_list_t *removes; /* in transaction targets only */ struct pkg_operations *ops; + + alpm_filelist_t files; }; -pmpkg_t* _alpm_pkg_new(void); -pmpkg_t *_alpm_pkg_dup(pmpkg_t *pkg); -void _alpm_pkg_free(pmpkg_t *pkg); -void _alpm_pkg_free_trans(pmpkg_t *pkg); +alpm_file_t *_alpm_file_copy(alpm_file_t *dest, const alpm_file_t *src); +int _alpm_files_cmp(const void *f1, const void *f2); + +alpm_pkg_t* _alpm_pkg_new(void); +alpm_pkg_t *_alpm_pkg_dup(alpm_pkg_t *pkg); +void _alpm_pkg_free(alpm_pkg_t *pkg); +void _alpm_pkg_free_trans(alpm_pkg_t *pkg); + + +alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle, const char *pkgfile, + int full, const char *md5sum, const char *base64_sig, + alpm_siglevel_t level); + int _alpm_pkg_cmp(const void *p1, const void *p2); -int _alpm_pkg_compare_versions(pmpkg_t *local_pkg, pmpkg_t *pkg); -pmpkg_t *_alpm_pkg_find(alpm_list_t *haystack, const char *needle); -int _alpm_pkg_should_ignore(pmpkg_t *pkg); +int _alpm_pkg_compare_versions(alpm_pkg_t *local_pkg, alpm_pkg_t *pkg); +alpm_pkg_t *_alpm_pkg_find(alpm_list_t *haystack, const char *needle); +int _alpm_pkg_should_ignore(alpm_handle_t *handle, alpm_pkg_t *pkg); #endif /* _ALPM_PACKAGE_H */ diff --git a/lib/libalpm/pkghash.c b/lib/libalpm/pkghash.c index 6dc43243..f6207ada 100644 --- a/lib/libalpm/pkghash.c +++ b/lib/libalpm/pkghash.c @@ -17,9 +17,10 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <errno.h> + #include "pkghash.h" #include "util.h" -#include "log.h" /* List of primes for possible sizes of hash tables. * @@ -50,16 +51,12 @@ static const size_t prime_list[] = }; /* Allocate a hash table with at least "size" buckets */ -pmpkghash_t *_alpm_pkghash_create(size_t size) +alpm_pkghash_t *_alpm_pkghash_create(size_t size) { - pmpkghash_t *hash = NULL; + alpm_pkghash_t *hash = NULL; size_t i, loopsize; - MALLOC(hash, sizeof(pmpkghash_t), RET_ERR(PM_ERR_MEMORY, NULL)); - - hash->list = NULL; - hash->entries = 0; - hash->buckets = 0; + CALLOC(hash, 1, sizeof(alpm_pkghash_t), return NULL); loopsize = sizeof(prime_list) / sizeof(*prime_list); for(i = 0; i < loopsize; i++) { @@ -70,18 +67,18 @@ pmpkghash_t *_alpm_pkghash_create(size_t size) } if(hash->buckets < size) { - _alpm_log(PM_LOG_ERROR, _("database larger than maximum size\n")); + errno = ERANGE; free(hash); - return(NULL); + return NULL; } - CALLOC(hash->hash_table, hash->buckets, sizeof(alpm_list_t*), \ - free(hash); RET_ERR(PM_ERR_MEMORY, NULL)); + CALLOC(hash->hash_table, hash->buckets, sizeof(alpm_list_t *), \ + free(hash); return NULL); - return(hash); + return hash; } -static size_t get_hash_position(unsigned long name_hash, pmpkghash_t *hash) +static size_t get_hash_position(unsigned long name_hash, alpm_pkghash_t *hash) { size_t position; @@ -92,13 +89,13 @@ static size_t get_hash_position(unsigned long name_hash, pmpkghash_t *hash) position = (position + 1) % hash->buckets; } - return(position); + return position; } /* Expand the hash table size to the next increment and rebin the entries */ -static pmpkghash_t *rehash(pmpkghash_t *oldhash) +static alpm_pkghash_t *rehash(alpm_pkghash_t *oldhash) { - pmpkghash_t *newhash; + alpm_pkghash_t *newhash; size_t newsize, position, i; /* Hash tables will need resized in two cases: @@ -123,7 +120,7 @@ static pmpkghash_t *rehash(pmpkghash_t *oldhash) newhash = _alpm_pkghash_create(newsize); if(newhash == NULL) { /* creation of newhash failed, stick with old one... */ - return(oldhash); + return oldhash; } newhash->list = oldhash->list; @@ -131,7 +128,7 @@ static pmpkghash_t *rehash(pmpkghash_t *oldhash) for(i = 0; i < oldhash->buckets; i++) { if(oldhash->hash_table[i] != NULL) { - pmpkg_t *package = oldhash->hash_table[i]->data; + alpm_pkg_t *package = oldhash->hash_table[i]->data; position = get_hash_position(package->name_hash, newhash); @@ -144,16 +141,16 @@ static pmpkghash_t *rehash(pmpkghash_t *oldhash) _alpm_pkghash_free(oldhash); - return(newhash); + return newhash; } -static pmpkghash_t *pkghash_add_pkg(pmpkghash_t *hash, pmpkg_t *pkg, int sorted) +static alpm_pkghash_t *pkghash_add_pkg(alpm_pkghash_t *hash, alpm_pkg_t *pkg, int sorted) { alpm_list_t *ptr; size_t position; if(pkg == NULL || hash == NULL) { - return(hash); + return hash; } if((hash->entries + 1) / MAX_HASH_LOAD > hash->buckets) { @@ -164,7 +161,7 @@ static pmpkghash_t *pkghash_add_pkg(pmpkghash_t *hash, pmpkg_t *pkg, int sorted) ptr = calloc(1, sizeof(alpm_list_t)); if(ptr == NULL) { - return(hash); + return hash; } ptr->data = pkg; @@ -179,20 +176,20 @@ static pmpkghash_t *pkghash_add_pkg(pmpkghash_t *hash, pmpkg_t *pkg, int sorted) } hash->entries += 1; - return(hash); + return hash; } -pmpkghash_t *_alpm_pkghash_add(pmpkghash_t *hash, pmpkg_t *pkg) +alpm_pkghash_t *_alpm_pkghash_add(alpm_pkghash_t *hash, alpm_pkg_t *pkg) { - return(pkghash_add_pkg(hash, pkg, 0)); + return pkghash_add_pkg(hash, pkg, 0); } -pmpkghash_t *_alpm_pkghash_add_sorted(pmpkghash_t *hash, pmpkg_t *pkg) +alpm_pkghash_t *_alpm_pkghash_add_sorted(alpm_pkghash_t *hash, alpm_pkg_t *pkg) { - return(pkghash_add_pkg(hash, pkg, 1)); + return pkghash_add_pkg(hash, pkg, 1); } -static size_t move_one_entry(pmpkghash_t *hash, size_t start, size_t end) +static size_t move_one_entry(alpm_pkghash_t *hash, size_t start, size_t end) { /* Iterate backwards from 'end' to 'start', seeing if any of the items * would hash to 'start'. If we find one, we move it there and break. If @@ -203,7 +200,7 @@ static size_t move_one_entry(pmpkghash_t *hash, size_t start, size_t end) * 'start' we can stop this madness. */ while(end != start) { alpm_list_t *i = hash->hash_table[end]; - pmpkg_t *info = i->data; + alpm_pkg_t *info = i->data; size_t new_position = get_hash_position(info->name_hash, hash); if(new_position == start) { @@ -217,7 +214,7 @@ static size_t move_one_entry(pmpkghash_t *hash, size_t start, size_t end) * e.g. (47 + 0 - 1) % 47 == 46 */ end = (hash->buckets + end - 1) % hash->buckets; } - return(end); + return end; } /** @@ -229,8 +226,8 @@ static size_t move_one_entry(pmpkghash_t *hash, size_t start, size_t end) * * @return the resultant hash */ -pmpkghash_t *_alpm_pkghash_remove(pmpkghash_t *hash, pmpkg_t *pkg, - pmpkg_t **data) +alpm_pkghash_t *_alpm_pkghash_remove(alpm_pkghash_t *hash, alpm_pkg_t *pkg, + alpm_pkg_t **data) { alpm_list_t *i; size_t position; @@ -240,12 +237,12 @@ pmpkghash_t *_alpm_pkghash_remove(pmpkghash_t *hash, pmpkg_t *pkg, } if(pkg == NULL || hash == NULL) { - return(hash); + return hash; } position = pkg->name_hash % hash->buckets; while((i = hash->hash_table[position]) != NULL) { - pmpkg_t *info = i->data; + alpm_pkg_t *info = i->data; if(info->name_hash == pkg->name_hash && strcmp(info->name, pkg->name) == 0) { @@ -277,16 +274,16 @@ pmpkghash_t *_alpm_pkghash_remove(pmpkghash_t *hash, pmpkg_t *pkg, position = prev; } - return(hash); + return hash; } position = (position + 1) % hash->buckets; } - return(hash); + return hash; } -void _alpm_pkghash_free(pmpkghash_t *hash) +void _alpm_pkghash_free(alpm_pkghash_t *hash) { size_t i; if(hash != NULL) { @@ -298,16 +295,14 @@ void _alpm_pkghash_free(pmpkghash_t *hash) free(hash); } -pmpkg_t *_alpm_pkghash_find(pmpkghash_t *hash, const char *name) +alpm_pkg_t *_alpm_pkghash_find(alpm_pkghash_t *hash, const char *name) { alpm_list_t *lp; unsigned long name_hash; size_t position; - ALPM_LOG_FUNC; - if(name == NULL || hash == NULL) { - return(NULL); + return NULL; } name_hash = _alpm_hash_sdbm(name); @@ -315,16 +310,16 @@ pmpkg_t *_alpm_pkghash_find(pmpkghash_t *hash, const char *name) position = name_hash % hash->buckets; while((lp = hash->hash_table[position]) != NULL) { - pmpkg_t *info = lp->data; + alpm_pkg_t *info = lp->data; if(info->name_hash == name_hash && strcmp(info->name, name) == 0) { - return(info); + return info; } position = (position + 1) % hash->buckets; } - return(NULL); + return NULL; } /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/pkghash.h b/lib/libalpm/pkghash.h index 617e60bd..edd500e9 100644 --- a/lib/libalpm/pkghash.h +++ b/lib/libalpm/pkghash.h @@ -27,12 +27,12 @@ /** - * @brief A hash table for holding pmpkg_t objects. + * @brief A hash table for holding alpm_pkg_t objects. * * A combination of a hash table and a list, allowing for fast look-up * by package name but also iteration over the packages. */ -struct __pmpkghash_t { +struct __alpm_pkghash_t { /** data held by the hash table */ alpm_list_t **hash_table; /** number of buckets in hash table */ @@ -43,17 +43,17 @@ struct __pmpkghash_t { alpm_list_t *list; }; -typedef struct __pmpkghash_t pmpkghash_t; +typedef struct __alpm_pkghash_t alpm_pkghash_t; -pmpkghash_t *_alpm_pkghash_create(size_t size); +alpm_pkghash_t *_alpm_pkghash_create(size_t size); -pmpkghash_t *_alpm_pkghash_add(pmpkghash_t *hash, pmpkg_t *pkg); -pmpkghash_t *_alpm_pkghash_add_sorted(pmpkghash_t *hash, pmpkg_t *pkg); -pmpkghash_t *_alpm_pkghash_remove(pmpkghash_t *hash, pmpkg_t *pkg, pmpkg_t **data); +alpm_pkghash_t *_alpm_pkghash_add(alpm_pkghash_t *hash, alpm_pkg_t *pkg); +alpm_pkghash_t *_alpm_pkghash_add_sorted(alpm_pkghash_t *hash, alpm_pkg_t *pkg); +alpm_pkghash_t *_alpm_pkghash_remove(alpm_pkghash_t *hash, alpm_pkg_t *pkg, alpm_pkg_t **data); -void _alpm_pkghash_free(pmpkghash_t *hash); +void _alpm_pkghash_free(alpm_pkghash_t *hash); -pmpkg_t *_alpm_pkghash_find(pmpkghash_t *hash, const char *name); +alpm_pkg_t *_alpm_pkghash_find(alpm_pkghash_t *hash, const char *name); #define MAX_HASH_LOAD 0.7 diff --git a/lib/libalpm/po/Makevars b/lib/libalpm/po/Makevars index 688553d1..09fb3539 100644 --- a/lib/libalpm/po/Makevars +++ b/lib/libalpm/po/Makevars @@ -4,7 +4,7 @@ DOMAIN = libalpm # These two variables depend on the location of this directory. -subdir = po +subdir = lib/libalpm/po top_builddir = ../../../ # These options get passed to xgettext. diff --git a/lib/libalpm/po/ca.po b/lib/libalpm/po/ca.po index 6ada8f4c..450dca97 100644 --- a/lib/libalpm/po/ca.po +++ b/lib/libalpm/po/ca.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Arch Linux Pacman package manager\n" "Report-Msgid-Bugs-To: http://bugs.archlinux.org/index.php?project=3\n" -"POT-Creation-Date: 2011-04-18 11:23-0500\n" +"POT-Creation-Date: 2011-06-23 21:48-0500\n" "PO-Revision-Date: 2011-04-12 11:15+0000\n" "Last-Translator: hseara <hseara@gmail.com>\n" "Language-Team: Catalan <None>\n" @@ -153,6 +153,10 @@ msgstr "falten les metadades del paquet en %s\n" msgid "removing invalid file: %s\n" msgstr "Esborrant fitxer invàlid: %s\n" +#, fuzzy, c-format +msgid "could not parse package '%s' description file from db '%s'\n" +msgstr "no s'ha pogut analitzar el fitxers de descripció de paquet en %s\n" + #, c-format msgid "database path is undefined\n" msgstr "no s'ha definit la ruta de la base de dades\n" @@ -220,18 +224,6 @@ msgid "failed retrieving file '%s' from %s : %s\n" msgstr "ha fallat en recuperar el fitxer '%s' des de %s : %s\n" #, c-format -msgid "resuming download of %s not possible; starting over\n" -msgstr "no es pot la reprendre la baixada de %s, s'està iniciant de nou\n" - -#, c-format -msgid "error writing to file '%s': %s\n" -msgstr "error en escriure al fitxer '%s': %s\n" - -#, c-format -msgid "failed retrieving file '%s' from %s\n" -msgstr "ha fallat en recuperar el fitxer '%s' de %s\n" - -#, c-format msgid "%s appears to be truncated: %jd/%jd bytes\n" msgstr "%s sembla estar truncat: %jd/%jd bytes\n" @@ -381,6 +373,18 @@ msgid "could not find repository for target" msgstr "no s'ha pogut trobar el repositori per l'objectiu" #, c-format +msgid "signature directory not configured correctly" +msgstr "" + +#, c-format +msgid "invalid PGP signature" +msgstr "" + +#, c-format +msgid "unknown PGP signature" +msgstr "" + +#, c-format msgid "invalid or corrupted delta" msgstr "delta invàlid o corrupte" @@ -405,10 +409,6 @@ msgid "failed to retrieve some files" msgstr "ha fallat en recuperar alguns fitxers" #, c-format -msgid "failed to copy some file" -msgstr "no s'ha aconseguit copiar algun arxiu" - -#, c-format msgid "invalid regular expression" msgstr "expressió regular invàlida" @@ -421,6 +421,10 @@ msgid "download library error" msgstr "error de la llibreria de baixades" #, c-format +msgid "gpgme error" +msgstr "" + +#, c-format msgid "error invoking external downloader" msgstr "error en invocar el baixador extern" @@ -429,10 +433,6 @@ msgid "unexpected error" msgstr "error inesperat" #, c-format -msgid "database larger than maximum size\n" -msgstr "base de dades sobrepassa la grandaria màxima\n" - -#, c-format msgid "could not find %s in database -- skipping\n" msgstr "no s'ha pogut trobar %s en la base de dades -- s'està ometent\n" @@ -553,3 +553,18 @@ msgstr "no existeix memòria cau %s, s'està creant...\n" #, c-format msgid "couldn't create package cache, using /tmp instead\n" msgstr "no s'ha pogut crear la memòria cau del paquet, s'usarà /tmp\n" + +#~ msgid "resuming download of %s not possible; starting over\n" +#~ msgstr "no es pot la reprendre la baixada de %s, s'està iniciant de nou\n" + +#~ msgid "error writing to file '%s': %s\n" +#~ msgstr "error en escriure al fitxer '%s': %s\n" + +#~ msgid "failed retrieving file '%s' from %s\n" +#~ msgstr "ha fallat en recuperar el fitxer '%s' de %s\n" + +#~ msgid "failed to copy some file" +#~ msgstr "no s'ha aconseguit copiar algun arxiu" + +#~ msgid "database larger than maximum size\n" +#~ msgstr "base de dades sobrepassa la grandaria màxima\n" diff --git a/lib/libalpm/po/cs.po b/lib/libalpm/po/cs.po index 0aa8ad3a..c2d51f4d 100644 --- a/lib/libalpm/po/cs.po +++ b/lib/libalpm/po/cs.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Arch Linux Pacman package manager\n" "Report-Msgid-Bugs-To: http://bugs.archlinux.org/index.php?project=3\n" -"POT-Creation-Date: 2011-04-18 11:23-0500\n" +"POT-Creation-Date: 2011-06-23 21:48-0500\n" "PO-Revision-Date: 2011-03-22 15:34+0000\n" "Last-Translator: vogo <vojtech.gondzala@gmail.com>\n" "Language-Team: Czech <None>\n" @@ -153,6 +153,10 @@ msgstr "chybí metadata balíčku v %s\n" msgid "removing invalid file: %s\n" msgstr "odstraněn neplatný soubor: %s\n" +#, fuzzy, c-format +msgid "could not parse package '%s' description file from db '%s'\n" +msgstr "nelze zpracovat soubor s popisem balíčku v %s\n" + #, c-format msgid "database path is undefined\n" msgstr "cesta k databázi není definována\n" @@ -219,18 +223,6 @@ msgid "failed retrieving file '%s' from %s : %s\n" msgstr "selhalo získání souboru '%s' z %s: %s\n" #, c-format -msgid "resuming download of %s not possible; starting over\n" -msgstr "nelze navázat stahování %s, začíná se znovu\n" - -#, c-format -msgid "error writing to file '%s': %s\n" -msgstr "chyba při zápisu do souboru '%s': %s\n" - -#, c-format -msgid "failed retrieving file '%s' from %s\n" -msgstr "selhalo získání souboru '%s' z %s\n" - -#, c-format msgid "%s appears to be truncated: %jd/%jd bytes\n" msgstr "%s se zdá být zkrácen: %jd/%jd bytů\n" @@ -379,6 +371,18 @@ msgid "could not find repository for target" msgstr "nelze nalézt repositář cíle" #, c-format +msgid "signature directory not configured correctly" +msgstr "" + +#, c-format +msgid "invalid PGP signature" +msgstr "" + +#, c-format +msgid "unknown PGP signature" +msgstr "" + +#, c-format msgid "invalid or corrupted delta" msgstr "neplatný nebo poškozený delta rozdíl" @@ -403,10 +407,6 @@ msgid "failed to retrieve some files" msgstr "selhalo získání některých souborů" #, c-format -msgid "failed to copy some file" -msgstr "selhalo kopírování souboru" - -#, c-format msgid "invalid regular expression" msgstr "nesprávný regulární výraz" @@ -419,6 +419,10 @@ msgid "download library error" msgstr "chyba knihovny pro stahování souborů" #, c-format +msgid "gpgme error" +msgstr "" + +#, c-format msgid "error invoking external downloader" msgstr "chyba volání externího programu pro stahování souborů" @@ -427,10 +431,6 @@ msgid "unexpected error" msgstr "neočekávaná chyba" #, c-format -msgid "database larger than maximum size\n" -msgstr "databáze je větší než maximální přípustná velikost\n" - -#, c-format msgid "could not find %s in database -- skipping\n" msgstr "nelze nalézt %s v databázi -- vynechat\n" @@ -549,3 +549,18 @@ msgstr "neexistuje mezipaměť %s, vytváří se...\n" #, c-format msgid "couldn't create package cache, using /tmp instead\n" msgstr "nelze vytvořit mezipaměť balíčků, používá se /tmp\n" + +#~ msgid "resuming download of %s not possible; starting over\n" +#~ msgstr "nelze navázat stahování %s, začíná se znovu\n" + +#~ msgid "error writing to file '%s': %s\n" +#~ msgstr "chyba při zápisu do souboru '%s': %s\n" + +#~ msgid "failed retrieving file '%s' from %s\n" +#~ msgstr "selhalo získání souboru '%s' z %s\n" + +#~ msgid "failed to copy some file" +#~ msgstr "selhalo kopírování souboru" + +#~ msgid "database larger than maximum size\n" +#~ msgstr "databáze je větší než maximální přípustná velikost\n" diff --git a/lib/libalpm/po/da.po b/lib/libalpm/po/da.po index 9f506e90..11253c77 100644 --- a/lib/libalpm/po/da.po +++ b/lib/libalpm/po/da.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Arch Linux Pacman package manager\n" "Report-Msgid-Bugs-To: http://bugs.archlinux.org/index.php?project=3\n" -"POT-Creation-Date: 2011-04-18 11:23-0500\n" +"POT-Creation-Date: 2011-06-23 21:48-0500\n" "PO-Revision-Date: 2011-03-22 15:34+0000\n" "Last-Translator: toofishes <dpmcgee@gmail.com>\n" "Language-Team: Danish <None>\n" @@ -153,6 +153,10 @@ msgstr "manglende pakkemetadata i %s\n" msgid "removing invalid file: %s\n" msgstr "" +#, fuzzy, c-format +msgid "could not parse package '%s' description file from db '%s'\n" +msgstr "kunne ikke fortolke pakkebeskrivelsesfil i %s\n" + #, c-format msgid "database path is undefined\n" msgstr "databasesti er udefineret\n" @@ -218,18 +222,6 @@ msgid "failed retrieving file '%s' from %s : %s\n" msgstr "fejlede i indhentning af fil »%s« fra %s: %s\n" #, c-format -msgid "resuming download of %s not possible; starting over\n" -msgstr "det er ikke muligt at genoptage hentning af %s; starter forfra\n" - -#, c-format -msgid "error writing to file '%s': %s\n" -msgstr "fejl under skrivning til fil »%s«: %s\n" - -#, c-format -msgid "failed retrieving file '%s' from %s\n" -msgstr "kunne ikke indhente fil »%s« fra %s\n" - -#, c-format msgid "%s appears to be truncated: %jd/%jd bytes\n" msgstr "%s ser ud til at være afkortet: %jd/%jd byte\n" @@ -378,6 +370,18 @@ msgid "could not find repository for target" msgstr "kunne ikke finde arkiv for mål" #, c-format +msgid "signature directory not configured correctly" +msgstr "" + +#, c-format +msgid "invalid PGP signature" +msgstr "" + +#, c-format +msgid "unknown PGP signature" +msgstr "" + +#, c-format msgid "invalid or corrupted delta" msgstr "ugyldig eller ødelagt delta" @@ -402,10 +406,6 @@ msgid "failed to retrieve some files" msgstr "kunne ikke indhente nogle filer" #, c-format -msgid "failed to copy some file" -msgstr "" - -#, c-format msgid "invalid regular expression" msgstr "ugyldigt regulært udtryk" @@ -418,6 +418,10 @@ msgid "download library error" msgstr "hent biblioteksfejl" #, c-format +msgid "gpgme error" +msgstr "" + +#, c-format msgid "error invoking external downloader" msgstr "fejl under opstart af ekstern hentningsprogram" @@ -426,10 +430,6 @@ msgid "unexpected error" msgstr "uventet fejl" #, c-format -msgid "database larger than maximum size\n" -msgstr "" - -#, c-format msgid "could not find %s in database -- skipping\n" msgstr "kunne ikke finde %s i database - springer over\n" @@ -548,3 +548,12 @@ msgstr "intet %s-mellemlager findes, opretter...\n" #, c-format msgid "couldn't create package cache, using /tmp instead\n" msgstr "kunne ikke oprette pakkemellemlager, bruger /tmp i steden for\n" + +#~ msgid "resuming download of %s not possible; starting over\n" +#~ msgstr "det er ikke muligt at genoptage hentning af %s; starter forfra\n" + +#~ msgid "error writing to file '%s': %s\n" +#~ msgstr "fejl under skrivning til fil »%s«: %s\n" + +#~ msgid "failed retrieving file '%s' from %s\n" +#~ msgstr "kunne ikke indhente fil »%s« fra %s\n" diff --git a/lib/libalpm/po/de.po b/lib/libalpm/po/de.po index cdda63d1..50853a2a 100644 --- a/lib/libalpm/po/de.po +++ b/lib/libalpm/po/de.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Arch Linux Pacman package manager\n" "Report-Msgid-Bugs-To: http://bugs.archlinux.org/index.php?project=3\n" -"POT-Creation-Date: 2011-04-18 11:23-0500\n" +"POT-Creation-Date: 2011-06-23 21:48-0500\n" "PO-Revision-Date: 2011-03-22 15:34+0000\n" "Last-Translator: tlaloc <matthias@archlinux.de>\n" "Language-Team: German <None>\n" @@ -157,6 +157,10 @@ msgstr "Fehlende Paket-Metadaten in %s\n" msgid "removing invalid file: %s\n" msgstr "Entferne ungültige Datei: %s\n" +#, fuzzy, c-format +msgid "could not parse package '%s' description file from db '%s'\n" +msgstr "Konnte Paket-Beschreibungsdatei in %s nicht analysieren\n" + #, c-format msgid "database path is undefined\n" msgstr "Datenbank-Pfad ist nicht definiert\n" @@ -223,18 +227,6 @@ msgid "failed retrieving file '%s' from %s : %s\n" msgstr "Konnte Datei '%s' nicht von %s übertragen : %s\n" #, c-format -msgid "resuming download of %s not possible; starting over\n" -msgstr "Kann den Download von %s nicht wieder aufnehmen, starte neu\n" - -#, c-format -msgid "error writing to file '%s': %s\n" -msgstr "Fehler beim Beschreiben von Datei '%s': %s\n" - -#, c-format -msgid "failed retrieving file '%s' from %s\n" -msgstr "Konnte Datei '%s' nicht von %s übertragen\n" - -#, c-format msgid "%s appears to be truncated: %jd/%jd bytes\n" msgstr "%s scheint verstümmelt zu sein: %jd/%jd Byte\n" @@ -384,6 +376,18 @@ msgid "could not find repository for target" msgstr "Konnte kein Repositorium für das Ziel finden" #, c-format +msgid "signature directory not configured correctly" +msgstr "" + +#, c-format +msgid "invalid PGP signature" +msgstr "" + +#, c-format +msgid "unknown PGP signature" +msgstr "" + +#, c-format msgid "invalid or corrupted delta" msgstr "Ungültiges oder beschädigtes Delta" @@ -408,10 +412,6 @@ msgid "failed to retrieve some files" msgstr "Konnte manche Dateien nicht übertragen" #, c-format -msgid "failed to copy some file" -msgstr "Konnte irgendeine Datei nicht kopieren" - -#, c-format msgid "invalid regular expression" msgstr "Ungültiger Regulärer Ausdruck" @@ -424,6 +424,10 @@ msgid "download library error" msgstr "Fehler in der Bibliothek für Downloads" #, c-format +msgid "gpgme error" +msgstr "" + +#, c-format msgid "error invoking external downloader" msgstr "Fehler beim Aufruf eines externen Downloaders" @@ -432,10 +436,6 @@ msgid "unexpected error" msgstr "Unerwarteter Fehler" #, c-format -msgid "database larger than maximum size\n" -msgstr "Datenbank überschreitet die maximal erlaubte Größe\n" - -#, c-format msgid "could not find %s in database -- skipping\n" msgstr "Konnte %s nicht in Datenbank finden -- Überspringe\n" @@ -554,3 +554,18 @@ msgstr "Es existiert kein %s-Puffer. Erstelle... \n" #, c-format msgid "couldn't create package cache, using /tmp instead\n" msgstr "Konnte Paketpuffer nicht erstellen, benutze stattdessen /tmp\n" + +#~ msgid "resuming download of %s not possible; starting over\n" +#~ msgstr "Kann den Download von %s nicht wieder aufnehmen, starte neu\n" + +#~ msgid "error writing to file '%s': %s\n" +#~ msgstr "Fehler beim Beschreiben von Datei '%s': %s\n" + +#~ msgid "failed retrieving file '%s' from %s\n" +#~ msgstr "Konnte Datei '%s' nicht von %s übertragen\n" + +#~ msgid "failed to copy some file" +#~ msgstr "Konnte irgendeine Datei nicht kopieren" + +#~ msgid "database larger than maximum size\n" +#~ msgstr "Datenbank überschreitet die maximal erlaubte Größe\n" diff --git a/lib/libalpm/po/el.po b/lib/libalpm/po/el.po index 68523f8c..b2d8c626 100644 --- a/lib/libalpm/po/el.po +++ b/lib/libalpm/po/el.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Arch Linux Pacman package manager\n" "Report-Msgid-Bugs-To: http://bugs.archlinux.org/index.php?project=3\n" -"POT-Creation-Date: 2011-04-18 11:23-0500\n" +"POT-Creation-Date: 2011-06-23 21:48-0500\n" "PO-Revision-Date: 2011-04-08 16:42+0000\n" "Last-Translator: nous <nous@archlinux.us>\n" "Language-Team: Greek <None>\n" @@ -153,6 +153,10 @@ msgstr "απόντα μετα-δεδομένα πακέτου στο %s\n" msgid "removing invalid file: %s\n" msgstr "διαγραφή άκυρου αρχείου: %s\n" +#, fuzzy, c-format +msgid "could not parse package '%s' description file from db '%s'\n" +msgstr "αδυναμία ανάλυσης αρχείου περιγραφής πακέτου στο %s\n" + #, c-format msgid "database path is undefined\n" msgstr "ακαθόριστη διαδρομή βάσης\n" @@ -218,18 +222,6 @@ msgid "failed retrieving file '%s' from %s : %s\n" msgstr "αποτυχία λήψης αρχείου '%s' από %s : %s\n" #, c-format -msgid "resuming download of %s not possible; starting over\n" -msgstr "συνέχιση λήψης %s αδύνατη, επανεκκίνηση\n" - -#, c-format -msgid "error writing to file '%s': %s\n" -msgstr "σφάλμα εγγραφής στο '%s': %s\n" - -#, c-format -msgid "failed retrieving file '%s' from %s\n" -msgstr "αποτυχία λήψης αρχείου '%s' από %s\n" - -#, c-format msgid "%s appears to be truncated: %jd/%jd bytes\n" msgstr "το %s δείχνει ημιτελές: %jd/%jd bytes\n" @@ -378,6 +370,18 @@ msgid "could not find repository for target" msgstr "αδυναμία εύρεσης αποθήκης για διεκπεραίωση" #, c-format +msgid "signature directory not configured correctly" +msgstr "" + +#, c-format +msgid "invalid PGP signature" +msgstr "" + +#, c-format +msgid "unknown PGP signature" +msgstr "" + +#, c-format msgid "invalid or corrupted delta" msgstr "άκυρο ή κατεστραμμένο delta" @@ -402,10 +406,6 @@ msgid "failed to retrieve some files" msgstr "αποτυχία λήψης κάποιων αρχείων" #, c-format -msgid "failed to copy some file" -msgstr "αποτυχία αντιγραφής αρχείου" - -#, c-format msgid "invalid regular expression" msgstr "άκυρη κανονική έκφραση" @@ -418,6 +418,10 @@ msgid "download library error" msgstr "σφάλμα βιβλιοθήκης λήψης" #, c-format +msgid "gpgme error" +msgstr "" + +#, c-format msgid "error invoking external downloader" msgstr "σφάλμα κλήσης προγράμματος λήψης" @@ -426,10 +430,6 @@ msgid "unexpected error" msgstr "απροσδόκητο σφάλμα" #, c-format -msgid "database larger than maximum size\n" -msgstr "βάση μεγαλύτερη από μέγιστο όριο\n" - -#, c-format msgid "could not find %s in database -- skipping\n" msgstr "δεν βρέθηκε το %s στη βάση -- παράλειψη\n" @@ -549,3 +549,18 @@ msgstr "δημιουργία κρύπτης %s...\n" #, c-format msgid "couldn't create package cache, using /tmp instead\n" msgstr "αδυναμία δημιουργίας κρύπτης πακέτων, χρήση /tmp\n" + +#~ msgid "resuming download of %s not possible; starting over\n" +#~ msgstr "συνέχιση λήψης %s αδύνατη, επανεκκίνηση\n" + +#~ msgid "error writing to file '%s': %s\n" +#~ msgstr "σφάλμα εγγραφής στο '%s': %s\n" + +#~ msgid "failed retrieving file '%s' from %s\n" +#~ msgstr "αποτυχία λήψης αρχείου '%s' από %s\n" + +#~ msgid "failed to copy some file" +#~ msgstr "αποτυχία αντιγραφής αρχείου" + +#~ msgid "database larger than maximum size\n" +#~ msgstr "βάση μεγαλύτερη από μέγιστο όριο\n" diff --git a/lib/libalpm/po/en_GB.po b/lib/libalpm/po/en_GB.po index d6cd67d7..02037648 100644 --- a/lib/libalpm/po/en_GB.po +++ b/lib/libalpm/po/en_GB.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Arch Linux Pacman package manager\n" "Report-Msgid-Bugs-To: http://bugs.archlinux.org/index.php?project=3\n" -"POT-Creation-Date: 2011-04-18 11:23-0500\n" +"POT-Creation-Date: 2011-06-23 21:48-0500\n" "PO-Revision-Date: 2011-03-22 15:34+0000\n" "Last-Translator: toofishes <dpmcgee@gmail.com>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -153,6 +153,10 @@ msgstr "missing package metadata in %s\n" msgid "removing invalid file: %s\n" msgstr "removing invalid file: %s\n" +#, fuzzy, c-format +msgid "could not parse package '%s' description file from db '%s'\n" +msgstr "could not parse package description file in %s\n" + #, c-format msgid "database path is undefined\n" msgstr "database path is undefined\n" @@ -218,18 +222,6 @@ msgid "failed retrieving file '%s' from %s : %s\n" msgstr "failed retrieving file '%s' from %s : %s\n" #, c-format -msgid "resuming download of %s not possible; starting over\n" -msgstr "resuming download of %s not possible; starting over\n" - -#, c-format -msgid "error writing to file '%s': %s\n" -msgstr "error writing to file '%s': %s\n" - -#, c-format -msgid "failed retrieving file '%s' from %s\n" -msgstr "failed retrieving file '%s' from %s\n" - -#, c-format msgid "%s appears to be truncated: %jd/%jd bytes\n" msgstr "%s appears to be truncated: %jd/%jd bytes\n" @@ -378,6 +370,18 @@ msgid "could not find repository for target" msgstr "could not find repository for target" #, c-format +msgid "signature directory not configured correctly" +msgstr "" + +#, c-format +msgid "invalid PGP signature" +msgstr "" + +#, c-format +msgid "unknown PGP signature" +msgstr "" + +#, c-format msgid "invalid or corrupted delta" msgstr "invalid or corrupted delta" @@ -402,10 +406,6 @@ msgid "failed to retrieve some files" msgstr "failed to retrieve some files" #, c-format -msgid "failed to copy some file" -msgstr "failed to copy some file" - -#, c-format msgid "invalid regular expression" msgstr "invalid regular expression" @@ -418,6 +418,10 @@ msgid "download library error" msgstr "download library error" #, c-format +msgid "gpgme error" +msgstr "" + +#, c-format msgid "error invoking external downloader" msgstr "error invoking external downloader" @@ -426,10 +430,6 @@ msgid "unexpected error" msgstr "unexpected error" #, c-format -msgid "database larger than maximum size\n" -msgstr "database larger than maximum size\n" - -#, c-format msgid "could not find %s in database -- skipping\n" msgstr "could not find %s in database -- skipping\n" @@ -548,3 +548,18 @@ msgstr "no %s cache exists, creating...\n" #, c-format msgid "couldn't create package cache, using /tmp instead\n" msgstr "couldn't create package cache, using /tmp instead\n" + +#~ msgid "resuming download of %s not possible; starting over\n" +#~ msgstr "resuming download of %s not possible; starting over\n" + +#~ msgid "error writing to file '%s': %s\n" +#~ msgstr "error writing to file '%s': %s\n" + +#~ msgid "failed retrieving file '%s' from %s\n" +#~ msgstr "failed retrieving file '%s' from %s\n" + +#~ msgid "failed to copy some file" +#~ msgstr "failed to copy some file" + +#~ msgid "database larger than maximum size\n" +#~ msgstr "database larger than maximum size\n" diff --git a/lib/libalpm/po/es.po b/lib/libalpm/po/es.po index 480e4308..afd41236 100644 --- a/lib/libalpm/po/es.po +++ b/lib/libalpm/po/es.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Arch Linux Pacman package manager\n" "Report-Msgid-Bugs-To: http://bugs.archlinux.org/index.php?project=3\n" -"POT-Creation-Date: 2011-04-18 11:23-0500\n" +"POT-Creation-Date: 2011-06-23 21:48-0500\n" "PO-Revision-Date: 2011-03-22 15:34+0000\n" "Last-Translator: angvp <angvp@archlinux.org>\n" "Language-Team: Spanish (Castilian) <>\n" @@ -157,6 +157,10 @@ msgstr "faltan los metadatos del paquete en %s\n" msgid "removing invalid file: %s\n" msgstr "eliminando archivo inválido: %s\n" +#, fuzzy, c-format +msgid "could not parse package '%s' description file from db '%s'\n" +msgstr "no se pudo interpretar el archivo de descripción en %s\n" + #, c-format msgid "database path is undefined\n" msgstr "la ruta de la base de datos no está definida\n" @@ -226,18 +230,6 @@ msgid "failed retrieving file '%s' from %s : %s\n" msgstr "fallo al obtener archivo '%s' desde %s: %s\n" #, c-format -msgid "resuming download of %s not possible; starting over\n" -msgstr "no es posible continuar la descarga de %s; empezando de nuevo\n" - -#, c-format -msgid "error writing to file '%s': %s\n" -msgstr "no se pudo escribir al archivo '%s': %s\n" - -#, c-format -msgid "failed retrieving file '%s' from %s\n" -msgstr "error al obtener el archivo '%s' desde %s\n" - -#, c-format msgid "%s appears to be truncated: %jd/%jd bytes\n" msgstr "%s parece estar truncado: %jd/%jd bytes\n" @@ -387,6 +379,18 @@ msgid "could not find repository for target" msgstr "no pudo encontrarse un repositorio para el objetivo" #, c-format +msgid "signature directory not configured correctly" +msgstr "" + +#, c-format +msgid "invalid PGP signature" +msgstr "" + +#, c-format +msgid "unknown PGP signature" +msgstr "" + +#, c-format msgid "invalid or corrupted delta" msgstr "no válido o diferencial dañado" @@ -411,10 +415,6 @@ msgid "failed to retrieve some files" msgstr "error al descargar algunos archivos" #, c-format -msgid "failed to copy some file" -msgstr "error al copiar algún archivo" - -#, c-format msgid "invalid regular expression" msgstr "expresión regular no válida" @@ -427,6 +427,10 @@ msgid "download library error" msgstr "error de descarga de biblioteca" #, c-format +msgid "gpgme error" +msgstr "" + +#, c-format msgid "error invoking external downloader" msgstr "error invocando el descargador externo" @@ -435,10 +439,6 @@ msgid "unexpected error" msgstr "error inesperado" #, c-format -msgid "database larger than maximum size\n" -msgstr "la base de datos supera el tamaño máximo\n" - -#, c-format msgid "could not find %s in database -- skipping\n" msgstr "no se pudo encontrar %s en la base de datos -- saltando\n" @@ -559,3 +559,18 @@ msgstr "no existe la caché %s, creando...\n" #, c-format msgid "couldn't create package cache, using /tmp instead\n" msgstr "no se pudo crear la cache de paquetes, usando /tmp en su lugar\n" + +#~ msgid "resuming download of %s not possible; starting over\n" +#~ msgstr "no es posible continuar la descarga de %s; empezando de nuevo\n" + +#~ msgid "error writing to file '%s': %s\n" +#~ msgstr "no se pudo escribir al archivo '%s': %s\n" + +#~ msgid "failed retrieving file '%s' from %s\n" +#~ msgstr "error al obtener el archivo '%s' desde %s\n" + +#~ msgid "failed to copy some file" +#~ msgstr "error al copiar algún archivo" + +#~ msgid "database larger than maximum size\n" +#~ msgstr "la base de datos supera el tamaño máximo\n" diff --git a/lib/libalpm/po/fi.po b/lib/libalpm/po/fi.po index 09909f56..8af1205a 100644 --- a/lib/libalpm/po/fi.po +++ b/lib/libalpm/po/fi.po @@ -158,6 +158,10 @@ msgstr "paketin metadata puuttuu tiedostosta %s\n" msgid "removing invalid file: %s\n" msgstr "poistetaan virheellinen tiedosto: %s\n" +#, fuzzy, c-format +msgid "could not parse package '%s' description file from db '%s'\n" +msgstr "paketin kuvausta tiedostossa %s ei voitu jäsentää\n" + #, c-format msgid "database path is undefined\n" msgstr "tietokannan polkua ei ole määritelty\n" @@ -223,18 +227,6 @@ msgid "failed retrieving file '%s' from %s : %s\n" msgstr "tiedoston '%s' nouto palvelimelta %s epäonnistui : %s\n" #, c-format -msgid "resuming download of %s not possible; starting over\n" -msgstr "tiedoston %s latauksen jatkaminen ei mahdollista; aloitetaan alusta\n" - -#, c-format -msgid "error writing to file '%s': %s\n" -msgstr "virhe kirjoitettaessa tiedostoon '%s': %s\n" - -#, c-format -msgid "failed retrieving file '%s' from %s\n" -msgstr "tiedoston '%s' nouto palvelimelta %s epäonnistui\n" - -#, c-format msgid "%s appears to be truncated: %jd/%jd bytes\n" msgstr "%s näyttää katkenneen: %jd/%jd tavua\n" @@ -383,6 +375,18 @@ msgid "could not find repository for target" msgstr "kohteen varastoa ei löytynyt" #, c-format +msgid "signature directory not configured correctly" +msgstr "" + +#, c-format +msgid "invalid PGP signature" +msgstr "" + +#, c-format +msgid "unknown PGP signature" +msgstr "" + +#, c-format msgid "invalid or corrupted delta" msgstr "delta ei kelvollinen tai vahingoittunut" @@ -407,10 +411,6 @@ msgid "failed to retrieve some files" msgstr "joidenkin tiedostojen nouto epäonnistui" #, c-format -msgid "failed to copy some file" -msgstr "jonkin tiedoston kopiointi epäonnistui" - -#, c-format msgid "invalid regular expression" msgstr "virheellinen säännöllinen lauseke" @@ -423,6 +423,10 @@ msgid "download library error" msgstr "latauskirjaston virhe" #, c-format +msgid "gpgme error" +msgstr "" + +#, c-format msgid "error invoking external downloader" msgstr "virhe kutsuttaessa ulkoista latausohjelmaa" @@ -431,10 +435,6 @@ msgid "unexpected error" msgstr "odottamaton virhe" #, c-format -msgid "database larger than maximum size\n" -msgstr "tietokanta enimmäiskokoa suurempi\n" - -#, c-format msgid "could not find %s in database -- skipping\n" msgstr "%s ei löytynyt tietokannasta -- ohitetaan\n" @@ -555,3 +555,19 @@ msgstr "välimuistia %s ei ole olemassa, luodaan...\n" #, c-format msgid "couldn't create package cache, using /tmp instead\n" msgstr "pakettivälimuistia ei voitu luoda, käytetään /tmp:tä sen sijasta\n" + +#~ msgid "resuming download of %s not possible; starting over\n" +#~ msgstr "" +#~ "tiedoston %s latauksen jatkaminen ei mahdollista; aloitetaan alusta\n" + +#~ msgid "error writing to file '%s': %s\n" +#~ msgstr "virhe kirjoitettaessa tiedostoon '%s': %s\n" + +#~ msgid "failed retrieving file '%s' from %s\n" +#~ msgstr "tiedoston '%s' nouto palvelimelta %s epäonnistui\n" + +#~ msgid "failed to copy some file" +#~ msgstr "jonkin tiedoston kopiointi epäonnistui" + +#~ msgid "database larger than maximum size\n" +#~ msgstr "tietokanta enimmäiskokoa suurempi\n" diff --git a/lib/libalpm/po/fr.po b/lib/libalpm/po/fr.po index 48d0d6c8..f2279c68 100644 --- a/lib/libalpm/po/fr.po +++ b/lib/libalpm/po/fr.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Arch Linux Pacman package manager\n" "Report-Msgid-Bugs-To: http://bugs.archlinux.org/index.php?project=3\n" -"POT-Creation-Date: 2011-04-18 11:23-0500\n" +"POT-Creation-Date: 2011-06-23 21:48-0500\n" "PO-Revision-Date: 2011-03-23 07:04+0000\n" "Last-Translator: toofishes <dpmcgee@gmail.com>\n" "Language-Team: French <>\n" @@ -153,6 +153,10 @@ msgstr "méta-données du paquet manquantes dans %s\n" msgid "removing invalid file: %s\n" msgstr "suppression du fichier invalide: %s\n" +#, fuzzy, c-format +msgid "could not parse package '%s' description file from db '%s'\n" +msgstr "l'analyse du fichier de description a échoué dans %s\n" + #, c-format msgid "database path is undefined\n" msgstr "base de données non initialisée\n" @@ -221,18 +225,6 @@ msgid "failed retrieving file '%s' from %s : %s\n" msgstr "échec de récupération du fichier '%s' depuis %s : %s\n" #, c-format -msgid "resuming download of %s not possible; starting over\n" -msgstr "le téléchargement de %s ne peut pas être continué, reprise au début\n" - -#, c-format -msgid "error writing to file '%s': %s\n" -msgstr "écriture dans le fichier '%s' impossible: %s\n" - -#, c-format -msgid "failed retrieving file '%s' from %s\n" -msgstr "échec de récupération du fichier '%s' depuis %s\n" - -#, c-format msgid "%s appears to be truncated: %jd/%jd bytes\n" msgstr "%s est apparemment tronqué: %jd/%jd bytes\n" @@ -383,6 +375,18 @@ msgid "could not find repository for target" msgstr "impossible de trouver le dépôt pour la cible" #, c-format +msgid "signature directory not configured correctly" +msgstr "" + +#, c-format +msgid "invalid PGP signature" +msgstr "" + +#, c-format +msgid "unknown PGP signature" +msgstr "" + +#, c-format msgid "invalid or corrupted delta" msgstr "delta invalide ou corrompu" @@ -407,10 +411,6 @@ msgid "failed to retrieve some files" msgstr "échec de récupération de certains fichiers" #, c-format -msgid "failed to copy some file" -msgstr "erreur lors d'une copie de fichier" - -#, c-format msgid "invalid regular expression" msgstr "expression régulière incorrecte" @@ -423,6 +423,10 @@ msgid "download library error" msgstr "erreur de la bibliothèque de téléchargement" #, c-format +msgid "gpgme error" +msgstr "" + +#, c-format msgid "error invoking external downloader" msgstr "erreur en invoquant le client externe de téléchargement" @@ -431,10 +435,6 @@ msgid "unexpected error" msgstr "erreur non prévue" #, c-format -msgid "database larger than maximum size\n" -msgstr "la base de données est plus grande que la taille maximale\n" - -#, c-format msgid "could not find %s in database -- skipping\n" msgstr "trouver %s dans la base de données a échoué -- ignoré\n" @@ -553,3 +553,19 @@ msgstr "le cache %s n'existe pas, création...\n" #, c-format msgid "couldn't create package cache, using /tmp instead\n" msgstr "n'a pas pu créer le cache de paquets, /tmp sera utilisé à la place\n" + +#~ msgid "resuming download of %s not possible; starting over\n" +#~ msgstr "" +#~ "le téléchargement de %s ne peut pas être continué, reprise au début\n" + +#~ msgid "error writing to file '%s': %s\n" +#~ msgstr "écriture dans le fichier '%s' impossible: %s\n" + +#~ msgid "failed retrieving file '%s' from %s\n" +#~ msgstr "échec de récupération du fichier '%s' depuis %s\n" + +#~ msgid "failed to copy some file" +#~ msgstr "erreur lors d'une copie de fichier" + +#~ msgid "database larger than maximum size\n" +#~ msgstr "la base de données est plus grande que la taille maximale\n" diff --git a/lib/libalpm/po/hu.po b/lib/libalpm/po/hu.po index e49075a7..ec796cb4 100644 --- a/lib/libalpm/po/hu.po +++ b/lib/libalpm/po/hu.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Arch Linux Pacman package manager\n" "Report-Msgid-Bugs-To: http://bugs.archlinux.org/index.php?project=3\n" -"POT-Creation-Date: 2011-04-18 11:23-0500\n" +"POT-Creation-Date: 2011-06-23 21:48-0500\n" "PO-Revision-Date: 2011-03-22 15:34+0000\n" "Last-Translator: ngaba <ngaba@bibl.u-szeged.hu>\n" "Language-Team: Hungarian <None>\n" @@ -153,6 +153,10 @@ msgstr "hiányzó csomaginformációs fájl itt: %s\n" msgid "removing invalid file: %s\n" msgstr "hibás fájl eltávolítása: %s\n" +#, fuzzy, c-format +msgid "could not parse package '%s' description file from db '%s'\n" +msgstr "nem sikerült értelmezni a(z) %s csomagleíró fájlját\n" + #, c-format msgid "database path is undefined\n" msgstr "az adatbázis-útvonal nincs megadva\n" @@ -220,18 +224,6 @@ msgid "failed retrieving file '%s' from %s : %s\n" msgstr "nem sikerült a(z) '%s' fájlt letölteni a %s helyről : %s\n" #, c-format -msgid "resuming download of %s not possible; starting over\n" -msgstr "nem tudom folytatni a(z) %s letöltését; újrakezdem\n" - -#, c-format -msgid "error writing to file '%s': %s\n" -msgstr "hiba a(z) '%s' fájl írása során: %s\n" - -#, c-format -msgid "failed retrieving file '%s' from %s\n" -msgstr "nem sikerült a(z) '%s' fájlt letölteni a %s helyről\n" - -#, c-format msgid "%s appears to be truncated: %jd/%jd bytes\n" msgstr "úgy tűnik, hogy %s csonka: %jd/%jd bájt\n" @@ -380,6 +372,18 @@ msgid "could not find repository for target" msgstr "nem található repó a célcsomaghoz" #, c-format +msgid "signature directory not configured correctly" +msgstr "" + +#, c-format +msgid "invalid PGP signature" +msgstr "" + +#, c-format +msgid "unknown PGP signature" +msgstr "" + +#, c-format msgid "invalid or corrupted delta" msgstr "hibás vagy sérült delta" @@ -404,10 +408,6 @@ msgid "failed to retrieve some files" msgstr "nem sikerült néhány fájlt letölteni" #, c-format -msgid "failed to copy some file" -msgstr "nem sikerült néhány fájlt másolni" - -#, c-format msgid "invalid regular expression" msgstr "hibás reguláris kifejezés" @@ -420,6 +420,10 @@ msgid "download library error" msgstr "letöltőkönyvtár hiba" #, c-format +msgid "gpgme error" +msgstr "" + +#, c-format msgid "error invoking external downloader" msgstr "hiba a külső letöltő meghívásakor" @@ -428,10 +432,6 @@ msgid "unexpected error" msgstr "nemvárt hiba" #, c-format -msgid "database larger than maximum size\n" -msgstr "az adatbázis nagyobb, mint a maximális megengedett méret\n" - -#, c-format msgid "could not find %s in database -- skipping\n" msgstr "nem található a(z) %s az adatbázisban -- kihagyás\n" @@ -550,3 +550,18 @@ msgstr "nem létezik a(z) %s gyorsítótár. létrehozás...\n" #, c-format msgid "couldn't create package cache, using /tmp instead\n" msgstr "nem sikerült létrehozni a csomaggyorsítótárat, a /tmp használata\n" + +#~ msgid "resuming download of %s not possible; starting over\n" +#~ msgstr "nem tudom folytatni a(z) %s letöltését; újrakezdem\n" + +#~ msgid "error writing to file '%s': %s\n" +#~ msgstr "hiba a(z) '%s' fájl írása során: %s\n" + +#~ msgid "failed retrieving file '%s' from %s\n" +#~ msgstr "nem sikerült a(z) '%s' fájlt letölteni a %s helyről\n" + +#~ msgid "failed to copy some file" +#~ msgstr "nem sikerült néhány fájlt másolni" + +#~ msgid "database larger than maximum size\n" +#~ msgstr "az adatbázis nagyobb, mint a maximális megengedett méret\n" diff --git a/lib/libalpm/po/it.po b/lib/libalpm/po/it.po index 35a3c0ca..770c26f1 100644 --- a/lib/libalpm/po/it.po +++ b/lib/libalpm/po/it.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Arch Linux Pacman package manager\n" "Report-Msgid-Bugs-To: http://bugs.archlinux.org/index.php?project=3\n" -"POT-Creation-Date: 2011-04-18 11:23-0500\n" +"POT-Creation-Date: 2011-06-23 21:48-0500\n" "PO-Revision-Date: 2011-03-22 15:34+0000\n" "Last-Translator: giovanni <giovanni@archlinux.org>\n" "Language-Team: Italian <None>\n" @@ -158,6 +158,10 @@ msgstr "manca il metadata del pacchetto in %s\n" msgid "removing invalid file: %s\n" msgstr "rimozione del file non valido: %s\n" +#, fuzzy, c-format +msgid "could not parse package '%s' description file from db '%s'\n" +msgstr "impossibile analizzare il file di descrizione del pacchetto in %s\n" + #, c-format msgid "database path is undefined\n" msgstr "il percorso del database non è stato definito\n" @@ -226,18 +230,6 @@ msgid "failed retrieving file '%s' from %s : %s\n" msgstr "impossibile scaricare il pacchetto '%s' da %s : %s\n" #, c-format -msgid "resuming download of %s not possible; starting over\n" -msgstr "impossibile riprendere il download di %s\n" - -#, c-format -msgid "error writing to file '%s': %s\n" -msgstr "si è verificato un errore durante la scrittura nel file '%s': %s\n" - -#, c-format -msgid "failed retrieving file '%s' from %s\n" -msgstr "impossibile scaricare il pacchetto '%s' da %s\n" - -#, c-format msgid "%s appears to be truncated: %jd/%jd bytes\n" msgstr "%s sembra essere incompleto: %jd/%jd byte\n" @@ -386,6 +378,18 @@ msgid "could not find repository for target" msgstr "impossibile trovare un repository contenente questo pacchetto" #, c-format +msgid "signature directory not configured correctly" +msgstr "" + +#, c-format +msgid "invalid PGP signature" +msgstr "" + +#, c-format +msgid "unknown PGP signature" +msgstr "" + +#, c-format msgid "invalid or corrupted delta" msgstr "il delta non è valido oppure è corrotto" @@ -410,10 +414,6 @@ msgid "failed to retrieve some files" msgstr "impossibile scaricare alcuni file" #, c-format -msgid "failed to copy some file" -msgstr "impossibile copiare alcuni file" - -#, c-format msgid "invalid regular expression" msgstr "l'espressione regolare non è valida" @@ -426,6 +426,10 @@ msgid "download library error" msgstr "si è verificato un errore della libreria di download" #, c-format +msgid "gpgme error" +msgstr "" + +#, c-format msgid "error invoking external downloader" msgstr "si è verificato un errore lanciando il downloader esterno" @@ -434,11 +438,6 @@ msgid "unexpected error" msgstr "errore inaspettato" #, c-format -msgid "database larger than maximum size\n" -msgstr "" -"la grandezza del database è superiore alla dimensione massima consentita\n" - -#, c-format msgid "could not find %s in database -- skipping\n" msgstr "impossibile trovare %s nel database, sarà ignorato\n" @@ -560,3 +559,19 @@ msgstr "la cache di %s non esiste, creazione in corso...\n" msgid "couldn't create package cache, using /tmp instead\n" msgstr "" "impossibile creare la cache del pacchetto, al suo posto sarà usata /tmp\n" + +#~ msgid "resuming download of %s not possible; starting over\n" +#~ msgstr "impossibile riprendere il download di %s\n" + +#~ msgid "error writing to file '%s': %s\n" +#~ msgstr "si è verificato un errore durante la scrittura nel file '%s': %s\n" + +#~ msgid "failed retrieving file '%s' from %s\n" +#~ msgstr "impossibile scaricare il pacchetto '%s' da %s\n" + +#~ msgid "failed to copy some file" +#~ msgstr "impossibile copiare alcuni file" + +#~ msgid "database larger than maximum size\n" +#~ msgstr "" +#~ "la grandezza del database è superiore alla dimensione massima consentita\n" diff --git a/lib/libalpm/po/kk.po b/lib/libalpm/po/kk.po index f0bce740..53c5d13f 100644 --- a/lib/libalpm/po/kk.po +++ b/lib/libalpm/po/kk.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Arch Linux Pacman package manager\n" "Report-Msgid-Bugs-To: http://bugs.archlinux.org/index.php?project=3\n" -"POT-Creation-Date: 2011-04-18 11:23-0500\n" +"POT-Creation-Date: 2011-06-23 21:48-0500\n" "PO-Revision-Date: 2011-03-22 15:34+0000\n" "Last-Translator: toofishes <dpmcgee@gmail.com>\n" "Language-Team: Kazakh <None>\n" @@ -153,6 +153,10 @@ msgstr "%s ішінде дестенің мета мәліметтері жоқ\ msgid "removing invalid file: %s\n" msgstr "қате файлды өшіру: %s\n" +#, fuzzy, c-format +msgid "could not parse package '%s' description file from db '%s'\n" +msgstr "%s ішіндегі анықтама файлын зерттеу мүмкін емес\n" + #, c-format msgid "database path is undefined\n" msgstr "дерекқорға жол анықталмаған\n" @@ -218,18 +222,6 @@ msgid "failed retrieving file '%s' from %s : %s\n" msgstr "'%s' файлын %s адресінен алу қатемен аяқталды : %s\n" #, c-format -msgid "resuming download of %s not possible; starting over\n" -msgstr "%s жүктемесін жалғастыру мүмкін емес; басынан басталады\n" - -#, c-format -msgid "error writing to file '%s': %s\n" -msgstr "'%s' файлына жазу қатесі: %s\n" - -#, c-format -msgid "failed retrieving file '%s' from %s\n" -msgstr "'%s' файлын %s адресінен алу қатемен аяқталды\n" - -#, c-format msgid "%s appears to be truncated: %jd/%jd bytes\n" msgstr "%s қысқартылған сияқты: %jd/%jd байт\n" @@ -378,6 +370,18 @@ msgid "could not find repository for target" msgstr "көрсетілген мақсат үшін репозиторийді табу мүмкін емес" #, c-format +msgid "signature directory not configured correctly" +msgstr "" + +#, c-format +msgid "invalid PGP signature" +msgstr "" + +#, c-format +msgid "unknown PGP signature" +msgstr "" + +#, c-format msgid "invalid or corrupted delta" msgstr "дельта файлы қате не зақымдалған" @@ -402,10 +406,6 @@ msgid "failed to retrieve some files" msgstr "кейбір файлдарды алу сәтсіз аяқталды" #, c-format -msgid "failed to copy some file" -msgstr "кейбір файлдарды көшіру сәтсіз" - -#, c-format msgid "invalid regular expression" msgstr "тұрақты өрнек дұрыс емес" @@ -418,6 +418,10 @@ msgid "download library error" msgstr "download library қатесі орын алды" #, c-format +msgid "gpgme error" +msgstr "" + +#, c-format msgid "error invoking external downloader" msgstr "сыртқы жүктемелер менеджерін шақыру қатемен аяқталды" @@ -426,10 +430,6 @@ msgid "unexpected error" msgstr "күтпеген қате кетті" #, c-format -msgid "database larger than maximum size\n" -msgstr "дерекқор рұқсат етілген өлшемінен үлкен\n" - -#, c-format msgid "could not find %s in database -- skipping\n" msgstr "дерекқор ішінде %s табылмады -- өткізіп жібереміз\n" @@ -549,3 +549,18 @@ msgstr "%s кэші жоқ болып тұр, құрылады...\n" #, c-format msgid "couldn't create package cache, using /tmp instead\n" msgstr "дестелер кэшін құру мүмкін емес, оның орнына /tmp қолданылады\n" + +#~ msgid "resuming download of %s not possible; starting over\n" +#~ msgstr "%s жүктемесін жалғастыру мүмкін емес; басынан басталады\n" + +#~ msgid "error writing to file '%s': %s\n" +#~ msgstr "'%s' файлына жазу қатесі: %s\n" + +#~ msgid "failed retrieving file '%s' from %s\n" +#~ msgstr "'%s' файлын %s адресінен алу қатемен аяқталды\n" + +#~ msgid "failed to copy some file" +#~ msgstr "кейбір файлдарды көшіру сәтсіз" + +#~ msgid "database larger than maximum size\n" +#~ msgstr "дерекқор рұқсат етілген өлшемінен үлкен\n" diff --git a/lib/libalpm/po/libalpm.pot b/lib/libalpm/po/libalpm.pot index 768ea204..1f7d25a7 100644 --- a/lib/libalpm/po/libalpm.pot +++ b/lib/libalpm/po/libalpm.pot @@ -152,6 +152,10 @@ msgid "removing invalid file: %s\n" msgstr "" #, c-format +msgid "could not parse package '%s' description file from db '%s'\n" +msgstr "" + +#, c-format msgid "database path is undefined\n" msgstr "" @@ -216,18 +220,6 @@ msgid "failed retrieving file '%s' from %s : %s\n" msgstr "" #, c-format -msgid "resuming download of %s not possible; starting over\n" -msgstr "" - -#, c-format -msgid "error writing to file '%s': %s\n" -msgstr "" - -#, c-format -msgid "failed retrieving file '%s' from %s\n" -msgstr "" - -#, c-format msgid "%s appears to be truncated: %jd/%jd bytes\n" msgstr "" @@ -376,6 +368,18 @@ msgid "could not find repository for target" msgstr "" #, c-format +msgid "signature directory not configured correctly" +msgstr "" + +#, c-format +msgid "invalid PGP signature" +msgstr "" + +#, c-format +msgid "unknown PGP signature" +msgstr "" + +#, c-format msgid "invalid or corrupted delta" msgstr "" @@ -400,10 +404,6 @@ msgid "failed to retrieve some files" msgstr "" #, c-format -msgid "failed to copy some file" -msgstr "" - -#, c-format msgid "invalid regular expression" msgstr "" @@ -416,15 +416,15 @@ msgid "download library error" msgstr "" #, c-format -msgid "error invoking external downloader" +msgid "gpgme error" msgstr "" #, c-format -msgid "unexpected error" +msgid "error invoking external downloader" msgstr "" #, c-format -msgid "database larger than maximum size\n" +msgid "unexpected error" msgstr "" #, c-format diff --git a/lib/libalpm/po/nb.po b/lib/libalpm/po/nb.po index 9349423e..b44a3ad5 100644 --- a/lib/libalpm/po/nb.po +++ b/lib/libalpm/po/nb.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Arch Linux Pacman package manager\n" "Report-Msgid-Bugs-To: http://bugs.archlinux.org/index.php?project=3\n" -"POT-Creation-Date: 2011-04-18 11:23-0500\n" +"POT-Creation-Date: 2011-06-23 21:48-0500\n" "PO-Revision-Date: 2011-04-16 00:45+0000\n" "Last-Translator: Jonhoo <jon@thesquareplanet.com>\n" "Language-Team: Norwegian Bokmål <None>\n" @@ -153,6 +153,10 @@ msgstr "mangler metadata i %s\n" msgid "removing invalid file: %s\n" msgstr "fjerner ugyldig fil: %s\n" +#, fuzzy, c-format +msgid "could not parse package '%s' description file from db '%s'\n" +msgstr "kunne ikke analysere pakkebeskrivelse i fil %s\n" + #, c-format msgid "database path is undefined\n" msgstr "databaseplassering er udefinert\n" @@ -219,18 +223,6 @@ msgid "failed retrieving file '%s' from %s : %s\n" msgstr "mottakelse av fil '%s' fra %s : %s feilet\n" #, c-format -msgid "resuming download of %s not possible; starting over\n" -msgstr "kan ikke fortsette nedlastingen av %s; starter på nytt\n" - -#, c-format -msgid "error writing to file '%s': %s\n" -msgstr "skriving til fil '%s': %s feilet\n" - -#, c-format -msgid "failed retrieving file '%s' from %s\n" -msgstr "mottakelse av fil '%s' fra %s\n" - -#, c-format msgid "%s appears to be truncated: %jd/%jd bytes\n" msgstr "%s ser ut til å være trunkert: %jd/%jd bytes\n" @@ -379,6 +371,18 @@ msgid "could not find repository for target" msgstr "fant ikke pakkebrønn for mål" #, c-format +msgid "signature directory not configured correctly" +msgstr "" + +#, c-format +msgid "invalid PGP signature" +msgstr "" + +#, c-format +msgid "unknown PGP signature" +msgstr "" + +#, c-format msgid "invalid or corrupted delta" msgstr "invalid" @@ -403,10 +407,6 @@ msgid "failed to retrieve some files" msgstr "mottagelsen av noen filer feilet" #, c-format -msgid "failed to copy some file" -msgstr "kunne ikke kopiere en fil" - -#, c-format msgid "invalid regular expression" msgstr "ugyldig uttrykk" @@ -419,6 +419,10 @@ msgid "download library error" msgstr "feil i nedlastingsbibliotek" #, c-format +msgid "gpgme error" +msgstr "" + +#, c-format msgid "error invoking external downloader" msgstr "påkalling av ekstern nedlaster feilet" @@ -427,10 +431,6 @@ msgid "unexpected error" msgstr "uforventet feil" #, c-format -msgid "database larger than maximum size\n" -msgstr "databasen er større enn maksstørrelsen\n" - -#, c-format msgid "could not find %s in database -- skipping\n" msgstr "kunne ikke finne %s i database -- hopper over\n" @@ -549,3 +549,18 @@ msgstr "ingen %s cache eksisterer, lager en ...\n" #, c-format msgid "couldn't create package cache, using /tmp instead\n" msgstr "kunne ikke danne pakke-cache, bruker /tmp istedenfor\n" + +#~ msgid "resuming download of %s not possible; starting over\n" +#~ msgstr "kan ikke fortsette nedlastingen av %s; starter på nytt\n" + +#~ msgid "error writing to file '%s': %s\n" +#~ msgstr "skriving til fil '%s': %s feilet\n" + +#~ msgid "failed retrieving file '%s' from %s\n" +#~ msgstr "mottakelse av fil '%s' fra %s\n" + +#~ msgid "failed to copy some file" +#~ msgstr "kunne ikke kopiere en fil" + +#~ msgid "database larger than maximum size\n" +#~ msgstr "databasen er større enn maksstørrelsen\n" diff --git a/lib/libalpm/po/pl.po b/lib/libalpm/po/pl.po index 667a564c..5915d1e2 100644 --- a/lib/libalpm/po/pl.po +++ b/lib/libalpm/po/pl.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Arch Linux Pacman package manager\n" "Report-Msgid-Bugs-To: http://bugs.archlinux.org/index.php?project=3\n" -"POT-Creation-Date: 2011-04-18 11:23-0500\n" +"POT-Creation-Date: 2011-06-23 21:48-0500\n" "PO-Revision-Date: 2011-04-12 20:00+0000\n" "Last-Translator: Barthalion <barthalion@gmail.com>\n" "Language-Team: Polish <None>\n" @@ -154,6 +154,10 @@ msgstr "brak metadanych pakietu w %s\n" msgid "removing invalid file: %s\n" msgstr "usuwanie nieprawidłowego pliku: %s\n" +#, fuzzy, c-format +msgid "could not parse package '%s' description file from db '%s'\n" +msgstr "nie udało się przeczytać opisu pliku w %s\n" + #, c-format msgid "database path is undefined\n" msgstr "ścieżka bazy danych jest niezdefiniowana\n" @@ -220,18 +224,6 @@ msgid "failed retrieving file '%s' from %s : %s\n" msgstr "nie udało się pobrać pliku '%s' z %s : %s\n" #, c-format -msgid "resuming download of %s not possible; starting over\n" -msgstr "kontynuowanie pobieranie %s jest niemożliwe; zaczynam od nowa\n" - -#, c-format -msgid "error writing to file '%s': %s\n" -msgstr "Błąd podczas zapisywania do pliku '%s': %s\n" - -#, c-format -msgid "failed retrieving file '%s' from %s\n" -msgstr "nie udało się pobrać pliku '%s' z %s\n" - -#, c-format msgid "%s appears to be truncated: %jd/%jd bytes\n" msgstr "%s wygląda, jakby został obcięty %jd/%jd bajtów\n" @@ -380,6 +372,18 @@ msgid "could not find repository for target" msgstr "nie mogę znaleźć repozytorium dla celu" #, c-format +msgid "signature directory not configured correctly" +msgstr "" + +#, c-format +msgid "invalid PGP signature" +msgstr "" + +#, c-format +msgid "unknown PGP signature" +msgstr "" + +#, c-format msgid "invalid or corrupted delta" msgstr "nieprawidłowy bądź uszkodzony pakiet przyrostowy" @@ -404,10 +408,6 @@ msgid "failed to retrieve some files" msgstr "nie udało się odzyskać niektórych plików" #, c-format -msgid "failed to copy some file" -msgstr "bład kopiowania niektórych plików" - -#, c-format msgid "invalid regular expression" msgstr "nieprawidłowe wyrażenie regularne" @@ -420,6 +420,10 @@ msgid "download library error" msgstr "błąd pobierania biblioteki" #, c-format +msgid "gpgme error" +msgstr "" + +#, c-format msgid "error invoking external downloader" msgstr "" "wystąpił błąd podczas odwoływania się do zewnętrznego programu pobierającego" @@ -429,10 +433,6 @@ msgid "unexpected error" msgstr "niespodziewany błąd" #, c-format -msgid "database larger than maximum size\n" -msgstr "baza danych jest większa, niż maksymalny rozmiar\n" - -#, c-format msgid "could not find %s in database -- skipping\n" msgstr "nie udało się odnaleźć %s w bazie danych -- pomijanie\n" @@ -552,3 +552,18 @@ msgstr "brak pamięci podręcznej dla %s, tworzenie...\n" msgid "couldn't create package cache, using /tmp instead\n" msgstr "" "nie udało się stworzyć pamięci podręcznej pakietu, używanie /tmp w zamian\n" + +#~ msgid "resuming download of %s not possible; starting over\n" +#~ msgstr "kontynuowanie pobieranie %s jest niemożliwe; zaczynam od nowa\n" + +#~ msgid "error writing to file '%s': %s\n" +#~ msgstr "Błąd podczas zapisywania do pliku '%s': %s\n" + +#~ msgid "failed retrieving file '%s' from %s\n" +#~ msgstr "nie udało się pobrać pliku '%s' z %s\n" + +#~ msgid "failed to copy some file" +#~ msgstr "bład kopiowania niektórych plików" + +#~ msgid "database larger than maximum size\n" +#~ msgstr "baza danych jest większa, niż maksymalny rozmiar\n" diff --git a/lib/libalpm/po/pt.po b/lib/libalpm/po/pt.po index 0d936bcd..3a82710e 100644 --- a/lib/libalpm/po/pt.po +++ b/lib/libalpm/po/pt.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Arch Linux Pacman package manager\n" "Report-Msgid-Bugs-To: http://bugs.archlinux.org/index.php?project=3\n" -"POT-Creation-Date: 2011-04-18 11:23-0500\n" +"POT-Creation-Date: 2011-06-23 21:48-0500\n" "PO-Revision-Date: 2011-04-16 01:24+0000\n" "Last-Translator: ArchGalileu <omeuviolino@gmail.com>\n" "Language-Team: Portuguese <>\n" @@ -154,6 +154,10 @@ msgstr "em falta metadados do pacote em %s\n" msgid "removing invalid file: %s\n" msgstr "a remover ficheiro inválido: %s\n" +#, fuzzy, c-format +msgid "could not parse package '%s' description file from db '%s'\n" +msgstr "não foi possível interpretar o ficheiro de descrição do pacote em %s\n" + #, c-format msgid "database path is undefined\n" msgstr "localização da base de dados não definida\n" @@ -223,18 +227,6 @@ msgid "failed retrieving file '%s' from %s : %s\n" msgstr "falha ao obter ficheiro '%s' de %s : %s\n" #, c-format -msgid "resuming download of %s not possible; starting over\n" -msgstr "não foi possível retomar a descarga de %s; a reiniciar a descarga\n" - -#, c-format -msgid "error writing to file '%s': %s\n" -msgstr "erro ao escrever no ficheiro '%s': %s\n" - -#, c-format -msgid "failed retrieving file '%s' from %s\n" -msgstr "falha ao obter o ficheiro '%s' de %s\n" - -#, c-format msgid "%s appears to be truncated: %jd/%jd bytes\n" msgstr "%s parece estar quebrado: %jd/%jd bytes\n" @@ -383,6 +375,18 @@ msgid "could not find repository for target" msgstr "não foi possível encontrar o repositório para o pacote" #, c-format +msgid "signature directory not configured correctly" +msgstr "" + +#, c-format +msgid "invalid PGP signature" +msgstr "" + +#, c-format +msgid "unknown PGP signature" +msgstr "" + +#, c-format msgid "invalid or corrupted delta" msgstr "delta inválido ou corrompido" @@ -407,10 +411,6 @@ msgid "failed to retrieve some files" msgstr "falha ao descarregar alguns ficheiros" #, c-format -msgid "failed to copy some file" -msgstr "falhou ao copiar algum ficheiro" - -#, c-format msgid "invalid regular expression" msgstr "expressão regular inválida" @@ -423,6 +423,10 @@ msgid "download library error" msgstr "erro na biblioteca de descargas" #, c-format +msgid "gpgme error" +msgstr "" + +#, c-format msgid "error invoking external downloader" msgstr "erro ao invocar o programa de descargas externo" @@ -431,10 +435,6 @@ msgid "unexpected error" msgstr "erro inesperado" #, c-format -msgid "database larger than maximum size\n" -msgstr "a base de dados é maior que o tamanho máximo\n" - -#, c-format msgid "could not find %s in database -- skipping\n" msgstr "não foi possível encontrar %s na base de dados - a ignorar\n" @@ -554,3 +554,18 @@ msgstr "cache %s não existe, a criar...\n" msgid "couldn't create package cache, using /tmp instead\n" msgstr "" "não foi possível criar cache de pacotes, a usar /tmp como alternativa\n" + +#~ msgid "resuming download of %s not possible; starting over\n" +#~ msgstr "não foi possível retomar a descarga de %s; a reiniciar a descarga\n" + +#~ msgid "error writing to file '%s': %s\n" +#~ msgstr "erro ao escrever no ficheiro '%s': %s\n" + +#~ msgid "failed retrieving file '%s' from %s\n" +#~ msgstr "falha ao obter o ficheiro '%s' de %s\n" + +#~ msgid "failed to copy some file" +#~ msgstr "falhou ao copiar algum ficheiro" + +#~ msgid "database larger than maximum size\n" +#~ msgstr "a base de dados é maior que o tamanho máximo\n" diff --git a/lib/libalpm/po/pt_BR.po b/lib/libalpm/po/pt_BR.po index 14815650..d2980e94 100644 --- a/lib/libalpm/po/pt_BR.po +++ b/lib/libalpm/po/pt_BR.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Arch Linux Pacman package manager\n" "Report-Msgid-Bugs-To: http://bugs.archlinux.org/index.php?project=3\n" -"POT-Creation-Date: 2011-04-18 11:23-0500\n" +"POT-Creation-Date: 2011-06-23 21:48-0500\n" "PO-Revision-Date: 2011-04-12 02:29+0000\n" "Last-Translator: ambaratti <ambaratti.listas@gmail.com>\n" "Language-Team: Portuguese (Brazilian) <None>\n" @@ -155,6 +155,10 @@ msgstr "faltando metadados do pacote em %s\n" msgid "removing invalid file: %s\n" msgstr "removendo arquivo inválido: %s\n" +#, fuzzy, c-format +msgid "could not parse package '%s' description file from db '%s'\n" +msgstr "não foi possível interpretar o arquivo de descrição do pacote em %s\n" + #, c-format msgid "database path is undefined\n" msgstr "caminho da base de dados não definido\n" @@ -223,18 +227,6 @@ msgid "failed retrieving file '%s' from %s : %s\n" msgstr "falha ao obter o arquivo '%s' de %s : %s\n" #, c-format -msgid "resuming download of %s not possible; starting over\n" -msgstr "não foi possível retomar o download de %s; começando de novo\n" - -#, c-format -msgid "error writing to file '%s': %s\n" -msgstr "erro ao escrever no arquivo '%s': %s\n" - -#, c-format -msgid "failed retrieving file '%s' from %s\n" -msgstr "falha ao obter arquivo '%s' de %s\n" - -#, c-format msgid "%s appears to be truncated: %jd/%jd bytes\n" msgstr "%s parece estar truncado: %jd/%jd bytes\n" @@ -383,6 +375,18 @@ msgid "could not find repository for target" msgstr "não foi possível encontrar o repositório para o pacote" #, c-format +msgid "signature directory not configured correctly" +msgstr "" + +#, c-format +msgid "invalid PGP signature" +msgstr "" + +#, c-format +msgid "unknown PGP signature" +msgstr "" + +#, c-format msgid "invalid or corrupted delta" msgstr "delta inválido ou corrompido" @@ -407,10 +411,6 @@ msgid "failed to retrieve some files" msgstr "falha ao obter alguns arquivos" #, c-format -msgid "failed to copy some file" -msgstr "falha ao copiar algum arquivo" - -#, c-format msgid "invalid regular expression" msgstr "expressão regular inválida" @@ -423,6 +423,10 @@ msgid "download library error" msgstr "erro na biblioteca de download" #, c-format +msgid "gpgme error" +msgstr "" + +#, c-format msgid "error invoking external downloader" msgstr "erro ao chamar o programa de download externo" @@ -431,10 +435,6 @@ msgid "unexpected error" msgstr "erro inesperado" #, c-format -msgid "database larger than maximum size\n" -msgstr "banco de dados maior que o tamanho máximo\n" - -#, c-format msgid "could not find %s in database -- skipping\n" msgstr "não foi possível encontrar %s na base de dados -- ignorando\n" @@ -553,3 +553,18 @@ msgstr "cache %s não existe, criando...\n" #, c-format msgid "couldn't create package cache, using /tmp instead\n" msgstr "não foi possível criar cache de pacotes, usando /tmp em seu lugar\n" + +#~ msgid "resuming download of %s not possible; starting over\n" +#~ msgstr "não foi possível retomar o download de %s; começando de novo\n" + +#~ msgid "error writing to file '%s': %s\n" +#~ msgstr "erro ao escrever no arquivo '%s': %s\n" + +#~ msgid "failed retrieving file '%s' from %s\n" +#~ msgstr "falha ao obter arquivo '%s' de %s\n" + +#~ msgid "failed to copy some file" +#~ msgstr "falha ao copiar algum arquivo" + +#~ msgid "database larger than maximum size\n" +#~ msgstr "banco de dados maior que o tamanho máximo\n" diff --git a/lib/libalpm/po/ro.po b/lib/libalpm/po/ro.po index cd83cc66..f3d7bec2 100644 --- a/lib/libalpm/po/ro.po +++ b/lib/libalpm/po/ro.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Arch Linux Pacman package manager\n" "Report-Msgid-Bugs-To: http://bugs.archlinux.org/index.php?project=3\n" -"POT-Creation-Date: 2011-04-18 11:23-0500\n" +"POT-Creation-Date: 2011-06-23 21:48-0500\n" "PO-Revision-Date: 2011-03-22 15:34+0000\n" "Last-Translator: wonder <ibiru@archlinux.org>\n" "Language-Team: Romanian <>\n" @@ -159,6 +159,10 @@ msgstr "lipsă metadate pentru pachet în %s\n" msgid "removing invalid file: %s\n" msgstr "se elimină fișierul nevalid: %s\n" +#, fuzzy, c-format +msgid "could not parse package '%s' description file from db '%s'\n" +msgstr "nu a putut fi analizat fișierul de descriere a pachetului în %s\n" + #, c-format msgid "database path is undefined\n" msgstr "calea bazei de date este nedefinită\n" @@ -225,20 +229,6 @@ msgid "failed retrieving file '%s' from %s : %s\n" msgstr "eșec la obținerea fișierului '%s' din %s : %s\n" #, c-format -msgid "resuming download of %s not possible; starting over\n" -msgstr "" -"nu se poate relua descărcarea pentru %s; se reîncepe\n" -"\n" - -#, c-format -msgid "error writing to file '%s': %s\n" -msgstr "eroare la scriere în fișierul '%s': %s\n" - -#, c-format -msgid "failed retrieving file '%s' from %s\n" -msgstr "eșec la obținerea fișierului '%s' din %s\n" - -#, c-format msgid "%s appears to be truncated: %jd/%jd bytes\n" msgstr "%s pare a fi trunchiat: %jd/%jd bytes\n" @@ -387,6 +377,18 @@ msgid "could not find repository for target" msgstr "depozitul pentru țintă nu poate fi găsit" #, c-format +msgid "signature directory not configured correctly" +msgstr "" + +#, c-format +msgid "invalid PGP signature" +msgstr "" + +#, c-format +msgid "unknown PGP signature" +msgstr "" + +#, c-format msgid "invalid or corrupted delta" msgstr "delta invalid sau corupt" @@ -411,10 +413,6 @@ msgid "failed to retrieve some files" msgstr "eșec în obținerea unor fișiere" #, c-format -msgid "failed to copy some file" -msgstr "copierea unui fișier a eșuat" - -#, c-format msgid "invalid regular expression" msgstr "expresie regulată nevalidă" @@ -427,6 +425,10 @@ msgid "download library error" msgstr "eroare în biblioteca de descărcare" #, c-format +msgid "gpgme error" +msgstr "" + +#, c-format msgid "error invoking external downloader" msgstr "eroare la invocarea descărcătorului extern" @@ -435,10 +437,6 @@ msgid "unexpected error" msgstr "eroare neașteptată" #, c-format -msgid "database larger than maximum size\n" -msgstr "baza de date e mai mare decât dimensiunea maximă\n" - -#, c-format msgid "could not find %s in database -- skipping\n" msgstr "nu poate fi găsit %s în baza de date -- se omite\n" @@ -557,3 +555,20 @@ msgstr "nu există cache %s, se crează...\n" #, c-format msgid "couldn't create package cache, using /tmp instead\n" msgstr "nu se poate crea cache pachet, se folosește /tmp în schimb\n" + +#~ msgid "resuming download of %s not possible; starting over\n" +#~ msgstr "" +#~ "nu se poate relua descărcarea pentru %s; se reîncepe\n" +#~ "\n" + +#~ msgid "error writing to file '%s': %s\n" +#~ msgstr "eroare la scriere în fișierul '%s': %s\n" + +#~ msgid "failed retrieving file '%s' from %s\n" +#~ msgstr "eșec la obținerea fișierului '%s' din %s\n" + +#~ msgid "failed to copy some file" +#~ msgstr "copierea unui fișier a eșuat" + +#~ msgid "database larger than maximum size\n" +#~ msgstr "baza de date e mai mare decât dimensiunea maximă\n" diff --git a/lib/libalpm/po/ru.po b/lib/libalpm/po/ru.po index c56b6fd0..93f8a7e2 100644 --- a/lib/libalpm/po/ru.po +++ b/lib/libalpm/po/ru.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Arch Linux Pacman package manager\n" "Report-Msgid-Bugs-To: http://bugs.archlinux.org/index.php?project=3\n" -"POT-Creation-Date: 2011-04-18 11:23-0500\n" +"POT-Creation-Date: 2011-06-23 21:48-0500\n" "PO-Revision-Date: 2011-04-13 14:50+0000\n" "Last-Translator: vdk <vdk@gmx.us>\n" "Language-Team: Russian <None>\n" @@ -156,6 +156,10 @@ msgstr "отсутствуют метаданные пакета в %s\n" msgid "removing invalid file: %s\n" msgstr "удаляется ошибочный файл: %s\n" +#, fuzzy, c-format +msgid "could not parse package '%s' description file from db '%s'\n" +msgstr "не удалось проанализировать файл с описанием пакета в %s\n" + #, c-format msgid "database path is undefined\n" msgstr "путь к базе данных не определён\n" @@ -223,18 +227,6 @@ msgid "failed retrieving file '%s' from %s : %s\n" msgstr "не удалось получить файл '%s' из %s : %s\n" #, c-format -msgid "resuming download of %s not possible; starting over\n" -msgstr "не удалось продолжить закачку %s; начинаю заново\n" - -#, c-format -msgid "error writing to file '%s': %s\n" -msgstr "ошибка записи в файл '%s': %s\n" - -#, c-format -msgid "failed retrieving file '%s' from %s\n" -msgstr "не удалось получить файл '%s' из %s\n" - -#, c-format msgid "%s appears to be truncated: %jd/%jd bytes\n" msgstr "%s, видимо, обрезан: %jd/%jd байт\n" @@ -383,6 +375,18 @@ msgid "could not find repository for target" msgstr "не удалось репозиторий для цели" #, c-format +msgid "signature directory not configured correctly" +msgstr "" + +#, c-format +msgid "invalid PGP signature" +msgstr "" + +#, c-format +msgid "unknown PGP signature" +msgstr "" + +#, c-format msgid "invalid or corrupted delta" msgstr "ошибка или повреждение в дельте" @@ -407,10 +411,6 @@ msgid "failed to retrieve some files" msgstr "не удалось получить некоторые файлы" #, c-format -msgid "failed to copy some file" -msgstr "не удалось скопировать некоторые файлы" - -#, c-format msgid "invalid regular expression" msgstr "неверное регулярное выражение" @@ -423,6 +423,10 @@ msgid "download library error" msgstr "ошибка в библиотеке загрузки" #, c-format +msgid "gpgme error" +msgstr "" + +#, c-format msgid "error invoking external downloader" msgstr "ошибка вызова внешнего менеджера загрузки" @@ -431,10 +435,6 @@ msgid "unexpected error" msgstr "непредвиденная ошибка" #, c-format -msgid "database larger than maximum size\n" -msgstr "база данных больше максимального размера\n" - -#, c-format msgid "could not find %s in database -- skipping\n" msgstr "не удалось найти %s в базе данных -- пропускается\n" @@ -553,3 +553,18 @@ msgstr "кэш %s не существует, создается...\n" #, c-format msgid "couldn't create package cache, using /tmp instead\n" msgstr "не удалось создать кэш пакетов, будет использован /tmp\n" + +#~ msgid "resuming download of %s not possible; starting over\n" +#~ msgstr "не удалось продолжить закачку %s; начинаю заново\n" + +#~ msgid "error writing to file '%s': %s\n" +#~ msgstr "ошибка записи в файл '%s': %s\n" + +#~ msgid "failed retrieving file '%s' from %s\n" +#~ msgstr "не удалось получить файл '%s' из %s\n" + +#~ msgid "failed to copy some file" +#~ msgstr "не удалось скопировать некоторые файлы" + +#~ msgid "database larger than maximum size\n" +#~ msgstr "база данных больше максимального размера\n" diff --git a/lib/libalpm/po/sk.po b/lib/libalpm/po/sk.po index 55f18e75..7efec81a 100644 --- a/lib/libalpm/po/sk.po +++ b/lib/libalpm/po/sk.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Arch Linux Pacman package manager\n" "Report-Msgid-Bugs-To: http://bugs.archlinux.org/index.php?project=3\n" -"POT-Creation-Date: 2011-04-18 11:23-0500\n" +"POT-Creation-Date: 2011-06-23 21:48-0500\n" "PO-Revision-Date: 2011-04-17 10:09+0000\n" "Last-Translator: jose1711 <jose1711@gmail.com>\n" "Language-Team: Slovak <None>\n" @@ -153,6 +153,10 @@ msgstr "chýbaju metadáta balíčka v %s\n" msgid "removing invalid file: %s\n" msgstr "odstraňujem neplatný súbor: %s\n" +#, fuzzy, c-format +msgid "could not parse package '%s' description file from db '%s'\n" +msgstr "nie je možné spracovať súbor s popisom balíčka v %s\n" + #, c-format msgid "database path is undefined\n" msgstr "cesta k databáze nie je definovaná\n" @@ -219,18 +223,6 @@ msgid "failed retrieving file '%s' from %s : %s\n" msgstr "chyba pri získavaní súboru '%s' z %s: %s\n" #, c-format -msgid "resuming download of %s not possible; starting over\n" -msgstr "nie je možné pokračovať v sťahovaní %s, začínam sťahovať od začiatku\n" - -#, c-format -msgid "error writing to file '%s': %s\n" -msgstr "chyba pri zápisu do súboru '%s': %s\n" - -#, c-format -msgid "failed retrieving file '%s' from %s\n" -msgstr "zlyhalo získanie súboru '%s' z %s\n" - -#, c-format msgid "%s appears to be truncated: %jd/%jd bytes\n" msgstr "%s vyzerá byť skrátený: %jd/%jd bytov\n" @@ -379,6 +371,18 @@ msgid "could not find repository for target" msgstr "nie je možné nájsť repozitár cieľa" #, c-format +msgid "signature directory not configured correctly" +msgstr "" + +#, c-format +msgid "invalid PGP signature" +msgstr "" + +#, c-format +msgid "unknown PGP signature" +msgstr "" + +#, c-format msgid "invalid or corrupted delta" msgstr "neplatný alebo poškodený delta rozdiel" @@ -403,10 +407,6 @@ msgid "failed to retrieve some files" msgstr "chyba pri získavaní niektorých súborov" #, c-format -msgid "failed to copy some file" -msgstr "nepodarilo sa skopírovať súbor" - -#, c-format msgid "invalid regular expression" msgstr "neplatný regulárny výraz" @@ -419,6 +419,10 @@ msgid "download library error" msgstr "chyba knižnice pre sťahovanie súborov" #, c-format +msgid "gpgme error" +msgstr "" + +#, c-format msgid "error invoking external downloader" msgstr "chyba volania externého programu pre sťahovanie súborov" @@ -427,10 +431,6 @@ msgid "unexpected error" msgstr "neočakávaná chyba" #, c-format -msgid "database larger than maximum size\n" -msgstr "databáza väčšia ako maximálna veľkosť\n" - -#, c-format msgid "could not find %s in database -- skipping\n" msgstr "nie je možné nájsť %s v databáze -- preskakujem\n" @@ -549,3 +549,19 @@ msgstr "neexistuje cache %s, vytváram...\n" #, c-format msgid "couldn't create package cache, using /tmp instead\n" msgstr "nie je možné vytvoriť cache balíčkov, použijem /tmp\n" + +#~ msgid "resuming download of %s not possible; starting over\n" +#~ msgstr "" +#~ "nie je možné pokračovať v sťahovaní %s, začínam sťahovať od začiatku\n" + +#~ msgid "error writing to file '%s': %s\n" +#~ msgstr "chyba pri zápisu do súboru '%s': %s\n" + +#~ msgid "failed retrieving file '%s' from %s\n" +#~ msgstr "zlyhalo získanie súboru '%s' z %s\n" + +#~ msgid "failed to copy some file" +#~ msgstr "nepodarilo sa skopírovať súbor" + +#~ msgid "database larger than maximum size\n" +#~ msgstr "databáza väčšia ako maximálna veľkosť\n" diff --git a/lib/libalpm/po/sr.po b/lib/libalpm/po/sr.po index 463c66b1..4d154eba 100644 --- a/lib/libalpm/po/sr.po +++ b/lib/libalpm/po/sr.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Arch Linux Pacman package manager\n" "Report-Msgid-Bugs-To: http://bugs.archlinux.org/index.php?project=3\n" -"POT-Creation-Date: 2011-04-18 11:23-0500\n" +"POT-Creation-Date: 2011-06-23 21:48-0500\n" "PO-Revision-Date: 2011-03-22 15:34+0000\n" "Last-Translator: Xabre <githzerai06@gmail.com>\n" "Language-Team: Serbian <None>\n" @@ -154,6 +154,10 @@ msgstr "недостају метаподаци пакета %s\n" msgid "removing invalid file: %s\n" msgstr "уклањам неисправан фајл: %s\n" +#, fuzzy, c-format +msgid "could not parse package '%s' description file from db '%s'\n" +msgstr "не могу да обрадим фајл описа пакета у %s\n" + #, c-format msgid "database path is undefined\n" msgstr "путања базе није одређена\n" @@ -220,18 +224,6 @@ msgid "failed retrieving file '%s' from %s : %s\n" msgstr "неуспешно преузимање фајла „%s“ са „%s“: %s\n" #, c-format -msgid "resuming download of %s not possible; starting over\n" -msgstr "настављање преузимања %s није могуће: започињем изнова\n" - -#, c-format -msgid "error writing to file '%s': %s\n" -msgstr "грешка при упису у фајл „%s“: %s\n" - -#, c-format -msgid "failed retrieving file '%s' from %s\n" -msgstr "неуспешно преузимање фајла „%s“ са %s\n" - -#, c-format msgid "%s appears to be truncated: %jd/%jd bytes\n" msgstr "изгледа да је %s окрњен: %jd/%jd бајтова\n" @@ -380,6 +372,18 @@ msgid "could not find repository for target" msgstr "не могу да нађем ризницу циља" #, c-format +msgid "signature directory not configured correctly" +msgstr "" + +#, c-format +msgid "invalid PGP signature" +msgstr "" + +#, c-format +msgid "unknown PGP signature" +msgstr "" + +#, c-format msgid "invalid or corrupted delta" msgstr "неисправна или покварена делта" @@ -404,10 +408,6 @@ msgid "failed to retrieve some files" msgstr "неуспешно преузимање неких фајлова" #, c-format -msgid "failed to copy some file" -msgstr "грешка при копирању фајла" - -#, c-format msgid "invalid regular expression" msgstr "неисправан регуларни израз" @@ -420,6 +420,10 @@ msgid "download library error" msgstr "грешка у библиотеци преузимања" #, c-format +msgid "gpgme error" +msgstr "" + +#, c-format msgid "error invoking external downloader" msgstr "грешка при покретању спољног програма за преузимање" @@ -428,10 +432,6 @@ msgid "unexpected error" msgstr "неочекивана грешка" #, c-format -msgid "database larger than maximum size\n" -msgstr "база је већа од максималне величине\n" - -#, c-format msgid "could not find %s in database -- skipping\n" msgstr "не могу да нађем %s у бази — прескачем\n" @@ -550,3 +550,18 @@ msgstr "не постоји кеш за %s; правим....\n" #, c-format msgid "couldn't create package cache, using /tmp instead\n" msgstr "не могу да направим кеш пакета; користим /tmp као замену\n" + +#~ msgid "resuming download of %s not possible; starting over\n" +#~ msgstr "настављање преузимања %s није могуће: започињем изнова\n" + +#~ msgid "error writing to file '%s': %s\n" +#~ msgstr "грешка при упису у фајл „%s“: %s\n" + +#~ msgid "failed retrieving file '%s' from %s\n" +#~ msgstr "неуспешно преузимање фајла „%s“ са %s\n" + +#~ msgid "failed to copy some file" +#~ msgstr "грешка при копирању фајла" + +#~ msgid "database larger than maximum size\n" +#~ msgstr "база је већа од максималне величине\n" diff --git a/lib/libalpm/po/sr@latin.po b/lib/libalpm/po/sr@latin.po index b2df9f68..8c1d15cc 100644 --- a/lib/libalpm/po/sr@latin.po +++ b/lib/libalpm/po/sr@latin.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Arch Linux Pacman package manager\n" "Report-Msgid-Bugs-To: http://bugs.archlinux.org/index.php?project=3\n" -"POT-Creation-Date: 2011-04-18 11:23-0500\n" +"POT-Creation-Date: 2011-06-23 21:48-0500\n" "PO-Revision-Date: 2011-03-22 15:34+0000\n" "Last-Translator: Xabre <githzerai06@gmail.com>\n" "Language-Team: Serbian (Latin) <None>\n" @@ -154,6 +154,10 @@ msgstr "nedostaju metapodaci paketa %s\n" msgid "removing invalid file: %s\n" msgstr "uklanjam neispravan fajl: %s\n" +#, fuzzy, c-format +msgid "could not parse package '%s' description file from db '%s'\n" +msgstr "ne mogu da obradim fajl opisa paketa u %s\n" + #, c-format msgid "database path is undefined\n" msgstr "putanja baze nije određena\n" @@ -220,18 +224,6 @@ msgid "failed retrieving file '%s' from %s : %s\n" msgstr "neuspešno preuzimanje fajla „%s“ sa „%s“: %s\n" #, c-format -msgid "resuming download of %s not possible; starting over\n" -msgstr "nastavljanje preuzimanja %s nije moguće: započinjem iznova\n" - -#, c-format -msgid "error writing to file '%s': %s\n" -msgstr "greška pri upisu u fajl „%s“: %s\n" - -#, c-format -msgid "failed retrieving file '%s' from %s\n" -msgstr "neuspešno preuzimanje fajla „%s“ sa %s\n" - -#, c-format msgid "%s appears to be truncated: %jd/%jd bytes\n" msgstr "izgleda da je %s okrnjen: %jd/%jd bajtova\n" @@ -380,6 +372,18 @@ msgid "could not find repository for target" msgstr "ne mogu da nađem riznicu cilja" #, c-format +msgid "signature directory not configured correctly" +msgstr "" + +#, c-format +msgid "invalid PGP signature" +msgstr "" + +#, c-format +msgid "unknown PGP signature" +msgstr "" + +#, c-format msgid "invalid or corrupted delta" msgstr "neispravna ili pokvarena delta" @@ -404,10 +408,6 @@ msgid "failed to retrieve some files" msgstr "neuspešno preuzimanje nekih fajlova" #, c-format -msgid "failed to copy some file" -msgstr "greška pri kopiranju fajla" - -#, c-format msgid "invalid regular expression" msgstr "neispravan regularni izraz" @@ -420,6 +420,10 @@ msgid "download library error" msgstr "greška u biblioteci preuzimanja" #, c-format +msgid "gpgme error" +msgstr "" + +#, c-format msgid "error invoking external downloader" msgstr "greška pri pokretanju spoljnog programa za preuzimanje" @@ -428,10 +432,6 @@ msgid "unexpected error" msgstr "neočekivana greška" #, c-format -msgid "database larger than maximum size\n" -msgstr "baza je veća od maksimalne veličine\n" - -#, c-format msgid "could not find %s in database -- skipping\n" msgstr "ne mogu da nađem %s u bazi — preskačem\n" @@ -550,3 +550,18 @@ msgstr "ne postoji keš za %s; pravim....\n" #, c-format msgid "couldn't create package cache, using /tmp instead\n" msgstr "ne mogu da napravim keš paketa; koristim /tmp kao zamenu\n" + +#~ msgid "resuming download of %s not possible; starting over\n" +#~ msgstr "nastavljanje preuzimanja %s nije moguće: započinjem iznova\n" + +#~ msgid "error writing to file '%s': %s\n" +#~ msgstr "greška pri upisu u fajl „%s“: %s\n" + +#~ msgid "failed retrieving file '%s' from %s\n" +#~ msgstr "neuspešno preuzimanje fajla „%s“ sa %s\n" + +#~ msgid "failed to copy some file" +#~ msgstr "greška pri kopiranju fajla" + +#~ msgid "database larger than maximum size\n" +#~ msgstr "baza je veća od maksimalne veličine\n" diff --git a/lib/libalpm/po/sv.po b/lib/libalpm/po/sv.po index ff6837ea..0d43caec 100644 --- a/lib/libalpm/po/sv.po +++ b/lib/libalpm/po/sv.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Arch Linux Pacman package manager\n" "Report-Msgid-Bugs-To: http://bugs.archlinux.org/index.php?project=3\n" -"POT-Creation-Date: 2011-04-18 11:23-0500\n" +"POT-Creation-Date: 2011-06-23 21:48-0500\n" "PO-Revision-Date: 2011-03-22 15:34+0000\n" "Last-Translator: toofishes <dpmcgee@gmail.com>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -153,6 +153,10 @@ msgstr "saknar metadata för paketet i %s\n" msgid "removing invalid file: %s\n" msgstr "" +#, fuzzy, c-format +msgid "could not parse package '%s' description file from db '%s'\n" +msgstr "kunde inte analysera paketbeskrivningen i %s\n" + #, c-format msgid "database path is undefined\n" msgstr "sökväg till databasen är odefinierad\n" @@ -218,18 +222,6 @@ msgid "failed retrieving file '%s' from %s : %s\n" msgstr "misslyckades hämta filen '%s' från %s : %s\n" #, c-format -msgid "resuming download of %s not possible; starting over\n" -msgstr "kan inte återuppta nerladdning av %s, börjar om\n" - -#, c-format -msgid "error writing to file '%s': %s\n" -msgstr "fel vid skrivning till filen '%s': %s\n" - -#, c-format -msgid "failed retrieving file '%s' from %s\n" -msgstr "misslyckades hämta filen '%s' från %s\n" - -#, c-format msgid "%s appears to be truncated: %jd/%jd bytes\n" msgstr "%s verkar vara trunkerad: %jd/%jd bytes\n" @@ -378,6 +370,18 @@ msgid "could not find repository for target" msgstr "givet förråd finns inte" #, c-format +msgid "signature directory not configured correctly" +msgstr "" + +#, c-format +msgid "invalid PGP signature" +msgstr "" + +#, c-format +msgid "unknown PGP signature" +msgstr "" + +#, c-format msgid "invalid or corrupted delta" msgstr "ogiltig eller korrupt delta" @@ -402,10 +406,6 @@ msgid "failed to retrieve some files" msgstr "misslyckades att hämta några filer" #, c-format -msgid "failed to copy some file" -msgstr "" - -#, c-format msgid "invalid regular expression" msgstr "ogiltigt vanligt uttryck" @@ -418,6 +418,10 @@ msgid "download library error" msgstr "fel vid nerladdning av bibliotek" #, c-format +msgid "gpgme error" +msgstr "" + +#, c-format msgid "error invoking external downloader" msgstr "fel vid anrop av extern nerladdare" @@ -426,10 +430,6 @@ msgid "unexpected error" msgstr "oväntat fel" #, c-format -msgid "database larger than maximum size\n" -msgstr "" - -#, c-format msgid "could not find %s in database -- skipping\n" msgstr "kunde inte hitta %s i databasen -- hoppar över\n" @@ -548,3 +548,12 @@ msgstr "ingen %s cache existerar, skapar...\n" #, c-format msgid "couldn't create package cache, using /tmp instead\n" msgstr "kunde inte skapa paket-cache, använder /tmp istället\n" + +#~ msgid "resuming download of %s not possible; starting over\n" +#~ msgstr "kan inte återuppta nerladdning av %s, börjar om\n" + +#~ msgid "error writing to file '%s': %s\n" +#~ msgstr "fel vid skrivning till filen '%s': %s\n" + +#~ msgid "failed retrieving file '%s' from %s\n" +#~ msgstr "misslyckades hämta filen '%s' från %s\n" diff --git a/lib/libalpm/po/tr.po b/lib/libalpm/po/tr.po index 9305fc47..b90edf50 100644 --- a/lib/libalpm/po/tr.po +++ b/lib/libalpm/po/tr.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Arch Linux Pacman package manager\n" "Report-Msgid-Bugs-To: http://bugs.archlinux.org/index.php?project=3\n" -"POT-Creation-Date: 2011-04-18 11:23-0500\n" +"POT-Creation-Date: 2011-06-23 21:48-0500\n" "PO-Revision-Date: 2011-03-22 15:34+0000\n" "Last-Translator: ras0ir <ras0ir@eventualis.org>\n" "Language-Team: Turkish <None>\n" @@ -153,6 +153,10 @@ msgstr "%s içerisinde eksik paket bilgisi\n" msgid "removing invalid file: %s\n" msgstr "silinen geçersiz dosya: %s\n" +#, fuzzy, c-format +msgid "could not parse package '%s' description file from db '%s'\n" +msgstr "%s içerisindeki paket açıklama dosyası ayrıştırılamadı\n" + #, c-format msgid "database path is undefined\n" msgstr "veritabanı yolu belirtilmemiş\n" @@ -218,18 +222,6 @@ msgid "failed retrieving file '%s' from %s : %s\n" msgstr "%3$s hatası nedeniyle '%1$s' dosyası %2$s adresinden alınamadı\n" #, c-format -msgid "resuming download of %s not possible; starting over\n" -msgstr "%s için indirme işlemine devam edilemiyor, baştan başlanıyor\n" - -#, c-format -msgid "error writing to file '%s': %s\n" -msgstr "'%s' dosyasına yazılamıyor: %s\n" - -#, c-format -msgid "failed retrieving file '%s' from %s\n" -msgstr "%s dosyası %s adresinden alınamadı\n" - -#, c-format msgid "%s appears to be truncated: %jd/%jd bytes\n" msgstr "%s eksik görünüyor: %jd/%jd bayt\n" @@ -378,6 +370,18 @@ msgid "could not find repository for target" msgstr "hedef için depo bulunamadı" #, c-format +msgid "signature directory not configured correctly" +msgstr "" + +#, c-format +msgid "invalid PGP signature" +msgstr "" + +#, c-format +msgid "unknown PGP signature" +msgstr "" + +#, c-format msgid "invalid or corrupted delta" msgstr "geçersiz ya da bozuk veri" @@ -402,10 +406,6 @@ msgid "failed to retrieve some files" msgstr "bazı dosyalar alınamadı" #, c-format -msgid "failed to copy some file" -msgstr "bazı dosyalar kopyalanamadı" - -#, c-format msgid "invalid regular expression" msgstr "geçersiz düzenli ifade" @@ -418,6 +418,10 @@ msgid "download library error" msgstr "indirme kütüphanesi hatası" #, c-format +msgid "gpgme error" +msgstr "" + +#, c-format msgid "error invoking external downloader" msgstr "harici indiriciyi çağırırken hata oluştu" @@ -426,10 +430,6 @@ msgid "unexpected error" msgstr "beklenmedik hata" #, c-format -msgid "database larger than maximum size\n" -msgstr "veritabanı maksimum boyuttan daha büyük\n" - -#, c-format msgid "could not find %s in database -- skipping\n" msgstr "%s veritabanında bulunamadı -- atlanıyor\n" @@ -549,3 +549,18 @@ msgstr "%s önbelleği yok, oluşturuluyor...\n" #, c-format msgid "couldn't create package cache, using /tmp instead\n" msgstr "paket önbelleği oluşturulamadı, /tmp kullanılacak\n" + +#~ msgid "resuming download of %s not possible; starting over\n" +#~ msgstr "%s için indirme işlemine devam edilemiyor, baştan başlanıyor\n" + +#~ msgid "error writing to file '%s': %s\n" +#~ msgstr "'%s' dosyasına yazılamıyor: %s\n" + +#~ msgid "failed retrieving file '%s' from %s\n" +#~ msgstr "%s dosyası %s adresinden alınamadı\n" + +#~ msgid "failed to copy some file" +#~ msgstr "bazı dosyalar kopyalanamadı" + +#~ msgid "database larger than maximum size\n" +#~ msgstr "veritabanı maksimum boyuttan daha büyük\n" diff --git a/lib/libalpm/po/uk.po b/lib/libalpm/po/uk.po index d55c5259..ec1de234 100644 --- a/lib/libalpm/po/uk.po +++ b/lib/libalpm/po/uk.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Arch Linux Pacman package manager\n" "Report-Msgid-Bugs-To: http://bugs.archlinux.org/index.php?project=3\n" -"POT-Creation-Date: 2011-04-18 11:23-0500\n" +"POT-Creation-Date: 2011-06-23 21:48-0500\n" "PO-Revision-Date: 2011-03-22 15:34+0000\n" "Last-Translator: toofishes <dpmcgee@gmail.com>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -154,6 +154,10 @@ msgstr "бракує метаданих пакунку в %s\n" msgid "removing invalid file: %s\n" msgstr "" +#, fuzzy, c-format +msgid "could not parse package '%s' description file from db '%s'\n" +msgstr "неможливо розібрати файл опису пакунка %s\n" + #, c-format msgid "database path is undefined\n" msgstr "шлях до бази даних не вказано\n" @@ -219,18 +223,6 @@ msgid "failed retrieving file '%s' from %s : %s\n" msgstr "не вдалося отримати файл '%s' з %s : %s\n" #, c-format -msgid "resuming download of %s not possible; starting over\n" -msgstr "неможливо продовжити завантаження %s; починається з початку\n" - -#, c-format -msgid "error writing to file '%s': %s\n" -msgstr "помилка при запису до файлу '%s': %s\n" - -#, c-format -msgid "failed retrieving file '%s' from %s\n" -msgstr "не вдалося отримати файл '%s' з %s\n" - -#, c-format msgid "%s appears to be truncated: %jd/%jd bytes\n" msgstr "здається %s обрізаний: %jd/%jd байтів\n" @@ -379,6 +371,18 @@ msgid "could not find repository for target" msgstr "неможливо знайти репозиторій з пакунком" #, c-format +msgid "signature directory not configured correctly" +msgstr "" + +#, c-format +msgid "invalid PGP signature" +msgstr "" + +#, c-format +msgid "unknown PGP signature" +msgstr "" + +#, c-format msgid "invalid or corrupted delta" msgstr "невірний чи пошкоджений дельта-патч" @@ -403,10 +407,6 @@ msgid "failed to retrieve some files" msgstr "не вдалося отримати деякі файли" #, c-format -msgid "failed to copy some file" -msgstr "" - -#, c-format msgid "invalid regular expression" msgstr "невірний регулярний вираз" @@ -419,6 +419,10 @@ msgid "download library error" msgstr "помилка бібліотеки завантаження" #, c-format +msgid "gpgme error" +msgstr "" + +#, c-format msgid "error invoking external downloader" msgstr "помилка виклику зовнішнього завантажувача" @@ -427,10 +431,6 @@ msgid "unexpected error" msgstr "неочікувана помилка" #, c-format -msgid "database larger than maximum size\n" -msgstr "" - -#, c-format msgid "could not find %s in database -- skipping\n" msgstr "неможливо знайти %s в базі даних -- пропускається\n" @@ -549,3 +549,12 @@ msgstr "кеш %s не існує, створюється...\n" #, c-format msgid "couldn't create package cache, using /tmp instead\n" msgstr "неможливо створити кеш пакунку, використовуватиметься /tmp\n" + +#~ msgid "resuming download of %s not possible; starting over\n" +#~ msgstr "неможливо продовжити завантаження %s; починається з початку\n" + +#~ msgid "error writing to file '%s': %s\n" +#~ msgstr "помилка при запису до файлу '%s': %s\n" + +#~ msgid "failed retrieving file '%s' from %s\n" +#~ msgstr "не вдалося отримати файл '%s' з %s\n" diff --git a/lib/libalpm/po/zh_CN.po b/lib/libalpm/po/zh_CN.po index d3844477..3b07ac07 100644 --- a/lib/libalpm/po/zh_CN.po +++ b/lib/libalpm/po/zh_CN.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Arch Linux Pacman package manager\n" "Report-Msgid-Bugs-To: http://bugs.archlinux.org/index.php?project=3\n" -"POT-Creation-Date: 2011-04-18 11:23-0500\n" +"POT-Creation-Date: 2011-06-23 21:48-0500\n" "PO-Revision-Date: 2011-03-22 15:34+0000\n" "Last-Translator: ganlu <rhythm.gan@gmail.com>\n" "Language-Team: Chinese (China) <None>\n" @@ -153,6 +153,10 @@ msgstr "%s 中缺少软件包元数据\n" msgid "removing invalid file: %s\n" msgstr "删除无效文件: %s\n" +#, fuzzy, c-format +msgid "could not parse package '%s' description file from db '%s'\n" +msgstr "无法解析 %s 中的软件包描述文件\n" + #, c-format msgid "database path is undefined\n" msgstr "数据库路径未定义\n" @@ -220,18 +224,6 @@ msgid "failed retrieving file '%s' from %s : %s\n" msgstr "无法从 %2$s : %3$s 获取文件 '%1$s'\n" #, c-format -msgid "resuming download of %s not possible; starting over\n" -msgstr "无法恢复下载 %s;正在重新开始\n" - -#, c-format -msgid "error writing to file '%s': %s\n" -msgstr "写入文件 '%1$s' 时出错: %2$s\n" - -#, c-format -msgid "failed retrieving file '%s' from %s\n" -msgstr "无法从 %2$s 获取文件 '%1$s'\n" - -#, c-format msgid "%s appears to be truncated: %jd/%jd bytes\n" msgstr "%s 可缩小:%jd/%jd bytes\n" @@ -380,6 +372,18 @@ msgid "could not find repository for target" msgstr "无法为目标找到软件库" #, c-format +msgid "signature directory not configured correctly" +msgstr "" + +#, c-format +msgid "invalid PGP signature" +msgstr "" + +#, c-format +msgid "unknown PGP signature" +msgstr "" + +#, c-format msgid "invalid or corrupted delta" msgstr "无效的或已损坏的 delta" @@ -404,10 +408,6 @@ msgid "failed to retrieve some files" msgstr "无法获取某些文件" #, c-format -msgid "failed to copy some file" -msgstr "复制文件失败" - -#, c-format msgid "invalid regular expression" msgstr "无效的正则表达式" @@ -420,6 +420,10 @@ msgid "download library error" msgstr "下载函数库出错" #, c-format +msgid "gpgme error" +msgstr "" + +#, c-format msgid "error invoking external downloader" msgstr "调用外部下载程序时出错" @@ -428,10 +432,6 @@ msgid "unexpected error" msgstr "未预期的错误" #, c-format -msgid "database larger than maximum size\n" -msgstr "数据库超过最大支持的大小\n" - -#, c-format msgid "could not find %s in database -- skipping\n" msgstr "无法在数据库中找到 %s -- 跳过\n" @@ -550,3 +550,18 @@ msgstr "没有 %s 缓存存在,正在创建...\n" #, c-format msgid "couldn't create package cache, using /tmp instead\n" msgstr "无法创建软件包缓存,正在使用 /tmp 代替\n" + +#~ msgid "resuming download of %s not possible; starting over\n" +#~ msgstr "无法恢复下载 %s;正在重新开始\n" + +#~ msgid "error writing to file '%s': %s\n" +#~ msgstr "写入文件 '%1$s' 时出错: %2$s\n" + +#~ msgid "failed retrieving file '%s' from %s\n" +#~ msgstr "无法从 %2$s 获取文件 '%1$s'\n" + +#~ msgid "failed to copy some file" +#~ msgstr "复制文件失败" + +#~ msgid "database larger than maximum size\n" +#~ msgstr "数据库超过最大支持的大小\n" diff --git a/lib/libalpm/rawstr.c b/lib/libalpm/rawstr.c new file mode 100644 index 00000000..86f4280c --- /dev/null +++ b/lib/libalpm/rawstr.c @@ -0,0 +1,137 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* These functions are borrowed from libcurl's lib/rawstr.c with minor + * modifications to style and naming. Curl_raw_equal and Curl_raw_nequal are + * further modified to be true cmp style functions, returning negative, zero, + * or positive. */ + +#include <stdlib.h> + +#include "util.h" + +/* Portable, consistent toupper (remember EBCDIC). Do not use toupper() because + its behavior is altered by the current locale. */ +static char raw_toupper(char in) +{ + switch(in) { + case 'a': + return 'A'; + case 'b': + return 'B'; + case 'c': + return 'C'; + case 'd': + return 'D'; + case 'e': + return 'E'; + case 'f': + return 'F'; + case 'g': + return 'G'; + case 'h': + return 'H'; + case 'i': + return 'I'; + case 'j': + return 'J'; + case 'k': + return 'K'; + case 'l': + return 'L'; + case 'm': + return 'M'; + case 'n': + return 'N'; + case 'o': + return 'O'; + case 'p': + return 'P'; + case 'q': + return 'Q'; + case 'r': + return 'R'; + case 's': + return 'S'; + case 't': + return 'T'; + case 'u': + return 'U'; + case 'v': + return 'V'; + case 'w': + return 'W'; + case 'x': + return 'X'; + case 'y': + return 'Y'; + case 'z': + return 'Z'; + } + return in; +} + +/* + * _alpm_raw_cmp() is for doing "raw" case insensitive strings. This is meant + * to be locale independent and only compare strings we know are safe for + * this. See http://daniel.haxx.se/blog/2008/10/15/strcasecmp-in-turkish/ for + * some further explanation to why this function is necessary. + * + * The function is capable of comparing a-z case insensitively even for + * non-ascii. + */ + +int _alpm_raw_cmp(const char *first, const char *second) +{ + while(*first && *second) { + if(raw_toupper(*first) != raw_toupper(*second)) { + /* get out of the loop as soon as they don't match */ + break; + } + first++; + second++; + } + /* we do the comparison here (possibly again), just to make sure that if the + loop above is skipped because one of the strings reached zero, we must not + return this as a successful match */ + return (raw_toupper(*first) - raw_toupper(*second)); +} + +int _alpm_raw_ncmp(const char *first, const char *second, size_t max) +{ + while(*first && *second && max) { + if(raw_toupper(*first) != raw_toupper(*second)) { + break; + } + max--; + first++; + second++; + } + if(0 == max) { + /* they are equal this far */ + return 0; + } + + return (raw_toupper(*first) - raw_toupper(*second)); +} + +/* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/remove.c b/lib/libalpm/remove.c index 22ae2bb8..3c19c90a 100644 --- a/lib/libalpm/remove.c +++ b/lib/libalpm/remove.c @@ -26,8 +26,6 @@ #include <stdlib.h> #include <errno.h> -#include <time.h> -#include <fcntl.h> #include <string.h> #include <limits.h> #include <unistd.h> @@ -36,6 +34,7 @@ /* libalpm */ #include "remove.h" #include "alpm_list.h" +#include "alpm.h" #include "trans.h" #include "util.h" #include "log.h" @@ -44,73 +43,72 @@ #include "db.h" #include "deps.h" #include "handle.h" -#include "alpm.h" +#include "conflict.h" -int SYMEXPORT alpm_remove_pkg(pmpkg_t *pkg) +int SYMEXPORT alpm_remove_pkg(alpm_handle_t *handle, alpm_pkg_t *pkg) { - pmtrans_t *trans; const char *pkgname; - - ALPM_LOG_FUNC; + alpm_trans_t *trans; /* Sanity checks */ - ASSERT(pkg != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + CHECK_HANDLE(handle, return -1); + ASSERT(pkg != NULL, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1)); + ASSERT(handle == pkg->handle, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1)); trans = handle->trans; - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); + ASSERT(trans != NULL, RET_ERR(handle, ALPM_ERR_TRANS_NULL, -1)); ASSERT(trans->state == STATE_INITIALIZED, - RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1)); + RET_ERR(handle, ALPM_ERR_TRANS_NOT_INITIALIZED, -1)); - pkgname = alpm_pkg_get_name(pkg); + pkgname = pkg->name; if(_alpm_pkg_find(trans->remove, pkgname)) { - RET_ERR(PM_ERR_TRANS_DUP_TARGET, -1); + RET_ERR(handle, ALPM_ERR_TRANS_DUP_TARGET, -1); } - _alpm_log(PM_LOG_DEBUG, "adding %s in the target list\n", pkgname); + _alpm_log(handle, ALPM_LOG_DEBUG, "adding package %s to the transaction remove list\n", + pkgname); trans->remove = alpm_list_add(trans->remove, _alpm_pkg_dup(pkg)); - return(0); + return 0; } -static void remove_prepare_cascade(pmtrans_t *trans, pmdb_t *db, - alpm_list_t *lp) +static void remove_prepare_cascade(alpm_handle_t *handle, alpm_list_t *lp) { - ALPM_LOG_FUNC; + alpm_trans_t *trans = handle->trans; while(lp) { alpm_list_t *i; for(i = lp; i; i = i->next) { - pmdepmissing_t *miss = (pmdepmissing_t *)i->data; - pmpkg_t *info = _alpm_db_get_pkgfromcache(db, miss->target); + alpm_depmissing_t *miss = i->data; + alpm_pkg_t *info = _alpm_db_get_pkgfromcache(handle->db_local, miss->target); if(info) { if(!_alpm_pkg_find(trans->remove, alpm_pkg_get_name(info))) { - _alpm_log(PM_LOG_DEBUG, "pulling %s in target list\n", + _alpm_log(handle, ALPM_LOG_DEBUG, "pulling %s in target list\n", alpm_pkg_get_name(info)); trans->remove = alpm_list_add(trans->remove, _alpm_pkg_dup(info)); } } else { - _alpm_log(PM_LOG_ERROR, _("could not find %s in database -- skipping\n"), + _alpm_log(handle, ALPM_LOG_ERROR, _("could not find %s in database -- skipping\n"), miss->target); } } alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_depmiss_free); alpm_list_free(lp); - lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, trans->remove, NULL); + lp = alpm_checkdeps(handle, _alpm_db_get_pkgcache(handle->db_local), + trans->remove, NULL, 1); } } -static void remove_prepare_keep_needed(pmtrans_t *trans, pmdb_t *db, - alpm_list_t *lp) +static void remove_prepare_keep_needed(alpm_handle_t *handle, alpm_list_t *lp) { - ALPM_LOG_FUNC; + alpm_trans_t *trans = handle->trans; /* Remove needed packages (which break dependencies) from target list */ while(lp != NULL) { alpm_list_t *i; for(i = lp; i; i = i->next) { - pmdepmissing_t *miss = (pmdepmissing_t *)i->data; + alpm_depmissing_t *miss = i->data; void *vpkg; - pmpkg_t *pkg = _alpm_pkg_find(trans->remove, miss->causingpkg); + alpm_pkg_t *pkg = _alpm_pkg_find(trans->remove, miss->causingpkg); if(pkg == NULL) { continue; } @@ -118,52 +116,50 @@ static void remove_prepare_keep_needed(pmtrans_t *trans, pmdb_t *db, &vpkg); pkg = vpkg; if(pkg) { - _alpm_log(PM_LOG_WARNING, _("removing %s from target list\n"), + _alpm_log(handle, ALPM_LOG_WARNING, _("removing %s from target list\n"), alpm_pkg_get_name(pkg)); _alpm_pkg_free(pkg); } } alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_depmiss_free); alpm_list_free(lp); - lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, trans->remove, NULL); + lp = alpm_checkdeps(handle, _alpm_db_get_pkgcache(handle->db_local), + trans->remove, NULL, 1); } } /** Transaction preparation for remove actions. * This functions takes a pointer to a alpm_list_t which will be - * filled with a list of pmdepmissing_t* objects representing + * filled with a list of alpm_depmissing_t* objects representing * the packages blocking the transaction. - * @param trans the transaction object - * @param db the database of local packages + * @param handle the context handle * @param data a pointer to an alpm_list_t* to fill */ -int _alpm_remove_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data) +int _alpm_remove_prepare(alpm_handle_t *handle, alpm_list_t **data) { alpm_list_t *lp; + alpm_trans_t *trans = handle->trans; + alpm_db_t *db = handle->db_local; - ALPM_LOG_FUNC; - - ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - - if((trans->flags & PM_TRANS_FLAG_RECURSE) && !(trans->flags & PM_TRANS_FLAG_CASCADE)) { - _alpm_log(PM_LOG_DEBUG, "finding removable dependencies\n"); - _alpm_recursedeps(db, trans->remove, trans->flags & PM_TRANS_FLAG_RECURSEALL); + if((trans->flags & ALPM_TRANS_FLAG_RECURSE) && !(trans->flags & ALPM_TRANS_FLAG_CASCADE)) { + _alpm_log(handle, ALPM_LOG_DEBUG, "finding removable dependencies\n"); + _alpm_recursedeps(db, trans->remove, + trans->flags & ALPM_TRANS_FLAG_RECURSEALL); } - if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) { - EVENT(trans, PM_TRANS_EVT_CHECKDEPS_START, NULL, NULL); + if(!(trans->flags & ALPM_TRANS_FLAG_NODEPS)) { + EVENT(trans, ALPM_TRANS_EVT_CHECKDEPS_START, NULL, NULL); - _alpm_log(PM_LOG_DEBUG, "looking for unsatisfied dependencies\n"); - lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, trans->remove, NULL); + _alpm_log(handle, ALPM_LOG_DEBUG, "looking for unsatisfied dependencies\n"); + lp = alpm_checkdeps(handle, _alpm_db_get_pkgcache(db), trans->remove, NULL, 1); if(lp != NULL) { - if(trans->flags & PM_TRANS_FLAG_CASCADE) { - remove_prepare_cascade(trans, db, lp); - } else if (trans->flags & PM_TRANS_FLAG_UNNEEDED) { + if(trans->flags & ALPM_TRANS_FLAG_CASCADE) { + remove_prepare_cascade(handle, lp); + } else if(trans->flags & ALPM_TRANS_FLAG_UNNEEDED) { /* Remove needed packages (which would break dependencies) * from target list */ - remove_prepare_keep_needed(trans, db, lp); + remove_prepare_keep_needed(handle, lp); } else { if(data) { *data = lp; @@ -171,74 +167,74 @@ int _alpm_remove_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data) alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_depmiss_free); alpm_list_free(lp); } - RET_ERR(PM_ERR_UNSATISFIED_DEPS, -1); + RET_ERR(handle, ALPM_ERR_UNSATISFIED_DEPS, -1); } } } /* re-order w.r.t. dependencies */ - _alpm_log(PM_LOG_DEBUG, "sorting by dependencies\n"); - lp = _alpm_sortbydeps(trans->remove, 1); + _alpm_log(handle, ALPM_LOG_DEBUG, "sorting by dependencies\n"); + lp = _alpm_sortbydeps(handle, trans->remove, 1); /* free the old alltargs */ alpm_list_free(trans->remove); trans->remove = lp; /* -Rcs == -Rc then -Rs */ - if((trans->flags & PM_TRANS_FLAG_CASCADE) && (trans->flags & PM_TRANS_FLAG_RECURSE)) { - _alpm_log(PM_LOG_DEBUG, "finding removable dependencies\n"); - _alpm_recursedeps(db, trans->remove, trans->flags & PM_TRANS_FLAG_RECURSEALL); + if((trans->flags & ALPM_TRANS_FLAG_CASCADE) && (trans->flags & ALPM_TRANS_FLAG_RECURSE)) { + _alpm_log(handle, ALPM_LOG_DEBUG, "finding removable dependencies\n"); + _alpm_recursedeps(db, trans->remove, trans->flags & ALPM_TRANS_FLAG_RECURSEALL); } - if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) { - EVENT(trans, PM_TRANS_EVT_CHECKDEPS_DONE, NULL, NULL); + if(!(trans->flags & ALPM_TRANS_FLAG_NODEPS)) { + EVENT(trans, ALPM_TRANS_EVT_CHECKDEPS_DONE, NULL, NULL); } - return(0); + return 0; } -static int can_remove_file(const char *path, alpm_list_t *skip) +static int can_remove_file(alpm_handle_t *handle, const alpm_file_t *file, + alpm_list_t *skip_remove) { - char file[PATH_MAX+1]; + char filepath[PATH_MAX]; - snprintf(file, PATH_MAX, "%s%s", handle->root, path); + snprintf(filepath, PATH_MAX, "%s%s", handle->root, file->name); - if(alpm_list_find_str(skip, file)) { + if(alpm_list_find_str(skip_remove, filepath)) { /* return success because we will never actually remove this file */ - return(1); + return 1; } /* If we fail write permissions due to a read-only filesystem, abort. * Assume all other possible failures are covered somewhere else */ - if(access(file, W_OK) == -1) { - if(errno != EACCES && errno != ETXTBSY && access(file, F_OK) == 0) { + if(_alpm_access(handle, NULL, filepath, W_OK) == -1) { + if(errno != EACCES && errno != ETXTBSY && access(filepath, F_OK) == 0) { /* only return failure if the file ACTUALLY exists and we can't write to * it - ignore "chmod -w" simple permission failures */ - _alpm_log(PM_LOG_ERROR, _("cannot remove file '%s': %s\n"), - file, strerror(errno)); - return(0); + _alpm_log(handle, ALPM_LOG_ERROR, _("cannot remove file '%s': %s\n"), + filepath, strerror(errno)); + return 0; } } - return(1); + return 1; } /* Helper function for iterating through a package's file and deleting them * Used by _alpm_remove_commit. */ -static void unlink_file(pmpkg_t *info, char *filename, alpm_list_t *skip_remove, int nosave) +static int unlink_file(alpm_handle_t *handle, alpm_pkg_t *info, + const alpm_file_t *fileobj, alpm_list_t *skip_remove, int nosave) { struct stat buf; - char file[PATH_MAX+1]; - - ALPM_LOG_FUNC; + char file[PATH_MAX]; - snprintf(file, PATH_MAX, "%s%s", handle->root, filename); + snprintf(file, PATH_MAX, "%s%s", handle->root, fileobj->name); /* check the remove skip list before removing the file. * see the big comment block in db_find_fileconflicts() for an * explanation. */ - if(alpm_list_find_str(skip_remove, filename)) { - _alpm_log(PM_LOG_DEBUG, "%s is in skip_remove, skipping removal\n", - file); - return; + if(alpm_list_find_str(skip_remove, fileobj->name)) { + _alpm_log(handle, ALPM_LOG_DEBUG, + "%s is in skip_remove, skipping removal\n", file); + return 1; } /* we want to do a lstat here, and not a _alpm_lstat. @@ -246,226 +242,252 @@ static void unlink_file(pmpkg_t *info, char *filename, alpm_list_t *skip_remove, * filesystem, we want to work with the linked directory instead of the * actual symlink */ if(lstat(file, &buf)) { - _alpm_log(PM_LOG_DEBUG, "file %s does not exist\n", file); - return; + _alpm_log(handle, ALPM_LOG_DEBUG, "file %s does not exist\n", file); + return 1; } if(S_ISDIR(buf.st_mode)) { - if(rmdir(file)) { - /* this is okay, other packages are probably using it (like /usr) */ - _alpm_log(PM_LOG_DEBUG, "keeping directory %s\n", file); + ssize_t files = _alpm_files_in_directory(handle, file, 0); + /* if we have files, no need to remove the directory */ + if(files > 0) { + _alpm_log(handle, ALPM_LOG_DEBUG, "keeping directory %s (contains files)\n", + file); + } else if(files < 0) { + _alpm_log(handle, ALPM_LOG_DEBUG, + "keeping directory %s (could not count files)\n", file); } else { - _alpm_log(PM_LOG_DEBUG, "removing directory %s\n", file); + /* one last check- does any other package own this file? */ + alpm_list_t *local, *local_pkgs; + int found = 0; + local_pkgs = _alpm_db_get_pkgcache(handle->db_local); + for(local = local_pkgs; local && !found; local = local->next) { + alpm_pkg_t *local_pkg = local->data; + alpm_filelist_t *filelist; + + /* we duplicated the package when we put it in the removal list, so we + * so we can't use direct pointer comparison here. */ + if(_alpm_pkg_cmp(info, local_pkg) == 0) { + continue; + } + filelist = alpm_pkg_get_files(local_pkg); + if(_alpm_filelist_contains(filelist, fileobj->name)) { + _alpm_log(handle, ALPM_LOG_DEBUG, + "keeping directory %s (owned by %s)\n", file, local_pkg->name); + found = 1; + } + } + if(!found) { + if(rmdir(file)) { + _alpm_log(handle, ALPM_LOG_DEBUG, + "directory removal of %s failed: %s\n", file, strerror(errno)); + return -1; + } else { + _alpm_log(handle, ALPM_LOG_DEBUG, + "removed directory %s (no remaining owners)\n", file); + } + } } } else { /* if the file needs backup and has been modified, back it up to .pacsave */ - char *pkghash = _alpm_needbackup(filename, alpm_pkg_get_backup(info)); - if(pkghash) { + alpm_backup_t *backup = _alpm_needbackup(fileobj->name, info); + if(backup) { if(nosave) { - _alpm_log(PM_LOG_DEBUG, "transaction is set to NOSAVE, not backing up '%s'\n", file); - FREE(pkghash); + _alpm_log(handle, ALPM_LOG_DEBUG, "transaction is set to NOSAVE, not backing up '%s'\n", file); } else { char *filehash = alpm_compute_md5sum(file); - int cmp = filehash ? strcmp(filehash, pkghash) : 0; + int cmp = filehash ? strcmp(filehash, backup->hash) : 0; FREE(filehash); - FREE(pkghash); if(cmp != 0) { char newpath[PATH_MAX]; snprintf(newpath, PATH_MAX, "%s.pacsave", file); - rename(file, newpath); - _alpm_log(PM_LOG_WARNING, _("%s saved as %s\n"), file, newpath); - alpm_logaction("warning: %s saved as %s\n", file, newpath); - return; + if(rename(file, newpath)) { + _alpm_log(handle, ALPM_LOG_ERROR, _("could not rename %s to %s (%s)\n"), + file, newpath, strerror(errno)); + alpm_logaction(handle, "error: could not rename %s to %s (%s)\n", + file, newpath, strerror(errno)); + return -1; + } + _alpm_log(handle, ALPM_LOG_WARNING, _("%s saved as %s\n"), file, newpath); + alpm_logaction(handle, "warning: %s saved as %s\n", file, newpath); + return 0; } } } - _alpm_log(PM_LOG_DEBUG, "unlinking %s\n", file); + _alpm_log(handle, ALPM_LOG_DEBUG, "unlinking %s\n", file); if(unlink(file) == -1) { - _alpm_log(PM_LOG_ERROR, _("cannot remove file '%s': %s\n"), - filename, strerror(errno)); + _alpm_log(handle, ALPM_LOG_ERROR, _("cannot remove %s (%s)\n"), + file, strerror(errno)); + alpm_logaction(handle, "error: cannot remove %s (%s)\n", + file, strerror(errno)); + return -1; } } + return 0; } -int _alpm_upgraderemove_package(pmpkg_t *oldpkg, pmpkg_t *newpkg, - pmtrans_t *trans) +int _alpm_remove_single_package(alpm_handle_t *handle, + alpm_pkg_t *oldpkg, alpm_pkg_t *newpkg, + size_t targ_count, size_t pkg_count) { - alpm_list_t *skip_remove, *b; - alpm_list_t *newfiles, *lp; - size_t filenum; - alpm_list_t *files = alpm_pkg_get_files(oldpkg); - const char *pkgname = alpm_pkg_get_name(oldpkg); + alpm_list_t *skip_remove; + size_t filenum = 0, position = 0; + const char *pkgname = oldpkg->name; + const char *pkgver = oldpkg->version; + alpm_filelist_t *filelist; + char scriptlet[PATH_MAX]; + size_t i; + + if(newpkg) { + _alpm_log(handle, ALPM_LOG_DEBUG, "removing old package first (%s-%s)\n", + pkgname, pkgver); + } else { + EVENT(handle->trans, ALPM_TRANS_EVT_REMOVE_START, oldpkg, NULL); + _alpm_log(handle, ALPM_LOG_DEBUG, "removing package %s-%s\n", + pkgname, pkgver); - ALPM_LOG_FUNC; + snprintf(scriptlet, PATH_MAX, "%s%s-%s/install", + _alpm_db_path(handle->db_local), pkgname, pkgver); - _alpm_log(PM_LOG_DEBUG, "removing old package first (%s-%s)\n", - oldpkg->name, oldpkg->version); + /* run the pre-remove scriptlet if it exists */ + if(alpm_pkg_has_scriptlet(oldpkg) && + !(handle->trans->flags & ALPM_TRANS_FLAG_NOSCRIPTLET)) { + _alpm_runscriptlet(handle, scriptlet, "pre_remove", pkgver, NULL); + } + } - if(trans->flags & PM_TRANS_FLAG_DBONLY) { + if(handle->trans->flags & ALPM_TRANS_FLAG_DBONLY) { goto db; } - /* copy the remove skiplist over */ - skip_remove = alpm_list_join( - alpm_list_strdup(trans->skip_remove), - alpm_list_strdup(handle->noupgrade)); - /* Add files in the NEW backup array to the skip_remove array - * so this removal operation doesn't kill them */ - /* old package backup list */ - alpm_list_t *filelist = alpm_pkg_get_files(newpkg); - for(b = alpm_pkg_get_backup(newpkg); b; b = b->next) { - char *backup = _alpm_backup_file(b->data); - /* safety check (fix the upgrade026 pactest) */ - if(!alpm_list_find_str(filelist, backup)) { - FREE(backup); - continue; + if(newpkg) { + alpm_filelist_t *newfiles; + alpm_list_t *b; + skip_remove = alpm_list_join( + alpm_list_strdup(handle->trans->skip_remove), + alpm_list_strdup(handle->noupgrade)); + /* Add files in the NEW backup array to the skip_remove array + * so this removal operation doesn't kill them */ + /* old package backup list */ + newfiles = alpm_pkg_get_files(newpkg); + for(b = alpm_pkg_get_backup(newpkg); b; b = b->next) { + const alpm_backup_t *backup = b->data; + /* safety check (fix the upgrade026 pactest) */ + if(!_alpm_filelist_contains(newfiles, backup->name)) { + continue; + } + _alpm_log(handle, ALPM_LOG_DEBUG, "adding %s to the skip_remove array\n", + backup->name); + skip_remove = alpm_list_add(skip_remove, strdup(backup->name)); } - _alpm_log(PM_LOG_DEBUG, "adding %s to the skip_remove array\n", backup); - skip_remove = alpm_list_add(skip_remove, backup); + } else { + skip_remove = alpm_list_strdup(handle->trans->skip_remove); } - for(lp = files; lp; lp = lp->next) { - if(!can_remove_file(lp->data, skip_remove)) { - _alpm_log(PM_LOG_DEBUG, "not removing package '%s', can't remove all files\n", - pkgname); - RET_ERR(PM_ERR_PKG_CANT_REMOVE, -1); + filelist = alpm_pkg_get_files(oldpkg); + for(i = 0; i < filelist->count; i++) { + alpm_file_t *file = filelist->files + i; + if(!can_remove_file(handle, file, skip_remove)) { + _alpm_log(handle, ALPM_LOG_DEBUG, + "not removing package '%s', can't remove all files\n", pkgname); + RET_ERR(handle, ALPM_ERR_PKG_CANT_REMOVE, -1); } + filenum++; } - filenum = alpm_list_count(files); - _alpm_log(PM_LOG_DEBUG, "removing %ld files\n", (unsigned long)filenum); + _alpm_log(handle, ALPM_LOG_DEBUG, "removing %ld files\n", (unsigned long)filenum); + + if(!newpkg) { + /* init progress bar, but only on true remove transactions */ + PROGRESS(handle->trans, ALPM_TRANS_PROGRESS_REMOVE_START, pkgname, 0, + pkg_count, targ_count); + } /* iterate through the list backwards, unlinking files */ - newfiles = alpm_list_reverse(files); - for(lp = newfiles; lp; lp = alpm_list_next(lp)) { - unlink_file(oldpkg, lp->data, skip_remove, 0); + for(i = filelist->count; i > 0; i--) { + alpm_file_t *file = filelist->files + i - 1; + int percent; + /* TODO: check return code and handle accordingly */ + unlink_file(handle, oldpkg, file, skip_remove, + handle->trans->flags & ALPM_TRANS_FLAG_NOSAVE); + + if(!newpkg) { + /* update progress bar after each file */ + percent = (position * 100) / filenum; + PROGRESS(handle->trans, ALPM_TRANS_PROGRESS_REMOVE_START, pkgname, + percent, pkg_count, targ_count); + } + position++; } - alpm_list_free(newfiles); FREELIST(skip_remove); + if(!newpkg) { + /* set progress to 100% after we finish unlinking files */ + PROGRESS(handle->trans, ALPM_TRANS_PROGRESS_REMOVE_START, pkgname, 100, + pkg_count, targ_count); + + /* run the post-remove script if it exists */ + if(alpm_pkg_has_scriptlet(oldpkg) && + !(handle->trans->flags & ALPM_TRANS_FLAG_NOSCRIPTLET)) { + _alpm_runscriptlet(handle, scriptlet, "post_remove", pkgver, NULL); + } + } + db: /* remove the package from the database */ - _alpm_log(PM_LOG_DEBUG, "updating database\n"); - _alpm_log(PM_LOG_DEBUG, "removing database entry '%s'\n", pkgname); + _alpm_log(handle, ALPM_LOG_DEBUG, "updating database\n"); + _alpm_log(handle, ALPM_LOG_DEBUG, "removing database entry '%s'\n", pkgname); if(_alpm_local_db_remove(handle->db_local, oldpkg) == -1) { - _alpm_log(PM_LOG_ERROR, _("could not remove database entry %s-%s\n"), - pkgname, alpm_pkg_get_version(oldpkg)); + _alpm_log(handle, ALPM_LOG_ERROR, _("could not remove database entry %s-%s\n"), + pkgname, pkgver); } /* remove the package from the cache */ if(_alpm_db_remove_pkgfromcache(handle->db_local, oldpkg) == -1) { - _alpm_log(PM_LOG_ERROR, _("could not remove entry '%s' from cache\n"), + _alpm_log(handle, ALPM_LOG_ERROR, _("could not remove entry '%s' from cache\n"), pkgname); } - return(0); + if(!newpkg) { + /* TODO: awesome! we're passing invalid pointers. */ + EVENT(handle->trans, ALPM_TRANS_EVT_REMOVE_DONE, oldpkg, NULL); + } + + return 0; } -int _alpm_remove_packages(pmtrans_t *trans, pmdb_t *db) +int _alpm_remove_packages(alpm_handle_t *handle) { - pmpkg_t *info; - alpm_list_t *targ, *lp; - size_t pkg_count; - - ALPM_LOG_FUNC; - - ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); + alpm_list_t *targ; + size_t pkg_count, targ_count; + alpm_trans_t *trans = handle->trans; + int ret = 0; pkg_count = alpm_list_count(trans->remove); + targ_count = 1; for(targ = trans->remove; targ; targ = targ->next) { - int position = 0; - char scriptlet[PATH_MAX]; - info = (pmpkg_t*)targ->data; - const char *pkgname = NULL; - size_t targcount = alpm_list_count(targ); - - if(handle->trans->state == STATE_INTERRUPTED) { - return(0); - } + alpm_pkg_t *pkg = targ->data; - /* get the name now so we can use it after package is removed */ - pkgname = alpm_pkg_get_name(info); - snprintf(scriptlet, PATH_MAX, "%s%s-%s/install", - _alpm_db_path(db), pkgname, alpm_pkg_get_version(info)); - - EVENT(trans, PM_TRANS_EVT_REMOVE_START, info, NULL); - _alpm_log(PM_LOG_DEBUG, "removing package %s-%s\n", - pkgname, alpm_pkg_get_version(info)); - - /* run the pre-remove scriptlet if it exists */ - if(alpm_pkg_has_scriptlet(info) && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) { - _alpm_runscriptlet(handle->root, scriptlet, "pre_remove", - alpm_pkg_get_version(info), NULL, trans); + if(trans->state == STATE_INTERRUPTED) { + return 0; } - if(!(trans->flags & PM_TRANS_FLAG_DBONLY)) { - alpm_list_t *files = alpm_pkg_get_files(info); - alpm_list_t *newfiles; - size_t filenum; - - for(lp = files; lp; lp = lp->next) { - if(!can_remove_file(lp->data, NULL)) { - _alpm_log(PM_LOG_DEBUG, "not removing package '%s', can't remove all files\n", - pkgname); - RET_ERR(PM_ERR_PKG_CANT_REMOVE, -1); - } - } - - filenum = alpm_list_count(files); - _alpm_log(PM_LOG_DEBUG, "removing %ld files\n", (unsigned long)filenum); - - /* init progress bar */ - PROGRESS(trans, PM_TRANS_PROGRESS_REMOVE_START, info->name, 0, - pkg_count, (pkg_count - targcount + 1)); - - /* iterate through the list backwards, unlinking files */ - newfiles = alpm_list_reverse(files); - for(lp = newfiles; lp; lp = alpm_list_next(lp)) { - int percent; - unlink_file(info, lp->data, NULL, trans->flags & PM_TRANS_FLAG_NOSAVE); - - /* update progress bar after each file */ - percent = (position * 100) / filenum; - PROGRESS(trans, PM_TRANS_PROGRESS_REMOVE_START, info->name, - percent, pkg_count, (pkg_count - targcount + 1)); - position++; - } - alpm_list_free(newfiles); - } - - /* set progress to 100% after we finish unlinking files */ - PROGRESS(trans, PM_TRANS_PROGRESS_REMOVE_START, pkgname, 100, - pkg_count, (pkg_count - targcount + 1)); - - /* run the post-remove script if it exists */ - if(alpm_pkg_has_scriptlet(info) && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) { - _alpm_runscriptlet(handle->root, scriptlet, "post_remove", - alpm_pkg_get_version(info), NULL, trans); - } - - /* remove the package from the database */ - _alpm_log(PM_LOG_DEBUG, "updating database\n"); - _alpm_log(PM_LOG_DEBUG, "removing database entry '%s'\n", pkgname); - if(_alpm_local_db_remove(db, info) == -1) { - _alpm_log(PM_LOG_ERROR, _("could not remove database entry %s-%s\n"), - pkgname, alpm_pkg_get_version(info)); - } - /* remove the package from the cache */ - if(_alpm_db_remove_pkgfromcache(db, info) == -1) { - _alpm_log(PM_LOG_ERROR, _("could not remove entry '%s' from cache\n"), - pkgname); + if(_alpm_remove_single_package(handle, pkg, NULL, + targ_count, pkg_count) == -1) { + handle->pm_errno = ALPM_ERR_TRANS_ABORT; + ret = -1; + goto cleanup; } - EVENT(trans, PM_TRANS_EVT_REMOVE_DONE, info, NULL); + targ_count++; } /* run ldconfig if it exists */ - _alpm_ldconfig(handle->root); + _alpm_ldconfig(handle); - return(0); +cleanup: + return ret; } /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/remove.h b/lib/libalpm/remove.h index a67e37a1..5da645b0 100644 --- a/lib/libalpm/remove.h +++ b/lib/libalpm/remove.h @@ -24,10 +24,12 @@ #include "alpm_list.h" #include "trans.h" -int _alpm_remove_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data); -int _alpm_remove_packages(pmtrans_t *trans, pmdb_t *db); +int _alpm_remove_prepare(alpm_handle_t *handle, alpm_list_t **data); +int _alpm_remove_packages(alpm_handle_t *handle); -int _alpm_upgraderemove_package(pmpkg_t *oldpkg, pmpkg_t *newpkg, pmtrans_t *trans); +int _alpm_remove_single_package(alpm_handle_t *handle, + alpm_pkg_t *oldpkg, alpm_pkg_t *newpkg, + size_t targ_count, size_t pkg_count); #endif /* _ALPM_REMOVE_H */ diff --git a/lib/libalpm/signing.c b/lib/libalpm/signing.c new file mode 100644 index 00000000..78e6264b --- /dev/null +++ b/lib/libalpm/signing.c @@ -0,0 +1,548 @@ +/* + * signing.c + * + * Copyright (c) 2008-2011 Pacman Development Team <pacman-dev@archlinux.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#if HAVE_LIBGPGME +#include <locale.h> /* setlocale() */ +#include <gpgme.h> +#include "base64.h" +#endif + +/* libalpm */ +#include "signing.h" +#include "package.h" +#include "util.h" +#include "log.h" +#include "alpm.h" +#include "handle.h" + +#if HAVE_LIBGPGME +#define CHECK_ERR(void) do { \ + if(gpg_err_code(err) != GPG_ERR_NO_ERROR) { goto error; } \ + } while(0) + +static const char *string_validity(gpgme_validity_t validity) +{ + switch(validity) { + case GPGME_VALIDITY_UNKNOWN: + return "unknown"; + case GPGME_VALIDITY_UNDEFINED: + return "undefined"; + case GPGME_VALIDITY_NEVER: + return "never"; + case GPGME_VALIDITY_MARGINAL: + return "marginal"; + case GPGME_VALIDITY_FULL: + return "full"; + case GPGME_VALIDITY_ULTIMATE: + return "ultimate"; + } + return "???"; +} + +static void sigsum_test_bit(gpgme_sigsum_t sigsum, alpm_list_t **summary, + gpgme_sigsum_t bit, const char *value) +{ + if(sigsum & bit) { + *summary = alpm_list_add(*summary, (void *)value); + } +} + +static alpm_list_t *list_sigsum(gpgme_sigsum_t sigsum) +{ + alpm_list_t *summary = NULL; + /* The docs say this can be a bitmask...not sure I believe it, but we'll code + * for it anyway and show all possible flags in the returned string. */ + + /* The signature is fully valid. */ + sigsum_test_bit(sigsum, &summary, GPGME_SIGSUM_VALID, "valid"); + /* The signature is good. */ + sigsum_test_bit(sigsum, &summary, GPGME_SIGSUM_GREEN, "green"); + /* The signature is bad. */ + sigsum_test_bit(sigsum, &summary, GPGME_SIGSUM_RED, "red"); + /* One key has been revoked. */ + sigsum_test_bit(sigsum, &summary, GPGME_SIGSUM_KEY_REVOKED, "key revoked"); + /* One key has expired. */ + sigsum_test_bit(sigsum, &summary, GPGME_SIGSUM_KEY_EXPIRED, "key expired"); + /* The signature has expired. */ + sigsum_test_bit(sigsum, &summary, GPGME_SIGSUM_SIG_EXPIRED, "sig expired"); + /* Can't verify: key missing. */ + sigsum_test_bit(sigsum, &summary, GPGME_SIGSUM_KEY_MISSING, "key missing"); + /* CRL not available. */ + sigsum_test_bit(sigsum, &summary, GPGME_SIGSUM_CRL_MISSING, "crl missing"); + /* Available CRL is too old. */ + sigsum_test_bit(sigsum, &summary, GPGME_SIGSUM_CRL_TOO_OLD, "crl too old"); + /* A policy was not met. */ + sigsum_test_bit(sigsum, &summary, GPGME_SIGSUM_BAD_POLICY, "bad policy"); + /* A system error occured. */ + sigsum_test_bit(sigsum, &summary, GPGME_SIGSUM_SYS_ERROR, "sys error"); + /* Fallback case */ + if(!sigsum) { + summary = alpm_list_add(summary, (void *)"(empty)"); + } + return summary; +} + +static int init_gpgme(alpm_handle_t *handle) +{ + static int init = 0; + const char *version, *sigdir; + gpgme_error_t err; + gpgme_engine_info_t enginfo; + + if(init) { + /* we already successfully initialized the library */ + return 0; + } + + sigdir = alpm_option_get_gpgdir(handle); + + if (_alpm_access(handle, sigdir, "pubring.gpg", R_OK) + || _alpm_access(handle, sigdir, "trustdb.gpg", R_OK)) { + handle->pm_errno = ALPM_ERR_NOT_A_FILE; + _alpm_log(handle, ALPM_LOG_DEBUG, "Signature verification will fail!\n"); + } + + /* calling gpgme_check_version() returns the current version and runs + * some internal library setup code */ + version = gpgme_check_version(NULL); + _alpm_log(handle, ALPM_LOG_DEBUG, "GPGME version: %s\n", version); + gpgme_set_locale(NULL, LC_CTYPE, setlocale(LC_CTYPE, NULL)); +#ifdef LC_MESSAGES + gpgme_set_locale(NULL, LC_MESSAGES, setlocale(LC_MESSAGES, NULL)); +#endif + /* NOTE: + * The GPGME library installs a SIGPIPE signal handler automatically if + * the default signal hander is in use. The only time we set a handler + * for SIGPIPE is in dload.c, and we reset it when we are done. Given that + * we do this, we can let GPGME do its automagic. However, if we install + * a library-wide SIGPIPE handler, we will have to be careful. + */ + + /* check for OpenPGP support (should be a no-brainer, but be safe) */ + err = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP); + CHECK_ERR(); + + /* set and check engine information */ + err = gpgme_set_engine_info(GPGME_PROTOCOL_OpenPGP, NULL, sigdir); + CHECK_ERR(); + err = gpgme_get_engine_info(&enginfo); + CHECK_ERR(); + _alpm_log(handle, ALPM_LOG_DEBUG, "GPGME engine info: file=%s, home=%s\n", + enginfo->file_name, enginfo->home_dir); + + init = 1; + return 0; + +error: + _alpm_log(handle, ALPM_LOG_ERROR, _("GPGME error: %s\n"), gpgme_strerror(err)); + RET_ERR(handle, ALPM_ERR_GPGME, 1); +} + +/** + * Decode a loaded signature in base64 form. + * @param base64_data the signature to attempt to decode + * @param data the decoded data; must be freed by the caller + * @param data_len the length of the returned data + * @return 0 on success, 1 on failure to properly decode + */ +static int decode_signature(const char *base64_data, + unsigned char **data, int *data_len) { + unsigned char *usline; + int len; + + len = strlen(base64_data); + usline = (unsigned char *)base64_data; + int ret, destlen = 0; + /* get the necessary size for the buffer by passing 0 */ + ret = base64_decode(NULL, &destlen, usline, len); + if(ret != 0 && ret != POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL) { + goto error; + } + /* alloc our memory and repeat the call to decode */ + MALLOC(*data, (size_t)destlen, goto error); + ret = base64_decode(*data, &destlen, usline, len); + if(ret != 0) { + goto error; + } + *data_len = destlen; + return 0; + +error: + *data = NULL; + *data_len = 0; + return 1; +} + +/** + * Check the PGP signature for the given file path. + * If base64_sig is provided, it will be used as the signature data after + * decoding. If base64_sig is NULL, expect a signature file next to path + * (e.g. "%s.sig"). + * + * The return value will be 0 if nothing abnormal happened during the signature + * check, and -1 if an error occurred while checking signatures or if a + * signature could not be found; pm_errno will be set. Note that "abnormal" + * does not include a failed signature; the value in #result should be checked + * to determine if the signature(s) are good. + * @param handle the context handle + * @param path the full path to a file + * @param base64_sig optional PGP signature data in base64 encoding + * @result + * @return 0 in normal cases, -1 if the something failed in the check process + */ +int _alpm_gpgme_checksig(alpm_handle_t *handle, const char *path, + const char *base64_sig, alpm_sigresult_t *result) +{ + int ret = -1, sigcount; + gpgme_error_t err; + gpgme_ctx_t ctx; + gpgme_data_t filedata, sigdata; + gpgme_verify_result_t verify_result; + gpgme_signature_t gpgsig; + char *sigpath = NULL; + unsigned char *decoded_sigdata = NULL; + FILE *file = NULL, *sigfile = NULL; + + if(!path || _alpm_access(handle, NULL, path, R_OK) != 0) { + RET_ERR(handle, ALPM_ERR_NOT_A_FILE, -1); + } + + if(!result) { + RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1); + } + result->count = 0; + + if(!base64_sig) { + size_t len = strlen(path) + 5; + CALLOC(sigpath, len, sizeof(char), RET_ERR(handle, ALPM_ERR_MEMORY, -1)); + snprintf(sigpath, len, "%s.sig", path); + + if(!_alpm_access(handle, NULL, sigpath, R_OK) == 0) { + /* sigcount is 0 */ + } + } + + if(init_gpgme(handle)) { + /* pm_errno was set in gpgme_init() */ + return -1; + } + + _alpm_log(handle, ALPM_LOG_DEBUG, "checking signature for %s\n", path); + + memset(&ctx, 0, sizeof(ctx)); + memset(&sigdata, 0, sizeof(sigdata)); + memset(&filedata, 0, sizeof(filedata)); + + err = gpgme_new(&ctx); + CHECK_ERR(); + + /* create our necessary data objects to verify the signature */ + file = fopen(path, "rb"); + if(file == NULL) { + handle->pm_errno = ALPM_ERR_NOT_A_FILE; + goto error; + } + err = gpgme_data_new_from_stream(&filedata, file); + CHECK_ERR(); + + /* next create data object for the signature */ + if(base64_sig) { + /* memory-based, we loaded it from a sync DB */ + int data_len; + int decode_ret = decode_signature(base64_sig, + &decoded_sigdata, &data_len); + if(decode_ret) { + handle->pm_errno = ALPM_ERR_SIG_INVALID; + goto error; + } + err = gpgme_data_new_from_mem(&sigdata, + (char *)decoded_sigdata, data_len, 0); + } else { + /* file-based, it is on disk */ + sigfile = fopen(sigpath, "rb"); + if(sigfile == NULL) { + handle->pm_errno = ALPM_ERR_SIG_MISSING; + goto error; + } + err = gpgme_data_new_from_stream(&sigdata, sigfile); + } + CHECK_ERR(); + + /* here's where the magic happens */ + err = gpgme_op_verify(ctx, sigdata, filedata, NULL); + CHECK_ERR(); + verify_result = gpgme_op_verify_result(ctx); + CHECK_ERR(); + if(!verify_result || !verify_result->signatures) { + _alpm_log(handle, ALPM_LOG_DEBUG, "no signatures returned\n"); + handle->pm_errno = ALPM_ERR_SIG_MISSING; + goto error; + } + for(gpgsig = verify_result->signatures, sigcount = 0; + gpgsig; gpgsig = gpgsig->next, sigcount++); + _alpm_log(handle, ALPM_LOG_DEBUG, "%d signatures returned\n", sigcount); + + result->status = calloc(sigcount, sizeof(alpm_sigstatus_t)); + result->validity = calloc(sigcount, sizeof(alpm_sigvalidity_t)); + result->uid = calloc(sigcount, sizeof(char*)); + if(!result->status || !result->validity || !result->uid) { + handle->pm_errno = ALPM_ERR_MEMORY; + goto error; + } + result->count = sigcount; + + for(gpgsig = verify_result->signatures, sigcount = 0; gpgsig; + gpgsig = gpgsig->next, sigcount++) { + alpm_list_t *summary_list, *summary; + alpm_sigstatus_t status; + alpm_sigvalidity_t validity; + gpgme_key_t key; + + _alpm_log(handle, ALPM_LOG_DEBUG, "fingerprint: %s\n", gpgsig->fpr); + summary_list = list_sigsum(gpgsig->summary); + for(summary = summary_list; summary; summary = summary->next) { + _alpm_log(handle, ALPM_LOG_DEBUG, "summary: %s\n", (const char *)summary->data); + } + alpm_list_free(summary_list); + _alpm_log(handle, ALPM_LOG_DEBUG, "status: %s\n", gpgme_strerror(gpgsig->status)); + _alpm_log(handle, ALPM_LOG_DEBUG, "timestamp: %lu\n", gpgsig->timestamp); + _alpm_log(handle, ALPM_LOG_DEBUG, "exp_timestamp: %lu\n", gpgsig->exp_timestamp); + _alpm_log(handle, ALPM_LOG_DEBUG, "validity: %s; reason: %s\n", + string_validity(gpgsig->validity), + gpgme_strerror(gpgsig->validity_reason)); + + err = gpgme_get_key(ctx, gpgsig->fpr, &key, 0); + if(gpg_err_code(err) == GPG_ERR_EOF) { + _alpm_log(handle, ALPM_LOG_DEBUG, "key lookup failed, unknown key\n"); + err = GPG_ERR_NO_ERROR; + STRDUP(result->uid[sigcount], gpgsig->fpr, + handle->pm_errno = ALPM_ERR_MEMORY; goto error); + } else { + CHECK_ERR(); + if(key->uids) { + const char *uid = key->uids->uid; + STRDUP(result->uid[sigcount], uid, + handle->pm_errno = ALPM_ERR_MEMORY; goto error); + _alpm_log(handle, ALPM_LOG_DEBUG, "key user: %s\n", uid); + } + gpgme_key_unref(key); + } + + switch(gpg_err_code(gpgsig->status)) { + /* good cases */ + case GPG_ERR_NO_ERROR: + status = ALPM_SIGSTATUS_VALID; + break; + case GPG_ERR_KEY_EXPIRED: + status = ALPM_SIGSTATUS_KEY_EXPIRED; + break; + /* bad cases */ + case GPG_ERR_SIG_EXPIRED: + status = ALPM_SIGSTATUS_SIG_EXPIRED; + break; + case GPG_ERR_NO_PUBKEY: + status = ALPM_SIGSTATUS_KEY_UNKNOWN; + break; + case GPG_ERR_BAD_SIGNATURE: + default: + status = ALPM_SIGSTATUS_INVALID; + break; + } + + if(status == ALPM_SIGSTATUS_VALID + || status == ALPM_SIGSTATUS_KEY_EXPIRED) { + switch(gpgsig->validity) { + case GPGME_VALIDITY_ULTIMATE: + case GPGME_VALIDITY_FULL: + validity = ALPM_SIGVALIDITY_FULL; + break; + case GPGME_VALIDITY_MARGINAL: + validity = ALPM_SIGVALIDITY_MARGINAL; + break; + case GPGME_VALIDITY_NEVER: + validity = ALPM_SIGVALIDITY_NEVER; + break; + case GPGME_VALIDITY_UNKNOWN: + case GPGME_VALIDITY_UNDEFINED: + default: + validity = ALPM_SIGVALIDITY_UNKNOWN; + break; + } + } else { + validity = ALPM_SIGVALIDITY_NEVER; + } + + result->status[sigcount] = status; + result->validity[sigcount] = validity; + } + + ret = 0; + +error: + gpgme_data_release(sigdata); + gpgme_data_release(filedata); + gpgme_release(ctx); + if(sigfile) { + fclose(sigfile); + } + if(file) { + fclose(file); + } + FREE(sigpath); + FREE(decoded_sigdata); + if(gpg_err_code(err) != GPG_ERR_NO_ERROR) { + _alpm_log(handle, ALPM_LOG_ERROR, _("GPGME error: %s\n"), gpgme_strerror(err)); + RET_ERR(handle, ALPM_ERR_GPGME, -1); + } + return ret; +} +#else +int _alpm_gpgme_checksig(alpm_handle_t UNUSED *handle, const char UNUSED *path, + const char UNUSED *base64_sig, alpm_sigresult_t UNUSED *result) +{ + return -1; +} +#endif + +int _alpm_check_pgp_helper(alpm_handle_t *handle, const char *path, + const char *base64_sig, int optional, int marginal, int unknown, + enum _alpm_errno_t invalid_err) +{ + alpm_sigresult_t result; + int ret; + + memset(&result, 0, sizeof(result)); + + _alpm_log(handle, ALPM_LOG_DEBUG, "checking signatures for %s\n", path); + ret = _alpm_gpgme_checksig(handle, path, base64_sig, &result); + if(ret && handle->pm_errno == ALPM_ERR_SIG_MISSING) { + if(optional) { + _alpm_log(handle, ALPM_LOG_DEBUG, "missing optional signature\n"); + handle->pm_errno = 0; + ret = 0; + } else { + _alpm_log(handle, ALPM_LOG_DEBUG, "missing required signature\n"); + /* ret will already be -1 */ + } + } else if(ret) { + _alpm_log(handle, ALPM_LOG_DEBUG, "signature check failed\n"); + /* ret will already be -1 */ + } else { + int num; + for(num = 0; !ret && num < result.count; num++) { + switch(result.status[num]) { + case ALPM_SIGSTATUS_VALID: + case ALPM_SIGSTATUS_KEY_EXPIRED: + _alpm_log(handle, ALPM_LOG_DEBUG, "signature is valid\n"); + switch(result.validity[num]) { + case ALPM_SIGVALIDITY_FULL: + _alpm_log(handle, ALPM_LOG_DEBUG, "signature is fully trusted\n"); + break; + case ALPM_SIGVALIDITY_MARGINAL: + _alpm_log(handle, ALPM_LOG_DEBUG, "signature is marginal trust\n"); + if(!marginal) { + ret = -1; + } + break; + case ALPM_SIGVALIDITY_UNKNOWN: + _alpm_log(handle, ALPM_LOG_DEBUG, "signature is unknown trust\n"); + if(!unknown) { + ret = -1; + } + break; + case ALPM_SIGVALIDITY_NEVER: + _alpm_log(handle, ALPM_LOG_DEBUG, "signature should never be trusted\n"); + ret = -1; + break; + } + break; + case ALPM_SIGSTATUS_SIG_EXPIRED: + case ALPM_SIGSTATUS_KEY_UNKNOWN: + case ALPM_SIGSTATUS_INVALID: + _alpm_log(handle, ALPM_LOG_DEBUG, "signature is not valid\n"); + ret = -1; + break; + } + } + + if(ret) { + handle->pm_errno = invalid_err; + } + } + + alpm_sigresult_cleanup(&result); + return ret; +} + +/** + * Check the PGP signature for the given package file. + * @param pkg the package to check + * @return a int value : 0 (valid), 1 (invalid), -1 (an error occurred) + */ +int SYMEXPORT alpm_pkg_check_pgp_signature(alpm_pkg_t *pkg, + alpm_sigresult_t *result) +{ + ASSERT(pkg != NULL, return -1); + ASSERT(result != NULL, RET_ERR(pkg->handle, ALPM_ERR_WRONG_ARGS, -1)); + pkg->handle->pm_errno = 0; + + return _alpm_gpgme_checksig(pkg->handle, alpm_pkg_get_filename(pkg), + pkg->base64_sig, result); +} + +/** + * Check the PGP signature for the given database. + * @param db the database to check + * @return a int value : 0 (valid), 1 (invalid), -1 (an error occurred) + */ +int SYMEXPORT alpm_db_check_pgp_signature(alpm_db_t *db, + alpm_sigresult_t *result) +{ + ASSERT(db != NULL, return -1); + ASSERT(result != NULL, RET_ERR(db->handle, ALPM_ERR_WRONG_ARGS, -1)); + db->handle->pm_errno = 0; + + return _alpm_gpgme_checksig(db->handle, _alpm_db_path(db), NULL, result); +} + +int SYMEXPORT alpm_sigresult_cleanup(alpm_sigresult_t *result) +{ + ASSERT(result != NULL, return -1); + /* Because it is likely result is on the stack, uid and status may have bogus + * values in the struct. Only look at them if count is greater than 0. */ + if(result->count > 0) { + free(result->status); + if(result->uid) { + int i; + for(i = 0; i < result->count; i++) { + free(result->uid[i]); + } + free(result->uid); + } + } + return 0; +} + +/* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/signing.h b/lib/libalpm/signing.h new file mode 100644 index 00000000..22f6357e --- /dev/null +++ b/lib/libalpm/signing.h @@ -0,0 +1,32 @@ +/* + * signing.h + * + * Copyright (c) 2008-2011 Pacman Development Team <pacman-dev@archlinux.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#ifndef _ALPM_SIGNING_H +#define _ALPM_SIGNING_H + +#include "alpm.h" + +int _alpm_gpgme_checksig(alpm_handle_t *handle, const char *path, + const char *base64_sig, alpm_sigresult_t *result); +int _alpm_check_pgp_helper(alpm_handle_t *handle, const char *path, + const char *base64_sig, int optional, int marginal, int unknown, + enum _alpm_errno_t invalid_err); + +#endif /* _ALPM_SIGNING_H */ + +/* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c index f83b0ef9..ca7e6579 100644 --- a/lib/libalpm/sync.c +++ b/lib/libalpm/sync.c @@ -26,11 +26,9 @@ #include <sys/types.h> /* off_t */ #include <stdlib.h> #include <stdio.h> -#include <fcntl.h> #include <string.h> #include <stdint.h> /* intmax_t */ #include <unistd.h> -#include <time.h> #include <limits.h> /* libalpm */ @@ -50,144 +48,149 @@ #include "delta.h" #include "remove.h" #include "diskspace.h" +#include "signing.h" /** Check for new version of pkg in sync repos * (only the first occurrence is considered in sync) */ -pmpkg_t SYMEXPORT *alpm_sync_newversion(pmpkg_t *pkg, alpm_list_t *dbs_sync) +alpm_pkg_t SYMEXPORT *alpm_sync_newversion(alpm_pkg_t *pkg, alpm_list_t *dbs_sync) { - ASSERT(pkg != NULL, return(NULL)); - alpm_list_t *i; - pmpkg_t *spkg = NULL; + alpm_pkg_t *spkg = NULL; + + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; for(i = dbs_sync; !spkg && i; i = i->next) { spkg = _alpm_db_get_pkgfromcache(i->data, alpm_pkg_get_name(pkg)); } if(spkg == NULL) { - _alpm_log(PM_LOG_DEBUG, "'%s' not found in sync db => no upgrade\n", + _alpm_log(pkg->handle, ALPM_LOG_DEBUG, "'%s' not found in sync db => no upgrade\n", alpm_pkg_get_name(pkg)); - return(NULL); + return NULL; } /* compare versions and see if spkg is an upgrade */ if(_alpm_pkg_compare_versions(spkg, pkg) > 0) { - _alpm_log(PM_LOG_DEBUG, "new version of '%s' found (%s => %s)\n", + _alpm_log(pkg->handle, ALPM_LOG_DEBUG, "new version of '%s' found (%s => %s)\n", alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg), alpm_pkg_get_version(spkg)); - return(spkg); + return spkg; } /* spkg is not an upgrade */ - return(NULL); + return NULL; } -/** Search for packages to upgrade and add them to the transaction. - * @return 0 on success, -1 on error (pm_errno is set accordingly) - */ -int SYMEXPORT alpm_sync_sysupgrade(int enable_downgrade) +/** Search for packages to upgrade and add them to the transaction. */ +int SYMEXPORT alpm_sync_sysupgrade(alpm_handle_t *handle, int enable_downgrade) { alpm_list_t *i, *j, *k; - pmtrans_t *trans; - pmdb_t *db_local; + alpm_trans_t *trans; + alpm_db_t *db_local; alpm_list_t *dbs_sync; - ALPM_LOG_FUNC; - - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + CHECK_HANDLE(handle, return -1); trans = handle->trans; db_local = handle->db_local; dbs_sync = handle->dbs_sync; - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1)); + ASSERT(trans != NULL, RET_ERR(handle, ALPM_ERR_TRANS_NULL, -1)); + ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(handle, ALPM_ERR_TRANS_NOT_INITIALIZED, -1)); - _alpm_log(PM_LOG_DEBUG, "checking for package upgrades\n"); + _alpm_log(handle, ALPM_LOG_DEBUG, "checking for package upgrades\n"); for(i = _alpm_db_get_pkgcache(db_local); i; i = i->next) { - pmpkg_t *lpkg = i->data; + alpm_pkg_t *lpkg = i->data; if(_alpm_pkg_find(trans->add, lpkg->name)) { - _alpm_log(PM_LOG_DEBUG, "%s is already in the target list -- skipping\n", lpkg->name); + _alpm_log(handle, ALPM_LOG_DEBUG, "%s is already in the target list -- skipping\n", lpkg->name); continue; } /* Search for literal then replacers in each sync database. * If found, don't check other databases */ for(j = dbs_sync; j; j = j->next) { - pmdb_t *sdb = j->data; + alpm_db_t *sdb = j->data; /* Check sdb */ - pmpkg_t *spkg = _alpm_db_get_pkgfromcache(sdb, lpkg->name); - if(spkg) { /* 1. literal was found in sdb */ + alpm_pkg_t *spkg = _alpm_db_get_pkgfromcache(sdb, lpkg->name); + if(spkg) { + /* 1. literal was found in sdb */ int cmp = _alpm_pkg_compare_versions(spkg, lpkg); if(cmp > 0) { - _alpm_log(PM_LOG_DEBUG, "new version of '%s' found (%s => %s)\n", + _alpm_log(handle, ALPM_LOG_DEBUG, "new version of '%s' found (%s => %s)\n", lpkg->name, lpkg->version, spkg->version); /* check IgnorePkg/IgnoreGroup */ - if(_alpm_pkg_should_ignore(spkg) || _alpm_pkg_should_ignore(lpkg)) { - _alpm_log(PM_LOG_WARNING, _("%s: ignoring package upgrade (%s => %s)\n"), - lpkg->name, lpkg->version, spkg->version); + if(_alpm_pkg_should_ignore(handle, spkg) + || _alpm_pkg_should_ignore(handle, lpkg)) { + _alpm_log(handle, ALPM_LOG_WARNING, _("%s: ignoring package upgrade (%s => %s)\n"), + lpkg->name, lpkg->version, spkg->version); } else { - _alpm_log(PM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n", + _alpm_log(handle, ALPM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n", spkg->name, spkg->version); trans->add = alpm_list_add(trans->add, spkg); } } else if(cmp < 0) { if(enable_downgrade) { /* check IgnorePkg/IgnoreGroup */ - if(_alpm_pkg_should_ignore(spkg) || _alpm_pkg_should_ignore(lpkg)) { - _alpm_log(PM_LOG_WARNING, _("%s: ignoring package downgrade (%s => %s)\n"), + if(_alpm_pkg_should_ignore(handle, spkg) + || _alpm_pkg_should_ignore(handle, lpkg)) { + _alpm_log(handle, ALPM_LOG_WARNING, _("%s: ignoring package downgrade (%s => %s)\n"), lpkg->name, lpkg->version, spkg->version); } else { - _alpm_log(PM_LOG_WARNING, _("%s: downgrading from version %s to version %s\n"), + _alpm_log(handle, ALPM_LOG_WARNING, _("%s: downgrading from version %s to version %s\n"), lpkg->name, lpkg->version, spkg->version); trans->add = alpm_list_add(trans->add, spkg); } } else { - _alpm_log(PM_LOG_WARNING, _("%s: local (%s) is newer than %s (%s)\n"), + _alpm_log(handle, ALPM_LOG_WARNING, _("%s: local (%s) is newer than %s (%s)\n"), lpkg->name, lpkg->version, sdb->treename, spkg->version); } } - break; /* jump to next local package */ - } else { /* 2. search for replacers in sdb */ + /* jump to next local package */ + break; + } else { + /* 2. search for replacers in sdb */ int found = 0; for(k = _alpm_db_get_pkgcache(sdb); k; k = k->next) { spkg = k->data; if(alpm_list_find_str(alpm_pkg_get_replaces(spkg), lpkg->name)) { found = 1; /* check IgnorePkg/IgnoreGroup */ - if(_alpm_pkg_should_ignore(spkg) || _alpm_pkg_should_ignore(lpkg)) { - _alpm_log(PM_LOG_WARNING, _("ignoring package replacement (%s-%s => %s-%s)\n"), + if(_alpm_pkg_should_ignore(handle, spkg) + || _alpm_pkg_should_ignore(handle, lpkg)) { + _alpm_log(handle, ALPM_LOG_WARNING, _("ignoring package replacement (%s-%s => %s-%s)\n"), lpkg->name, lpkg->version, spkg->name, spkg->version); continue; } int doreplace = 0; - QUESTION(trans, PM_TRANS_CONV_REPLACE_PKG, lpkg, spkg, sdb->treename, &doreplace); + QUESTION(trans, ALPM_TRANS_CONV_REPLACE_PKG, lpkg, spkg, sdb->treename, &doreplace); if(!doreplace) { continue; } /* If spkg is already in the target list, we append lpkg to spkg's * removes list */ - pmpkg_t *tpkg = _alpm_pkg_find(trans->add, spkg->name); + alpm_pkg_t *tpkg = _alpm_pkg_find(trans->add, spkg->name); if(tpkg) { /* sanity check, multiple repos can contain spkg->name */ if(tpkg->origin_data.db != sdb) { - _alpm_log(PM_LOG_WARNING, _("cannot replace %s by %s\n"), + _alpm_log(handle, ALPM_LOG_WARNING, _("cannot replace %s by %s\n"), lpkg->name, spkg->name); continue; } - _alpm_log(PM_LOG_DEBUG, "appending %s to the removes list of %s\n", + _alpm_log(handle, ALPM_LOG_DEBUG, "appending %s to the removes list of %s\n", lpkg->name, tpkg->name); tpkg->removes = alpm_list_add(tpkg->removes, lpkg); /* check the to-be-replaced package's reason field */ - if(alpm_pkg_get_reason(lpkg) == PM_PKG_REASON_EXPLICIT) { - tpkg->reason = PM_PKG_REASON_EXPLICIT; + if(alpm_pkg_get_reason(lpkg) == ALPM_PKG_REASON_EXPLICIT) { + tpkg->reason = ALPM_PKG_REASON_EXPLICIT; } - } else { /* add spkg to the target list */ + } else { + /* add spkg to the target list */ /* copy over reason */ spkg->reason = alpm_pkg_get_reason(lpkg); spkg->removes = alpm_list_add(NULL, lpkg); - _alpm_log(PM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n", + _alpm_log(handle, ALPM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n", spkg->name, spkg->version); trans->add = alpm_list_add(trans->add, spkg); } @@ -200,38 +203,38 @@ int SYMEXPORT alpm_sync_sysupgrade(int enable_downgrade) } } - return(0); + return 0; } /** Find group members across a list of databases. * If a member exists in several databases, only the first database is used. * IgnorePkg is also handled. - * @param dbs the list of pmdb_t * + * @param dbs the list of alpm_db_t * * @pram name the name of the group - * @return the list of pmpkg_t * (caller is responsible for alpm_list_free) + * @return the list of alpm_pkg_t * (caller is responsible for alpm_list_free) */ -alpm_list_t SYMEXPORT *alpm_find_grp_pkgs(alpm_list_t *dbs, +alpm_list_t SYMEXPORT *alpm_find_group_pkgs(alpm_list_t *dbs, const char *name) { alpm_list_t *i, *j, *pkgs = NULL, *ignorelist = NULL; for(i = dbs; i; i = i->next) { - pmdb_t *db = i->data; - pmgrp_t *grp = alpm_db_readgrp(db, name); + alpm_db_t *db = i->data; + alpm_group_t *grp = alpm_db_readgroup(db, name); if(!grp) continue; - for(j = alpm_grp_get_pkgs(grp); j; j = j->next) { - pmpkg_t *pkg = j->data; + for(j = grp->packages; j; j = j->next) { + alpm_pkg_t *pkg = j->data; if(_alpm_pkg_find(ignorelist, alpm_pkg_get_name(pkg))) { continue; } - if(_alpm_pkg_should_ignore(pkg)) { + if(_alpm_pkg_should_ignore(db->handle, pkg)) { ignorelist = alpm_list_add(ignorelist, pkg); int install = 0; - QUESTION(handle->trans, PM_TRANS_CONV_INSTALL_IGNOREPKG, pkg, + QUESTION(db->handle->trans, ALPM_TRANS_CONV_INSTALL_IGNOREPKG, pkg, NULL, NULL, &install); if(!install) continue; @@ -242,28 +245,29 @@ alpm_list_t SYMEXPORT *alpm_find_grp_pkgs(alpm_list_t *dbs, } } alpm_list_free(ignorelist); - return(pkgs); + return pkgs; } /** Compute the size of the files that will be downloaded to install a * package. * @param newpkg the new package to upgrade to */ -static int compute_download_size(pmpkg_t *newpkg) +static int compute_download_size(alpm_pkg_t *newpkg) { const char *fname; char *fpath; off_t size = 0; + alpm_handle_t *handle = newpkg->handle; if(newpkg->origin != PKG_FROM_SYNCDB) { newpkg->infolevel |= INFRQ_DSIZE; newpkg->download_size = 0; - return(0); + return 0; } fname = alpm_pkg_get_filename(newpkg); - ASSERT(fname != NULL, RET_ERR(PM_ERR_PKG_INVALID_NAME, -1)); - fpath = _alpm_filecache_find(fname); + ASSERT(fname != NULL, RET_ERR(handle, ALPM_ERR_PKG_INVALID_NAME, -1)); + fpath = _alpm_filecache_find(handle, fname); if(fpath) { FREE(fpath); @@ -272,16 +276,16 @@ static int compute_download_size(pmpkg_t *newpkg) off_t dltsize; off_t pkgsize = alpm_pkg_get_size(newpkg); - dltsize = _alpm_shortest_delta_path( + dltsize = _alpm_shortest_delta_path(handle, alpm_pkg_get_deltas(newpkg), alpm_pkg_get_filename(newpkg), &newpkg->delta_path); if(newpkg->delta_path && (dltsize < pkgsize * MAX_DELTA_RATIO)) { - _alpm_log(PM_LOG_DEBUG, "using delta size\n"); + _alpm_log(handle, ALPM_LOG_DEBUG, "using delta size\n"); size = dltsize; } else { - _alpm_log(PM_LOG_DEBUG, "using package size\n"); + _alpm_log(handle, ALPM_LOG_DEBUG, "using package size\n"); size = alpm_pkg_get_size(newpkg); alpm_list_free(newpkg->delta_path); newpkg->delta_path = NULL; @@ -290,42 +294,46 @@ static int compute_download_size(pmpkg_t *newpkg) size = alpm_pkg_get_size(newpkg); } - _alpm_log(PM_LOG_DEBUG, "setting download size %jd for pkg %s\n", + _alpm_log(handle, ALPM_LOG_DEBUG, "setting download size %jd for pkg %s\n", (intmax_t)size, alpm_pkg_get_name(newpkg)); newpkg->infolevel |= INFRQ_DSIZE; newpkg->download_size = size; - return(0); + return 0; } -int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, alpm_list_t **data) +int _alpm_sync_prepare(alpm_handle_t *handle, alpm_list_t **data) { + alpm_list_t *i, *j; alpm_list_t *deps = NULL; alpm_list_t *unresolvable = NULL; - alpm_list_t *i, *j; alpm_list_t *remove = NULL; int ret = 0; - - ALPM_LOG_FUNC; - - ASSERT(db_local != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); + alpm_trans_t *trans = handle->trans; if(data) { *data = NULL; } - if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) { + /* ensure all sync database are valid since we will be using them */ + for(i = handle->dbs_sync; i; i = i->next) { + const alpm_db_t *db = i->data; + if(!(db->status & DB_STATUS_VALID)) { + RET_ERR(handle, ALPM_ERR_DB_INVALID, -1); + } + } + + if(!(trans->flags & ALPM_TRANS_FLAG_NODEPS)) { alpm_list_t *resolved = NULL; /* target list after resolvedeps */ /* Build up list by repeatedly resolving each transaction package */ /* Resolve targets dependencies */ - EVENT(trans, PM_TRANS_EVT_RESOLVEDEPS_START, NULL, NULL); - _alpm_log(PM_LOG_DEBUG, "resolving target's dependencies\n"); + EVENT(trans, ALPM_TRANS_EVT_RESOLVEDEPS_START, NULL, NULL); + _alpm_log(handle, ALPM_LOG_DEBUG, "resolving target's dependencies\n"); /* build remove list for resolvedeps */ for(i = trans->add; i; i = i->next) { - pmpkg_t *spkg = i->data; + alpm_pkg_t *spkg = i->data; for(j = spkg->removes; j; j = j->next) { remove = alpm_list_add(remove, j->data); } @@ -333,14 +341,14 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync /* Compute the fake local database for resolvedeps (partial fix for the * phonon/qt issue) */ - alpm_list_t *localpkgs = alpm_list_diff(_alpm_db_get_pkgcache(db_local), + alpm_list_t *localpkgs = alpm_list_diff(_alpm_db_get_pkgcache(handle->db_local), trans->add, _alpm_pkg_cmp); /* Resolve packages in the transaction one at a time, in addition building up a list of packages which could not be resolved. */ for(i = trans->add; i; i = i->next) { - pmpkg_t *pkg = i->data; - if(_alpm_resolvedeps(localpkgs, dbs_sync, pkg, trans->add, + alpm_pkg_t *pkg = i->data; + if(_alpm_resolvedeps(handle, localpkgs, pkg, trans->add, &resolved, remove, data) == -1) { unresolvable = alpm_list_add(unresolvable, pkg); } @@ -353,14 +361,14 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync see if they'd like to ignore them rather than failing the sync */ if(unresolvable != NULL) { int remove_unresolvable = 0; - QUESTION(handle->trans, PM_TRANS_CONV_REMOVE_PKGS, unresolvable, + QUESTION(trans, ALPM_TRANS_CONV_REMOVE_PKGS, unresolvable, NULL, NULL, &remove_unresolvable); - if (remove_unresolvable) { + if(remove_unresolvable) { /* User wants to remove the unresolvable packages from the transaction. The packages will be removed from the actual transaction when the transaction packages are replaced with a dependency-reordered list below */ - pm_errno = 0; /* pm_errno was set by resolvedeps */ + handle->pm_errno = 0; /* pm_errno was set by resolvedeps */ if(data) { alpm_list_free_inner(*data, (alpm_list_fn_free)_alpm_depmiss_free); alpm_list_free(*data); @@ -376,9 +384,9 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync /* Set DEPEND reason for pulled packages */ for(i = resolved; i; i = i->next) { - pmpkg_t *pkg = i->data; + alpm_pkg_t *pkg = i->data; if(!_alpm_pkg_find(trans->add, pkg->name)) { - pkg->reason = PM_PKG_REASON_DEPEND; + pkg->reason = ALPM_PKG_REASON_DEPEND; } } @@ -388,25 +396,25 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync /* re-order w.r.t. dependencies */ alpm_list_free(trans->add); - trans->add = _alpm_sortbydeps(resolved, 0); + trans->add = _alpm_sortbydeps(handle, resolved, 0); alpm_list_free(resolved); - EVENT(trans, PM_TRANS_EVT_RESOLVEDEPS_DONE, NULL, NULL); + EVENT(trans, ALPM_TRANS_EVT_RESOLVEDEPS_DONE, NULL, NULL); } - if(!(trans->flags & PM_TRANS_FLAG_NOCONFLICTS)) { + if(!(trans->flags & ALPM_TRANS_FLAG_NOCONFLICTS)) { /* check for inter-conflicts and whatnot */ - EVENT(trans, PM_TRANS_EVT_INTERCONFLICTS_START, NULL, NULL); + EVENT(trans, ALPM_TRANS_EVT_INTERCONFLICTS_START, NULL, NULL); - _alpm_log(PM_LOG_DEBUG, "looking for conflicts\n"); + _alpm_log(handle, ALPM_LOG_DEBUG, "looking for conflicts\n"); /* 1. check for conflicts in the target list */ - _alpm_log(PM_LOG_DEBUG, "check targets vs targets\n"); - deps = _alpm_innerconflicts(trans->add); + _alpm_log(handle, ALPM_LOG_DEBUG, "check targets vs targets\n"); + deps = _alpm_innerconflicts(handle, trans->add); for(i = deps; i; i = i->next) { - pmconflict_t *conflict = i->data; - pmpkg_t *rsync, *sync, *sync1, *sync2; + alpm_conflict_t *conflict = i->data; + alpm_pkg_t *rsync, *sync, *sync1, *sync2; /* have we already removed one of the conflicting targets? */ sync1 = _alpm_pkg_find(trans->add, conflict->package1); @@ -415,12 +423,12 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync continue; } - _alpm_log(PM_LOG_DEBUG, "conflicting packages in the sync list: '%s' <-> '%s'\n", + _alpm_log(handle, ALPM_LOG_DEBUG, "conflicting packages in the sync list: '%s' <-> '%s'\n", conflict->package1, conflict->package2); /* if sync1 provides sync2, we remove sync2 from the targets, and vice versa */ - pmdepend_t *dep1 = _alpm_splitdep(conflict->package1); - pmdepend_t *dep2 = _alpm_splitdep(conflict->package2); + alpm_depend_t *dep1 = _alpm_splitdep(conflict->package1); + alpm_depend_t *dep2 = _alpm_splitdep(conflict->package2); if(_alpm_depcmp(sync1, dep2)) { rsync = sync2; sync = sync1; @@ -428,11 +436,11 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync rsync = sync1; sync = sync2; } else { - _alpm_log(PM_LOG_ERROR, _("unresolvable package conflicts detected\n")); - pm_errno = PM_ERR_CONFLICTING_DEPS; + _alpm_log(handle, ALPM_LOG_ERROR, _("unresolvable package conflicts detected\n")); + handle->pm_errno = ALPM_ERR_CONFLICTING_DEPS; ret = -1; if(data) { - pmconflict_t *newconflict = _alpm_conflict_dup(conflict); + alpm_conflict_t *newconflict = _alpm_conflict_dup(conflict); if(newconflict) { *data = alpm_list_add(*data, newconflict); } @@ -447,7 +455,7 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync _alpm_dep_free(dep2); /* Prints warning */ - _alpm_log(PM_LOG_WARNING, + _alpm_log(handle, ALPM_LOG_WARNING, _("removing '%s' from target list because it conflicts with '%s'\n"), rsync->name, sync->name); trans->add = alpm_list_remove(trans->add, rsync, _alpm_pkg_cmp, NULL); @@ -460,17 +468,17 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync deps = NULL; /* 2. we check for target vs db conflicts (and resolve)*/ - _alpm_log(PM_LOG_DEBUG, "check targets vs db and db vs targets\n"); - deps = _alpm_outerconflicts(db_local, trans->add); + _alpm_log(handle, ALPM_LOG_DEBUG, "check targets vs db and db vs targets\n"); + deps = _alpm_outerconflicts(handle->db_local, trans->add); for(i = deps; i; i = i->next) { - pmconflict_t *conflict = i->data; + alpm_conflict_t *conflict = i->data; /* if conflict->package2 (the local package) is not elected for removal, we ask the user */ int found = 0; for(j = trans->add; j && !found; j = j->next) { - pmpkg_t *spkg = j->data; + alpm_pkg_t *spkg = j->data; if(_alpm_pkg_find(spkg->removes, conflict->package2)) { found = 1; } @@ -479,24 +487,24 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync continue; } - _alpm_log(PM_LOG_DEBUG, "package '%s' conflicts with '%s'\n", + _alpm_log(handle, ALPM_LOG_DEBUG, "package '%s' conflicts with '%s'\n", conflict->package1, conflict->package2); - pmpkg_t *sync = _alpm_pkg_find(trans->add, conflict->package1); - pmpkg_t *local = _alpm_db_get_pkgfromcache(db_local, conflict->package2); + alpm_pkg_t *sync = _alpm_pkg_find(trans->add, conflict->package1); + alpm_pkg_t *local = _alpm_db_get_pkgfromcache(handle->db_local, conflict->package2); int doremove = 0; - QUESTION(trans, PM_TRANS_CONV_CONFLICT_PKG, conflict->package1, + QUESTION(trans, ALPM_TRANS_CONV_CONFLICT_PKG, conflict->package1, conflict->package2, conflict->reason, &doremove); if(doremove) { /* append to the removes list */ - _alpm_log(PM_LOG_DEBUG, "electing '%s' for removal\n", conflict->package2); + _alpm_log(handle, ALPM_LOG_DEBUG, "electing '%s' for removal\n", conflict->package2); sync->removes = alpm_list_add(sync->removes, local); } else { /* abort */ - _alpm_log(PM_LOG_ERROR, _("unresolvable package conflicts detected\n")); - pm_errno = PM_ERR_CONFLICTING_DEPS; + _alpm_log(handle, ALPM_LOG_ERROR, _("unresolvable package conflicts detected\n")); + handle->pm_errno = ALPM_ERR_CONFLICTING_DEPS; ret = -1; if(data) { - pmconflict_t *newconflict = _alpm_conflict_dup(conflict); + alpm_conflict_t *newconflict = _alpm_conflict_dup(conflict); if(newconflict) { *data = alpm_list_add(*data, newconflict); } @@ -506,28 +514,29 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync goto cleanup; } } - EVENT(trans, PM_TRANS_EVT_INTERCONFLICTS_DONE, NULL, NULL); + EVENT(trans, ALPM_TRANS_EVT_INTERCONFLICTS_DONE, NULL, NULL); alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_conflict_free); alpm_list_free(deps); } /* Build trans->remove list */ for(i = trans->add; i; i = i->next) { - pmpkg_t *spkg = i->data; + alpm_pkg_t *spkg = i->data; for(j = spkg->removes; j; j = j->next) { - pmpkg_t *rpkg = j->data; + alpm_pkg_t *rpkg = j->data; if(!_alpm_pkg_find(trans->remove, rpkg->name)) { - _alpm_log(PM_LOG_DEBUG, "adding '%s' to remove list\n", rpkg->name); + _alpm_log(handle, ALPM_LOG_DEBUG, "adding '%s' to remove list\n", rpkg->name); trans->remove = alpm_list_add(trans->remove, _alpm_pkg_dup(rpkg)); } } } - if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) { - _alpm_log(PM_LOG_DEBUG, "checking dependencies\n"); - deps = alpm_checkdeps(_alpm_db_get_pkgcache(db_local), 1, trans->remove, trans->add); + if(!(trans->flags & ALPM_TRANS_FLAG_NODEPS)) { + _alpm_log(handle, ALPM_LOG_DEBUG, "checking dependencies\n"); + deps = alpm_checkdeps(handle, _alpm_db_get_pkgcache(handle->db_local), + trans->remove, trans->add, 1); if(deps) { - pm_errno = PM_ERR_UNSATISFIED_DEPS; + handle->pm_errno = ALPM_ERR_UNSATISFIED_DEPS; ret = -1; if(data) { *data = deps; @@ -540,7 +549,7 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync } for(i = trans->add; i; i = i->next) { /* update download size field */ - pmpkg_t *spkg = i->data; + alpm_pkg_t *spkg = i->data; if(compute_download_size(spkg) != 0) { ret = -1; goto cleanup; @@ -551,7 +560,7 @@ cleanup: alpm_list_free(unresolvable); alpm_list_free(remove); - return(ret); + return ret; } /** Returns the size of the files that will be downloaded to install a @@ -559,18 +568,18 @@ cleanup: * @param newpkg the new package to upgrade to * @return the size of the download */ -off_t SYMEXPORT alpm_pkg_download_size(pmpkg_t *newpkg) +off_t SYMEXPORT alpm_pkg_download_size(alpm_pkg_t *newpkg) { if(!(newpkg->infolevel & INFRQ_DSIZE)) { compute_download_size(newpkg); } - return(newpkg->download_size); + return newpkg->download_size; } static int endswith(const char *filename, const char *extension) { const char *s = filename + strlen(filename) - strlen(extension); - return(strcmp(s, extension) == 0); + return strcmp(s, extension) == 0; } /** Applies delta files to create an upgraded package file. @@ -578,18 +587,19 @@ static int endswith(const char *filename, const char *extension) * All intermediate files are deleted, leaving only the starting and * ending package files. * - * @param trans the transaction + * @param handle the context handle * * @return 0 if all delta files were able to be applied, 1 otherwise. */ -static int apply_deltas(pmtrans_t *trans) +static int apply_deltas(alpm_handle_t *handle) { alpm_list_t *i; int ret = 0; - const char *cachedir = _alpm_filecache_setup(); + const char *cachedir = _alpm_filecache_setup(handle); + alpm_trans_t *trans = handle->trans; for(i = trans->add; i; i = i->next) { - pmpkg_t *spkg = i->data; + alpm_pkg_t *spkg = i->data; alpm_list_t *delta_path = spkg->delta_path; alpm_list_t *dlts = NULL; @@ -598,23 +608,23 @@ static int apply_deltas(pmtrans_t *trans) } for(dlts = delta_path; dlts; dlts = dlts->next) { - pmdelta_t *d = dlts->data; + alpm_delta_t *d = dlts->data; char *delta, *from, *to; char command[PATH_MAX]; size_t len = 0; - delta = _alpm_filecache_find(d->delta); + delta = _alpm_filecache_find(handle, d->delta); /* the initial package might be in a different cachedir */ if(dlts == delta_path) { - from = _alpm_filecache_find(d->from); + from = _alpm_filecache_find(handle, d->from); } else { /* len = cachedir len + from len + '/' + null */ len = strlen(cachedir) + strlen(d->from) + 2; - CALLOC(from, len, sizeof(char), RET_ERR(PM_ERR_MEMORY, 1)); + CALLOC(from, len, sizeof(char), RET_ERR(handle, ALPM_ERR_MEMORY, 1)); snprintf(from, len, "%s/%s", cachedir, d->from); } len = strlen(cachedir) + strlen(d->to) + 2; - CALLOC(to, len, sizeof(char), RET_ERR(PM_ERR_MEMORY, 1)); + CALLOC(to, len, sizeof(char), RET_ERR(handle, ALPM_ERR_MEMORY, 1)); snprintf(to, len, "%s/%s", cachedir, d->to); /* build the patch command */ @@ -625,13 +635,13 @@ static int apply_deltas(pmtrans_t *trans) snprintf(command, PATH_MAX, "xdelta3 -d -q -s %s %s %s", from, delta, to); } - _alpm_log(PM_LOG_DEBUG, "command: %s\n", command); + _alpm_log(handle, ALPM_LOG_DEBUG, "command: %s\n", command); - EVENT(trans, PM_TRANS_EVT_DELTA_PATCH_START, d->to, d->delta); + EVENT(trans, ALPM_TRANS_EVT_DELTA_PATCH_START, d->to, d->delta); int retval = system(command); if(retval == 0) { - EVENT(trans, PM_TRANS_EVT_DELTA_PATCH_DONE, NULL, NULL); + EVENT(trans, ALPM_TRANS_EVT_DELTA_PATCH_DONE, NULL, NULL); /* delete the delta file */ unlink(delta); @@ -649,14 +659,15 @@ static int apply_deltas(pmtrans_t *trans) if(retval != 0) { /* one delta failed for this package, cancel the remaining ones */ - EVENT(trans, PM_TRANS_EVT_DELTA_PATCH_FAILED, NULL, NULL); + EVENT(trans, ALPM_TRANS_EVT_DELTA_PATCH_FAILED, NULL, NULL); + handle->pm_errno = ALPM_ERR_DLT_PATCHFAILED; ret = 1; break; } } } - return(ret); + return ret; } /** Compares the md5sum of a file to the expected value. @@ -665,50 +676,73 @@ static int apply_deltas(pmtrans_t *trans) * should be deleted. * * @param trans the transaction - * @param filename the filename of the file to test + * @param filename the absolute path of the file to test * @param md5sum the expected md5sum of the file * * @return 0 if the md5sum matched, 1 if not, -1 in case of errors */ -static int test_md5sum(pmtrans_t *trans, const char *filename, +static int test_md5sum(alpm_trans_t *trans, const char *filepath, const char *md5sum) { - char *filepath; - int ret; - - filepath = _alpm_filecache_find(filename); - - ret = _alpm_test_md5sum(filepath, md5sum); - + int ret = _alpm_test_md5sum(filepath, md5sum); if(ret == 1) { int doremove = 0; - QUESTION(trans, PM_TRANS_CONV_CORRUPTED_PKG, (char *)filename, + QUESTION(trans, ALPM_TRANS_CONV_CORRUPTED_PKG, (char *)filepath, NULL, NULL, &doremove); if(doremove) { unlink(filepath); } } - FREE(filepath); - - return(ret); + return ret; } -int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) +static int validate_deltas(alpm_handle_t *handle, alpm_list_t *deltas, + alpm_list_t **data) { - alpm_list_t *i, *j, *files = NULL; - alpm_list_t *deltas = NULL; - size_t numtargs, current = 0, replaces = 0; - int errors = 0; - const char *cachedir = NULL; - int ret = -1; + int errors = 0, ret = 0; + alpm_list_t *i; + alpm_trans_t *trans = handle->trans; - ALPM_LOG_FUNC; + if(!deltas) { + return 0; + } + + /* Check integrity of deltas */ + EVENT(trans, ALPM_TRANS_EVT_DELTA_INTEGRITY_START, NULL, NULL); - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); + for(i = deltas; i; i = i->next) { + alpm_delta_t *d = alpm_list_getdata(i); + char *filepath = _alpm_filecache_find(handle, d->delta); - cachedir = _alpm_filecache_setup(); - trans->state = STATE_DOWNLOADING; + if(test_md5sum(trans, filepath, d->delta_md5) != 0) { + errors++; + *data = alpm_list_add(*data, strdup(d->delta)); + } + FREE(filepath); + } + if(errors) { + handle->pm_errno = ALPM_ERR_DLT_INVALID; + return -1; + } + EVENT(trans, ALPM_TRANS_EVT_DELTA_INTEGRITY_DONE, NULL, NULL); + + /* Use the deltas to generate the packages */ + EVENT(trans, ALPM_TRANS_EVT_DELTA_PATCHES_START, NULL, NULL); + ret = apply_deltas(handle); + EVENT(trans, ALPM_TRANS_EVT_DELTA_PATCHES_DONE, NULL, NULL); + return ret; +} + +static int download_files(alpm_handle_t *handle, alpm_list_t **deltas) +{ + const char *cachedir; + alpm_list_t *i, *j; + alpm_list_t *files = NULL; + int errors = 0; + + cachedir = _alpm_filecache_setup(handle); + handle->trans->state = STATE_DOWNLOADING; /* Total progress - figure out the total download size if required to * pass to the callback. This function is called once, and it is up to the @@ -716,8 +750,8 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) if(handle->totaldlcb) { off_t total_size = (off_t)0; /* sum up the download size for each package and store total */ - for(i = trans->add; i; i = i->next) { - pmpkg_t *spkg = i->data; + for(i = handle->trans->add; i; i = i->next) { + alpm_pkg_t *spkg = i->data; total_size += spkg->download_size; } handle->totaldlcb(total_size); @@ -725,62 +759,88 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) /* group sync records by repository and download */ for(i = handle->dbs_sync; i; i = i->next) { - pmdb_t *current = i->data; + alpm_db_t *current = i->data; - for(j = trans->add; j; j = j->next) { - pmpkg_t *spkg = j->data; + for(j = handle->trans->add; j; j = j->next) { + alpm_pkg_t *spkg = j->data; if(spkg->origin != PKG_FROM_FILE && current == spkg->origin_data.db) { - const char *fname = NULL; - - fname = alpm_pkg_get_filename(spkg); - ASSERT(fname != NULL, RET_ERR(PM_ERR_PKG_INVALID_NAME, -1)); alpm_list_t *delta_path = spkg->delta_path; if(delta_path) { /* using deltas */ - alpm_list_t *dlts = NULL; - + alpm_list_t *dlts; for(dlts = delta_path; dlts; dlts = dlts->next) { - pmdelta_t *d = dlts->data; + alpm_delta_t *delta = dlts->data; + if(delta->download_size != 0) { + struct dload_payload *dpayload; - if(d->download_size != 0) { - /* add the delta filename to the download list if needed */ - files = alpm_list_add(files, strdup(d->delta)); - } + CALLOC(dpayload, 1, sizeof(*dpayload), RET_ERR(handle, ALPM_ERR_MEMORY, -1)); + STRDUP(dpayload->filename, delta->delta, RET_ERR(handle, ALPM_ERR_MEMORY, -1)); + dpayload->max_size = delta->download_size; + files = alpm_list_add(files, dpayload); + } /* keep a list of all the delta files for md5sums */ - deltas = alpm_list_add(deltas, d); + *deltas = alpm_list_add(*deltas, delta); } - } else { - /* not using deltas */ - if(spkg->download_size != 0) { - /* add the filename to the download list if needed */ - files = alpm_list_add(files, strdup(fname)); - } + } else if(spkg->download_size != 0) { + struct dload_payload *payload; + + ASSERT(spkg->filename != NULL, RET_ERR(handle, ALPM_ERR_PKG_INVALID_NAME, -1)); + CALLOC(payload, 1, sizeof(*payload), RET_ERR(handle, ALPM_ERR_MEMORY, -1)); + STRDUP(payload->filename, spkg->filename, RET_ERR(handle, ALPM_ERR_MEMORY, -1)); + payload->max_size = alpm_pkg_get_size(spkg); + + files = alpm_list_add(files, payload); } } } if(files) { - EVENT(trans, PM_TRANS_EVT_RETRIEVE_START, current->treename, NULL); - errors = _alpm_download_files(files, current->servers, cachedir); + EVENT(handle->trans, ALPM_TRANS_EVT_RETRIEVE_START, current->treename, NULL); + for(j = files; j; j = j->next) { + struct dload_payload *payload = j->data; + alpm_list_t *server; + int ret = -1; + for(server = current->servers; server; server = server->next) { + const char *server_url = server->data; + size_t len; + + /* print server + filename into a buffer */ + len = strlen(server_url) + strlen(payload->filename) + 2; + CALLOC(payload->fileurl, len, sizeof(char), RET_ERR(handle, ALPM_ERR_MEMORY, -1)); + snprintf(payload->fileurl, len, "%s/%s", server_url, payload->filename); + payload->handle = handle; + payload->allow_resume = 1; + + ret = _alpm_download(payload, cachedir, NULL); + if(ret != -1) { + break; + } + } + if(ret == -1) { + errors++; + } + } - if (errors) { - _alpm_log(PM_LOG_WARNING, _("failed to retrieve some files from %s\n"), + alpm_list_free_inner(files, (alpm_list_fn_free)_alpm_dload_payload_free); + alpm_list_free(files); + files = NULL; + if(errors) { + _alpm_log(handle, ALPM_LOG_WARNING, _("failed to retrieve some files from %s\n"), current->treename); - if(pm_errno == 0) { - pm_errno = PM_ERR_RETRIEVE; + if(handle->pm_errno == 0) { + handle->pm_errno = ALPM_ERR_RETRIEVE; } - goto error; + return -1; } - FREELIST(files); } } - for(j = trans->add; j; j = j->next) { - pmpkg_t *pkg = j->data; + for(j = handle->trans->add; j; j = j->next) { + alpm_pkg_t *pkg = j->data; pkg->infolevel &= ~INFRQ_DSIZE; pkg->download_size = 0; } @@ -789,70 +849,60 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) if(handle->totaldlcb) { handle->totaldlcb(0); } + return 0; +} - /* if we have deltas to work with */ - if(handle->usedelta && deltas) { - int ret = 0; - errors = 0; - /* Check integrity of deltas */ - EVENT(trans, PM_TRANS_EVT_DELTA_INTEGRITY_START, NULL, NULL); - - for(i = deltas; i; i = i->next) { - pmdelta_t *d = alpm_list_getdata(i); - const char *filename = alpm_delta_get_filename(d); - const char *md5sum = alpm_delta_get_md5sum(d); - - if(test_md5sum(trans, filename, md5sum) != 0) { - errors++; - *data = alpm_list_add(*data, strdup(filename)); - } - } - if(errors) { - pm_errno = PM_ERR_DLT_INVALID; - goto error; - } - EVENT(trans, PM_TRANS_EVT_DELTA_INTEGRITY_DONE, NULL, NULL); +int _alpm_sync_commit(alpm_handle_t *handle, alpm_list_t **data) +{ + alpm_list_t *i; + alpm_list_t *deltas = NULL; + size_t numtargs, current = 0, replaces = 0; + int errors; + alpm_trans_t *trans = handle->trans; - /* Use the deltas to generate the packages */ - EVENT(trans, PM_TRANS_EVT_DELTA_PATCHES_START, NULL, NULL); - ret = apply_deltas(trans); - EVENT(trans, PM_TRANS_EVT_DELTA_PATCHES_DONE, NULL, NULL); + if(download_files(handle, &deltas)) { + alpm_list_free(deltas); + return -1; + } - if(ret) { - pm_errno = PM_ERR_DLT_PATCHFAILED; - goto error; - } + if(validate_deltas(handle, deltas, data)) { + alpm_list_free(deltas); + return -1; } + alpm_list_free(deltas); /* Check integrity of packages */ numtargs = alpm_list_count(trans->add); - EVENT(trans, PM_TRANS_EVT_INTEGRITY_START, NULL, NULL); + EVENT(trans, ALPM_TRANS_EVT_INTEGRITY_START, NULL, NULL); errors = 0; + for(i = trans->add; i; i = i->next, current++) { - pmpkg_t *spkg = i->data; + alpm_pkg_t *spkg = i->data; int percent = (current * 100) / numtargs; + const char *filename; + char *filepath; + alpm_siglevel_t level; + + PROGRESS(trans, ALPM_TRANS_PROGRESS_INTEGRITY_START, "", percent, + numtargs, current); if(spkg->origin == PKG_FROM_FILE) { continue; /* pkg_load() has been already called, this package is valid */ } - PROGRESS(trans, PM_TRANS_PROGRESS_INTEGRITY_START, "", percent, - numtargs, current); - const char *filename = alpm_pkg_get_filename(spkg); - const char *md5sum = alpm_pkg_get_md5sum(spkg); + filename = alpm_pkg_get_filename(spkg); + filepath = _alpm_filecache_find(handle, filename); + alpm_db_t *sdb = alpm_pkg_get_db(spkg); + level = alpm_db_get_siglevel(sdb); - if(test_md5sum(trans, filename, md5sum) != 0) { - errors++; - *data = alpm_list_add(*data, strdup(filename)); - continue; - } /* load the package file and replace pkgcache entry with it in the target list */ /* TODO: alpm_pkg_get_db() will not work on this target anymore */ - _alpm_log(PM_LOG_DEBUG, "replacing pkgcache entry with package file for target %s\n", spkg->name); - char *filepath = _alpm_filecache_find(filename); - pmpkg_t *pkgfile; - if(alpm_pkg_load(filepath, 1, &pkgfile) != 0) { - _alpm_pkg_free(pkgfile); + _alpm_log(handle, ALPM_LOG_DEBUG, + "replacing pkgcache entry with package file for target %s\n", + spkg->name); + alpm_pkg_t *pkgfile =_alpm_pkg_load_internal(handle, filepath, 1, spkg->md5sum, + spkg->base64_sig, level); + if(!pkgfile) { errors++; *data = alpm_list_add(*data, strdup(filename)); FREE(filepath); @@ -863,17 +913,18 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) i->data = pkgfile; _alpm_pkg_free_trans(spkg); /* spkg has been removed from the target list */ } - PROGRESS(trans, PM_TRANS_PROGRESS_INTEGRITY_START, "", 100, + + PROGRESS(trans, ALPM_TRANS_PROGRESS_INTEGRITY_START, "", 100, numtargs, current); - EVENT(trans, PM_TRANS_EVT_INTEGRITY_DONE, NULL, NULL); + EVENT(trans, ALPM_TRANS_EVT_INTEGRITY_DONE, NULL, NULL); + + if(errors) { - pm_errno = PM_ERR_PKG_INVALID; - goto error; + RET_ERR(handle, ALPM_ERR_PKG_INVALID, -1); } - if(trans->flags & PM_TRANS_FLAG_DOWNLOADONLY) { - ret = 0; - goto error; + if(trans->flags & ALPM_TRANS_FLAG_DOWNLOADONLY) { + return 0; } trans->state = STATE_COMMITING; @@ -881,61 +932,56 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) replaces = alpm_list_count(trans->remove); /* fileconflict check */ - if(!(trans->flags & PM_TRANS_FLAG_FORCE)) { - EVENT(trans, PM_TRANS_EVT_FILECONFLICTS_START, NULL, NULL); + if(!(trans->flags & ALPM_TRANS_FLAG_FORCE)) { + EVENT(trans, ALPM_TRANS_EVT_FILECONFLICTS_START, NULL, NULL); - _alpm_log(PM_LOG_DEBUG, "looking for file conflicts\n"); - alpm_list_t *conflict = _alpm_db_find_fileconflicts(db_local, trans, - trans->add, trans->remove); + _alpm_log(handle, ALPM_LOG_DEBUG, "looking for file conflicts\n"); + alpm_list_t *conflict = _alpm_db_find_fileconflicts(handle, + trans->add, trans->remove); if(conflict) { - pm_errno = PM_ERR_FILE_CONFLICTS; if(data) { *data = conflict; } else { alpm_list_free_inner(conflict, (alpm_list_fn_free)_alpm_fileconflict_free); alpm_list_free(conflict); } - goto error; + RET_ERR(handle, ALPM_ERR_FILE_CONFLICTS, -1); } - EVENT(trans, PM_TRANS_EVT_FILECONFLICTS_DONE, NULL, NULL); + EVENT(trans, ALPM_TRANS_EVT_FILECONFLICTS_DONE, NULL, NULL); } /* check available disk space */ if(handle->checkspace) { - EVENT(trans, PM_TRANS_EVT_DISKSPACE_START, NULL, NULL); + EVENT(trans, ALPM_TRANS_EVT_DISKSPACE_START, NULL, NULL); - _alpm_log(PM_LOG_DEBUG, "checking available disk space\n"); - if(_alpm_check_diskspace(trans, handle->db_local) == -1) { - _alpm_log(PM_LOG_ERROR, "%s\n", _("not enough free disk space")); - goto error; + _alpm_log(handle, ALPM_LOG_DEBUG, "checking available disk space\n"); + if(_alpm_check_diskspace(handle) == -1) { + _alpm_log(handle, ALPM_LOG_ERROR, "%s\n", _("not enough free disk space")); + return -1; } - EVENT(trans, PM_TRANS_EVT_DISKSPACE_DONE, NULL, NULL); + EVENT(trans, ALPM_TRANS_EVT_DISKSPACE_DONE, NULL, NULL); } /* remove conflicting and to-be-replaced packages */ if(replaces) { - _alpm_log(PM_LOG_DEBUG, "removing conflicting and to-be-replaced packages\n"); + _alpm_log(handle, ALPM_LOG_DEBUG, "removing conflicting and to-be-replaced packages\n"); /* we want the frontend to be aware of commit details */ - if(_alpm_remove_packages(trans, handle->db_local) == -1) { - _alpm_log(PM_LOG_ERROR, _("could not commit removal transaction\n")); - goto error; + if(_alpm_remove_packages(handle) == -1) { + _alpm_log(handle, ALPM_LOG_ERROR, _("could not commit removal transaction\n")); + return -1; } } /* install targets */ - _alpm_log(PM_LOG_DEBUG, "installing packages\n"); - if(_alpm_upgrade_packages(trans, handle->db_local) == -1) { - _alpm_log(PM_LOG_ERROR, _("could not commit transaction\n")); - goto error; + _alpm_log(handle, ALPM_LOG_DEBUG, "installing packages\n"); + if(_alpm_upgrade_packages(handle) == -1) { + _alpm_log(handle, ALPM_LOG_ERROR, _("could not commit transaction\n")); + return -1; } - ret = 0; -error: - FREELIST(files); - alpm_list_free(deltas); - return(ret); + return 0; } /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/sync.h b/lib/libalpm/sync.h index 90a2d40d..472d1dfc 100644 --- a/lib/libalpm/sync.h +++ b/lib/libalpm/sync.h @@ -24,8 +24,8 @@ #include "alpm.h" -int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, alpm_list_t **data); -int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data); +int _alpm_sync_prepare(alpm_handle_t *handle, alpm_list_t **data); +int _alpm_sync_commit(alpm_handle_t *handle, alpm_list_t **data); #endif /* _ALPM_SYNC_H */ diff --git a/lib/libalpm/trans.c b/lib/libalpm/trans.c index bf9ef722..1bab830d 100644 --- a/lib/libalpm/trans.c +++ b/lib/libalpm/trans.c @@ -28,11 +28,8 @@ #include <string.h> #include <unistd.h> #include <sys/types.h> -#include <sys/stat.h> -#include <sys/statvfs.h> #include <errno.h> #include <limits.h> -#include <fcntl.h> /* libalpm */ #include "trans.h" @@ -41,91 +38,34 @@ #include "util.h" #include "log.h" #include "handle.h" -#include "add.h" #include "remove.h" #include "sync.h" #include "alpm.h" -#include "deps.h" /** \addtogroup alpm_trans Transaction Functions * @brief Functions to manipulate libalpm transactions * @{ */ -/* Create a lock file */ -static int make_lock(pmhandle_t *handle) -{ - int fd; - char *dir, *ptr; - - ASSERT(handle->lockfile != NULL, return -1); - - /* create the dir of the lockfile first */ - dir = strdup(handle->lockfile); - ptr = strrchr(dir, '/'); - if(ptr) { - *ptr = '\0'; - } - if(_alpm_makepath(dir)) { - FREE(dir); - return(-1); - } - FREE(dir); - - do { - fd = open(handle->lockfile, O_WRONLY | O_CREAT | O_EXCL, 0000); - } while (fd == -1 && errno == EINTR); - if(fd > 0) { - FILE *f = fdopen(fd, "w"); - fprintf(f, "%ld\n", (long)getpid()); - fflush(f); - fsync(fd); - handle->lckstream = f; - return(0); - } - return(-1); -} - -/* Remove a lock file */ -static int remove_lock(pmhandle_t *handle) -{ - if(handle->lckstream != NULL) { - fclose(handle->lckstream); - handle->lckstream = NULL; - } - if(unlink(handle->lockfile) == -1 && errno != ENOENT) { - return(-1); - } - return(0); -} - /** Initialize the transaction. */ -int SYMEXPORT alpm_trans_init(pmtransflag_t flags, +int SYMEXPORT alpm_trans_init(alpm_handle_t *handle, alpm_transflag_t flags, alpm_trans_cb_event event, alpm_trans_cb_conv conv, alpm_trans_cb_progress progress) { - pmtrans_t *trans; - const int required_db_version = 2; - int db_version; - - ALPM_LOG_FUNC; + alpm_trans_t *trans; /* Sanity checks */ - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); - ASSERT(handle->trans == NULL, RET_ERR(PM_ERR_TRANS_NOT_NULL, -1)); + CHECK_HANDLE(handle, return -1); + ASSERT(handle->trans == NULL, RET_ERR(handle, ALPM_ERR_TRANS_NOT_NULL, -1)); /* lock db */ - if(!(flags & PM_TRANS_FLAG_NOLOCK)) { - if(make_lock(handle)) { - RET_ERR(PM_ERR_HANDLE_LOCK, -1); + if(!(flags & ALPM_TRANS_FLAG_NOLOCK)) { + if(_alpm_handle_lock(handle)) { + RET_ERR(handle, ALPM_ERR_HANDLE_LOCK, -1); } } - trans = _alpm_trans_new(); - if(trans == NULL) { - RET_ERR(PM_ERR_MEMORY, -1); - } - + CALLOC(trans, 1, sizeof(alpm_trans_t), RET_ERR(handle, ALPM_ERR_MEMORY, -1)); trans->flags = flags; trans->cb_event = event; trans->cb_conv = conv; @@ -134,201 +74,169 @@ int SYMEXPORT alpm_trans_init(pmtransflag_t flags, handle->trans = trans; - /* check database version */ - db_version = _alpm_db_version(handle->db_local); - if(db_version < required_db_version) { - _alpm_log(PM_LOG_ERROR, - _("%s database version is too old\n"), handle->db_local->treename); - remove_lock(handle); - _alpm_trans_free(trans); - RET_ERR(PM_ERR_DB_VERSION, -1); - } - - return(0); + return 0; } -static alpm_list_t *check_arch(alpm_list_t *pkgs) +static alpm_list_t *check_arch(alpm_handle_t *handle, alpm_list_t *pkgs) { alpm_list_t *i; alpm_list_t *invalid = NULL; - const char *arch = alpm_option_get_arch(); + const char *arch = alpm_option_get_arch(handle); if(!arch) { - return(NULL); + return NULL; } for(i = pkgs; i; i = i->next) { - pmpkg_t *pkg = i->data; + alpm_pkg_t *pkg = i->data; const char *pkgarch = alpm_pkg_get_arch(pkg); if(pkgarch && strcmp(pkgarch, arch) && strcmp(pkgarch, "any")) { char *string; const char *pkgname = alpm_pkg_get_name(pkg); const char *pkgver = alpm_pkg_get_version(pkg); size_t len = strlen(pkgname) + strlen(pkgver) + strlen(pkgarch) + 3; - MALLOC(string, len, RET_ERR(PM_ERR_MEMORY, invalid)); + MALLOC(string, len, RET_ERR(handle, ALPM_ERR_MEMORY, invalid)); sprintf(string, "%s-%s-%s", pkgname, pkgver, pkgarch); invalid = alpm_list_add(invalid, string); } } - return(invalid); + return invalid; } /** Prepare a transaction. */ -int SYMEXPORT alpm_trans_prepare(alpm_list_t **data) +int SYMEXPORT alpm_trans_prepare(alpm_handle_t *handle, alpm_list_t **data) { - pmtrans_t *trans; - - ALPM_LOG_FUNC; + alpm_trans_t *trans; /* Sanity checks */ - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); - ASSERT(data != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); + CHECK_HANDLE(handle, return -1); + ASSERT(data != NULL, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1)); trans = handle->trans; - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1)); + ASSERT(trans != NULL, RET_ERR(handle, ALPM_ERR_TRANS_NULL, -1)); + ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(handle, ALPM_ERR_TRANS_NOT_INITIALIZED, -1)); /* If there's nothing to do, return without complaining */ if(trans->add == NULL && trans->remove == NULL) { - return(0); + return 0; } - alpm_list_t *invalid = check_arch(trans->add); + alpm_list_t *invalid = check_arch(handle, trans->add); if(invalid) { if(data) { *data = invalid; } - RET_ERR(PM_ERR_PKG_INVALID_ARCH, -1); + RET_ERR(handle, ALPM_ERR_PKG_INVALID_ARCH, -1); } if(trans->add == NULL) { - if(_alpm_remove_prepare(trans, handle->db_local, data) == -1) { + if(_alpm_remove_prepare(handle, data) == -1) { /* pm_errno is set by _alpm_remove_prepare() */ - return(-1); + return -1; } } else { - if(_alpm_sync_prepare(trans, handle->db_local, handle->dbs_sync, data) == -1) { + if(_alpm_sync_prepare(handle, data) == -1) { /* pm_errno is set by _alpm_sync_prepare() */ - return(-1); + return -1; } } trans->state = STATE_PREPARED; - return(0); + return 0; } /** Commit a transaction. */ -int SYMEXPORT alpm_trans_commit(alpm_list_t **data) +int SYMEXPORT alpm_trans_commit(alpm_handle_t *handle, alpm_list_t **data) { - pmtrans_t *trans; - - ALPM_LOG_FUNC; + alpm_trans_t *trans; /* Sanity checks */ - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + CHECK_HANDLE(handle, return -1); trans = handle->trans; - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - ASSERT(trans->state == STATE_PREPARED, RET_ERR(PM_ERR_TRANS_NOT_PREPARED, -1)); + ASSERT(trans != NULL, RET_ERR(handle, ALPM_ERR_TRANS_NULL, -1)); + ASSERT(trans->state == STATE_PREPARED, RET_ERR(handle, ALPM_ERR_TRANS_NOT_PREPARED, -1)); - ASSERT(!(trans->flags & PM_TRANS_FLAG_NOLOCK), RET_ERR(PM_ERR_TRANS_NOT_LOCKED, -1)); + ASSERT(!(trans->flags & ALPM_TRANS_FLAG_NOLOCK), RET_ERR(handle, ALPM_ERR_TRANS_NOT_LOCKED, -1)); /* If there's nothing to do, return without complaining */ if(trans->add == NULL && trans->remove == NULL) { - return(0); + return 0; } trans->state = STATE_COMMITING; if(trans->add == NULL) { - if(_alpm_remove_packages(trans, handle->db_local) == -1) { + if(_alpm_remove_packages(handle) == -1) { /* pm_errno is set by _alpm_remove_commit() */ - return(-1); + return -1; } } else { - if(_alpm_sync_commit(trans, handle->db_local, data) == -1) { + if(_alpm_sync_commit(handle, data) == -1) { /* pm_errno is set by _alpm_sync_commit() */ - return(-1); + return -1; } } trans->state = STATE_COMMITED; - return(0); + return 0; } /** Interrupt a transaction. */ -int SYMEXPORT alpm_trans_interrupt(void) +int SYMEXPORT alpm_trans_interrupt(alpm_handle_t *handle) { - pmtrans_t *trans; - - ALPM_LOG_FUNC; + alpm_trans_t *trans; /* Sanity checks */ - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + CHECK_HANDLE(handle, return -1); trans = handle->trans; - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); + ASSERT(trans != NULL, RET_ERR(handle, ALPM_ERR_TRANS_NULL, -1)); ASSERT(trans->state == STATE_COMMITING || trans->state == STATE_INTERRUPTED, - RET_ERR(PM_ERR_TRANS_TYPE, -1)); + RET_ERR(handle, ALPM_ERR_TRANS_TYPE, -1)); trans->state = STATE_INTERRUPTED; - return(0); + return 0; } /** Release a transaction. */ -int SYMEXPORT alpm_trans_release(void) +int SYMEXPORT alpm_trans_release(alpm_handle_t *handle) { - pmtrans_t *trans; - - ALPM_LOG_FUNC; + alpm_trans_t *trans; /* Sanity checks */ - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + CHECK_HANDLE(handle, return -1); trans = handle->trans; - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - ASSERT(trans->state != STATE_IDLE, RET_ERR(PM_ERR_TRANS_NULL, -1)); + ASSERT(trans != NULL, RET_ERR(handle, ALPM_ERR_TRANS_NULL, -1)); + ASSERT(trans->state != STATE_IDLE, RET_ERR(handle, ALPM_ERR_TRANS_NULL, -1)); - int nolock_flag = trans->flags & PM_TRANS_FLAG_NOLOCK; + int nolock_flag = trans->flags & ALPM_TRANS_FLAG_NOLOCK; _alpm_trans_free(trans); handle->trans = NULL; /* unlock db */ if(!nolock_flag) { - if(remove_lock(handle)) { - _alpm_log(PM_LOG_WARNING, _("could not remove lock file %s\n"), - alpm_option_get_lockfile()); - alpm_logaction("warning: could not remove lock file %s\n", - alpm_option_get_lockfile()); + if(_alpm_handle_unlock(handle)) { + _alpm_log(handle, ALPM_LOG_WARNING, _("could not remove lock file %s\n"), + alpm_option_get_lockfile(handle)); + alpm_logaction(handle, "warning: could not remove lock file %s\n", + alpm_option_get_lockfile(handle)); } } - return(0); + return 0; } /** @} */ -pmtrans_t *_alpm_trans_new(void) +void _alpm_trans_free(alpm_trans_t *trans) { - pmtrans_t *trans; - - ALPM_LOG_FUNC; - - CALLOC(trans, 1, sizeof(pmtrans_t), RET_ERR(PM_ERR_MEMORY, NULL)); - trans->state = STATE_IDLE; - - return(trans); -} - -void _alpm_trans_free(pmtrans_t *trans) -{ - ALPM_LOG_FUNC; - if(trans == NULL) { return; } @@ -351,7 +259,7 @@ static int grep(const char *fn, const char *needle) FILE *fp; if((fp = fopen(fn, "r")) == NULL) { - return(0); + return 0; } while(!feof(fp)) { char line[1024]; @@ -362,16 +270,15 @@ static int grep(const char *fn, const char *needle) * ends up being split across line reads */ if(strstr(line, needle)) { fclose(fp); - return(1); + return 1; } } fclose(fp); - return(0); + return 0; } -int _alpm_runscriptlet(const char *root, const char *installfn, - const char *script, const char *ver, - const char *oldver, pmtrans_t *trans) +int _alpm_runscriptlet(alpm_handle_t *handle, const char *installfn, + const char *script, const char *ver, const char *oldver) { char scriptfn[PATH_MAX]; char cmdline[PATH_MAX]; @@ -381,23 +288,20 @@ int _alpm_runscriptlet(const char *root, const char *installfn, int clean_tmpdir = 0; int retval = 0; - ALPM_LOG_FUNC; - - if(access(installfn, R_OK)) { - /* not found */ - _alpm_log(PM_LOG_DEBUG, "scriptlet '%s' not found\n", installfn); - return(0); + if(_alpm_access(handle, NULL, installfn, R_OK) != 0) { + _alpm_log(handle, ALPM_LOG_DEBUG, "scriptlet '%s' not found\n", installfn); + return 0; } /* creates a directory in $root/tmp/ for copying/extracting the scriptlet */ - snprintf(tmpdir, PATH_MAX, "%stmp/", root); + snprintf(tmpdir, PATH_MAX, "%stmp/", handle->root); if(access(tmpdir, F_OK) != 0) { _alpm_makepath_mode(tmpdir, 01777); } - snprintf(tmpdir, PATH_MAX, "%stmp/alpm_XXXXXX", root); + snprintf(tmpdir, PATH_MAX, "%stmp/alpm_XXXXXX", handle->root); if(mkdtemp(tmpdir) == NULL) { - _alpm_log(PM_LOG_ERROR, _("could not create temp directory\n")); - return(1); + _alpm_log(handle, ALPM_LOG_ERROR, _("could not create temp directory\n")); + return 1; } else { clean_tmpdir = 1; } @@ -405,12 +309,12 @@ int _alpm_runscriptlet(const char *root, const char *installfn, /* either extract or copy the scriptlet */ snprintf(scriptfn, PATH_MAX, "%s/.INSTALL", tmpdir); if(strcmp(script, "pre_upgrade") == 0 || strcmp(script, "pre_install") == 0) { - if(_alpm_unpack_single(installfn, tmpdir, ".INSTALL")) { + if(_alpm_unpack_single(handle, installfn, tmpdir, ".INSTALL")) { retval = 1; } } else { if(_alpm_copyfile(installfn, scriptfn)) { - _alpm_log(PM_LOG_ERROR, _("could not copy tempfile to %s (%s)\n"), scriptfn, strerror(errno)); + _alpm_log(handle, ALPM_LOG_ERROR, _("could not copy tempfile to %s (%s)\n"), scriptfn, strerror(errno)); retval = 1; } } @@ -419,7 +323,7 @@ int _alpm_runscriptlet(const char *root, const char *installfn, } /* chop off the root so we can find the tmpdir in the chroot */ - scriptpath = scriptfn + strlen(root) - 1; + scriptpath = scriptfn + strlen(handle->root) - 1; if(!grep(scriptfn, script)) { /* script not found in scriptlet file */ @@ -434,41 +338,41 @@ int _alpm_runscriptlet(const char *root, const char *installfn, scriptpath, script, ver); } - _alpm_log(PM_LOG_DEBUG, "executing \"%s\"\n", cmdline); + _alpm_log(handle, ALPM_LOG_DEBUG, "executing \"%s\"\n", cmdline); - retval = _alpm_run_chroot(root, "/bin/sh", argv); + retval = _alpm_run_chroot(handle, "/bin/sh", argv); cleanup: if(clean_tmpdir && _alpm_rmrf(tmpdir)) { - _alpm_log(PM_LOG_WARNING, _("could not remove tmpdir %s\n"), tmpdir); + _alpm_log(handle, ALPM_LOG_WARNING, _("could not remove tmpdir %s\n"), tmpdir); } - return(retval); + return retval; } -int SYMEXPORT alpm_trans_get_flags() +alpm_transflag_t SYMEXPORT alpm_trans_get_flags(alpm_handle_t *handle) { /* Sanity checks */ - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); - ASSERT(handle->trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); + CHECK_HANDLE(handle, return -1); + ASSERT(handle->trans != NULL, RET_ERR(handle, ALPM_ERR_TRANS_NULL, -1)); return handle->trans->flags; } -alpm_list_t SYMEXPORT * alpm_trans_get_add() +alpm_list_t SYMEXPORT *alpm_trans_get_add(alpm_handle_t *handle) { /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(handle->trans != NULL, return(NULL)); + CHECK_HANDLE(handle, return NULL); + ASSERT(handle->trans != NULL, RET_ERR(handle, ALPM_ERR_TRANS_NULL, NULL)); return handle->trans->add; } -alpm_list_t SYMEXPORT * alpm_trans_get_remove() +alpm_list_t SYMEXPORT *alpm_trans_get_remove(alpm_handle_t *handle) { /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(handle->trans != NULL, return(NULL)); + CHECK_HANDLE(handle, return NULL); + ASSERT(handle->trans != NULL, RET_ERR(handle, ALPM_ERR_TRANS_NULL, NULL)); return handle->trans->remove; } diff --git a/lib/libalpm/trans.h b/lib/libalpm/trans.h index 6702881b..9a60e71b 100644 --- a/lib/libalpm/trans.h +++ b/lib/libalpm/trans.h @@ -25,7 +25,7 @@ #include "alpm.h" -typedef enum _pmtransstate_t { +typedef enum _alpm_transstate_t { STATE_IDLE = 0, STATE_INITIALIZED, STATE_PREPARED, @@ -33,14 +33,14 @@ typedef enum _pmtransstate_t { STATE_COMMITING, STATE_COMMITED, STATE_INTERRUPTED -} pmtransstate_t; +} alpm_transstate_t; /* Transaction */ -struct __pmtrans_t { - pmtransflag_t flags; - pmtransstate_t state; - alpm_list_t *add; /* list of (pmpkg_t *) */ - alpm_list_t *remove; /* list of (pmpkg_t *) */ +struct __alpm_trans_t { + alpm_transflag_t flags; + alpm_transstate_t state; + alpm_list_t *add; /* list of (alpm_pkg_t *) */ + alpm_list_t *remove; /* list of (alpm_pkg_t *) */ alpm_list_t *skip_remove; /* list of (char *) */ alpm_trans_cb_event cb_event; alpm_trans_cb_conv cb_conv; @@ -66,14 +66,12 @@ do { \ } \ } while(0) -pmtrans_t *_alpm_trans_new(void); -void _alpm_trans_free(pmtrans_t *trans); -int _alpm_trans_init(pmtrans_t *trans, pmtransflag_t flags, +void _alpm_trans_free(alpm_trans_t *trans); +int _alpm_trans_init(alpm_trans_t *trans, alpm_transflag_t flags, alpm_trans_cb_event event, alpm_trans_cb_conv conv, alpm_trans_cb_progress progress); -int _alpm_runscriptlet(const char *root, const char *installfn, - const char *script, const char *ver, - const char *oldver, pmtrans_t *trans); +int _alpm_runscriptlet(alpm_handle_t *handle, const char *installfn, + const char *script, const char *ver, const char *oldver); #endif /* _ALPM_TRANS_H */ diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c index 430da92a..123cd24e 100644 --- a/lib/libalpm/util.c +++ b/lib/libalpm/util.c @@ -53,10 +53,10 @@ /* libalpm */ #include "util.h" #include "log.h" -#include "package.h" #include "alpm.h" #include "alpm_list.h" #include "handle.h" +#include "trans.h" #ifndef HAVE_STRSEP /* This is a replacement for strsep which is not portable (missing on Solaris). @@ -65,14 +65,14 @@ char* strsep(char** str, const char* delims) { char* token; - if (*str==NULL) { + if(*str==NULL) { /* No more tokens */ return NULL; } token=*str; - while (**str!='\0') { - if (strchr(delims,**str)!=NULL) { + while(**str!='\0') { + if(strchr(delims,**str)!=NULL) { **str='\0'; (*str)++; return token; @@ -87,7 +87,7 @@ char* strsep(char** str, const char* delims) int _alpm_makepath(const char *path) { - return(_alpm_makepath_mode(path, 0755)); + return _alpm_makepath_mode(path, 0755); } /* does the same thing as 'mkdir -p' */ @@ -123,7 +123,7 @@ int _alpm_makepath_mode(const char *path, mode_t mode) free(orig); free(incr); umask(oldmask); - return(ret); + return ret; } #define CPBUFSIZE 8 * 1024 @@ -137,12 +137,12 @@ int _alpm_copyfile(const char *src, const char *dest) in = fopen(src, "rb"); if(in == NULL) { - return(1); + return 1; } out = fopen(dest, "wb"); if(out == NULL) { fclose(in); - return(1); + return 1; } CALLOC(buf, (size_t)CPBUFSIZE, (size_t)1, ret = 1; goto cleanup;); @@ -152,9 +152,6 @@ int _alpm_copyfile(const char *src, const char *dest) size_t nwritten = 0; nwritten = fwrite(buf, 1, len, out); if((nwritten != len) || ferror(out)) { - pm_errno = PM_ERR_WRITE; - _alpm_log(PM_LOG_ERROR, _("error writing to file '%s': %s\n"), - dest, strerror(errno)); ret = -1; goto cleanup; } @@ -175,7 +172,7 @@ cleanup: fclose(in); fclose(out); FREE(buf); - return(ret); + return ret; } /* Trim whitespace and newlines from a string @@ -186,7 +183,7 @@ char *_alpm_strtrim(char *str) if(*str == '\0') { /* string is empty, so we're done. */ - return(str); + return str; } while(isspace((unsigned char)*pch)) { @@ -198,7 +195,7 @@ char *_alpm_strtrim(char *str) /* check if there wasn't anything but whitespace in the string. */ if(*str == '\0') { - return(str); + return str; } pch = (str + (strlen(str) - 1)); @@ -207,7 +204,27 @@ char *_alpm_strtrim(char *str) } *++pch = '\0'; - return(str); + return str; +} + +/** + * Trim trailing newline from a string (if one exists). + * @param str a single line of text + * @return the length of the trimmed string + */ +size_t _alpm_strip_newline(char *str) +{ + size_t len; + if(str == '\0') { + return 0; + } + len = strlen(str); + while(str[len - 1] == '\n') { + len--; + } + str[len] = '\0'; + + return len; } /* Compression functions */ @@ -215,36 +232,39 @@ char *_alpm_strtrim(char *str) /** * @brief Unpack a specific file in an archive. * - * @param archive the archive to unpack - * @param prefix where to extract the files - * @param fn a file within the archive to unpack + * @param handle the context handle + * @param archive the archive to unpack + * @param prefix where to extract the files + * @param filename a file within the archive to unpack * @return 0 on success, 1 on failure */ -int _alpm_unpack_single(const char *archive, const char *prefix, const char *fn) +int _alpm_unpack_single(alpm_handle_t *handle, const char *archive, + const char *prefix, const char *filename) { alpm_list_t *list = NULL; int ret = 0; - if(fn == NULL) { - return(1); + if(filename == NULL) { + return 1; } - list = alpm_list_add(list, (void *)fn); - ret = _alpm_unpack(archive, prefix, list, 1); + list = alpm_list_add(list, (void *)filename); + ret = _alpm_unpack(handle, archive, prefix, list, 1); alpm_list_free(list); - return(ret); + return ret; } /** * @brief Unpack a list of files in an archive. * - * @param archive the archive to unpack - * @param prefix where to extract the files - * @param list a list of files within the archive to unpack or - * NULL for all + * @param handle the context handle + * @param archive the archive to unpack + * @param prefix where to extract the files + * @param list a list of files within the archive to unpack or NULL for all * @param breakfirst break after the first entry found * * @return 0 on success, 1 on failure */ -int _alpm_unpack(const char *archive, const char *prefix, alpm_list_t *list, int breakfirst) +int _alpm_unpack(alpm_handle_t *handle, const char *archive, const char *prefix, + alpm_list_t *list, int breakfirst) { int ret = 0; mode_t oldmask; @@ -253,33 +273,33 @@ int _alpm_unpack(const char *archive, const char *prefix, alpm_list_t *list, int char cwd[PATH_MAX]; int restore_cwd = 0; - ALPM_LOG_FUNC; - - if((_archive = archive_read_new()) == NULL) - RET_ERR(PM_ERR_LIBARCHIVE, 1); + if((_archive = archive_read_new()) == NULL) { + RET_ERR(handle, ALPM_ERR_LIBARCHIVE, 1); + } archive_read_support_compression_all(_archive); archive_read_support_format_all(_archive); if(archive_read_open_filename(_archive, archive, ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) { - _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), archive, + _alpm_log(handle, ALPM_LOG_ERROR, _("could not open file %s: %s\n"), archive, archive_error_string(_archive)); - RET_ERR(PM_ERR_PKG_OPEN, 1); + RET_ERR(handle, ALPM_ERR_PKG_OPEN, 1); } oldmask = umask(0022); /* save the cwd so we can restore it later */ if(getcwd(cwd, PATH_MAX) == NULL) { - _alpm_log(PM_LOG_ERROR, _("could not get current working directory\n")); + _alpm_log(handle, ALPM_LOG_ERROR, _("could not get current working directory\n")); } else { restore_cwd = 1; } /* just in case our cwd was removed in the upgrade operation */ if(chdir(prefix) != 0) { - _alpm_log(PM_LOG_ERROR, _("could not change directory to %s (%s)\n"), prefix, strerror(errno)); + _alpm_log(handle, ALPM_LOG_ERROR, _("could not change directory to %s (%s)\n"), + prefix, strerror(errno)); ret = 1; goto cleanup; } @@ -299,21 +319,21 @@ int _alpm_unpack(const char *archive, const char *prefix, alpm_list_t *list, int /* If specific files were requested, skip entries that don't match. */ if(list) { - char *prefix = strdup(entryname); - char *p = strstr(prefix,"/"); + char *entry_prefix = strdup(entryname); + char *p = strstr(entry_prefix,"/"); if(p) { *(p+1) = '\0'; } - char *found = alpm_list_find_str(list, prefix); - free(prefix); + char *found = alpm_list_find_str(list, entry_prefix); + free(entry_prefix); if(!found) { - if (archive_read_data_skip(_archive) != ARCHIVE_OK) { + if(archive_read_data_skip(_archive) != ARCHIVE_OK) { ret = 1; goto cleanup; } continue; } else { - _alpm_log(PM_LOG_DEBUG, "extracting: %s\n", entryname); + _alpm_log(handle, ALPM_LOG_DEBUG, "extracting: %s\n", entryname); } } @@ -321,10 +341,10 @@ int _alpm_unpack(const char *archive, const char *prefix, alpm_list_t *list, int int readret = archive_read_extract(_archive, entry, 0); if(readret == ARCHIVE_WARN) { /* operation succeeded but a non-critical error was encountered */ - _alpm_log(PM_LOG_WARNING, _("warning given when extracting %s (%s)\n"), + _alpm_log(handle, ALPM_LOG_WARNING, _("warning given when extracting %s (%s)\n"), entryname, archive_error_string(_archive)); } else if(readret != ARCHIVE_OK) { - _alpm_log(PM_LOG_ERROR, _("could not extract %s (%s)\n"), + _alpm_log(handle, ALPM_LOG_ERROR, _("could not extract %s (%s)\n"), entryname, archive_error_string(_archive)); ret = 1; goto cleanup; @@ -339,9 +359,10 @@ cleanup: umask(oldmask); archive_read_finish(_archive); if(restore_cwd && chdir(cwd) != 0) { - _alpm_log(PM_LOG_ERROR, _("could not change directory to %s (%s)\n"), cwd, strerror(errno)); + _alpm_log(handle, ALPM_LOG_ERROR, _("could not change directory to %s (%s)\n"), + cwd, strerror(errno)); } - return(ret); + return ret; } /* does the same thing as 'rm -rf' */ @@ -356,18 +377,18 @@ int _alpm_rmrf(const char *path) if(_alpm_lstat(path, &st) == 0) { if(!S_ISDIR(st.st_mode)) { if(!unlink(path)) { - return(0); + return 0; } else { if(errno == ENOENT) { - return(0); + return 0; } else { - return(1); + return 1; } } } else { dirp = opendir(path); if(!dirp) { - return(1); + return 1; } for(dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { if(dp->d_ino) { @@ -382,16 +403,58 @@ int _alpm_rmrf(const char *path) errflag++; } } - return(errflag); + return errflag; } - return(0); + return 0; } -int _alpm_logaction(int usesyslog, FILE *f, const char *fmt, va_list args) +/** + * Determine if there are files in a directory + * @param handle the context handle + * @param path the full absolute directory path + * @param full_count whether to return an exact count of files + * @return a file count if full_count is != 0, else >0 if directory has + * contents, 0 if no contents, and -1 on error + */ +ssize_t _alpm_files_in_directory(alpm_handle_t *handle, const char *path, + int full_count) +{ + ssize_t files = 0; + struct dirent *ent; + DIR *dir = opendir(path); + + if(!dir) { + if(errno == ENOTDIR) { + _alpm_log(handle, ALPM_LOG_DEBUG, "%s was not a directory\n", path); + } else { + _alpm_log(handle, ALPM_LOG_DEBUG, "could not read directory %s\n", + path); + } + return -1; + } + while((ent = readdir(dir)) != NULL) { + const char *name = ent->d_name; + + if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { + continue; + } + + files++; + + if(!full_count) { + break; + } + } + + closedir(dir); + return files; +} + +int _alpm_logaction(alpm_handle_t *handle, const char *fmt, va_list args) { int ret = 0; - if(usesyslog) { + if(handle->usesyslog) { /* we can't use a va_list more than once, so we need to copy it * so we can use the original when calling vfprintf below. */ va_list args_syslog; @@ -400,7 +463,7 @@ int _alpm_logaction(int usesyslog, FILE *f, const char *fmt, va_list args) va_end(args_syslog); } - if(f) { + if(handle->logstream) { time_t t; struct tm *tm; @@ -408,17 +471,17 @@ int _alpm_logaction(int usesyslog, FILE *f, const char *fmt, va_list args) tm = localtime(&t); /* Use ISO-8601 date format */ - fprintf(f, "[%04d-%02d-%02d %02d:%02d] ", + fprintf(handle->logstream, "[%04d-%02d-%02d %02d:%02d] ", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min); - ret = vfprintf(f, fmt, args); - fflush(f); + ret = vfprintf(handle->logstream, fmt, args); + fflush(handle->logstream); } - return(ret); + return ret; } -int _alpm_run_chroot(const char *root, const char *path, char *const argv[]) +int _alpm_run_chroot(alpm_handle_t *handle, const char *path, char *const argv[]) { char cwd[PATH_MAX]; pid_t pid; @@ -426,28 +489,28 @@ int _alpm_run_chroot(const char *root, const char *path, char *const argv[]) int restore_cwd = 0; int retval = 0; - ALPM_LOG_FUNC; - /* save the cwd so we can restore it later */ if(getcwd(cwd, PATH_MAX) == NULL) { - _alpm_log(PM_LOG_ERROR, _("could not get current working directory\n")); + _alpm_log(handle, ALPM_LOG_ERROR, _("could not get current working directory\n")); } else { restore_cwd = 1; } /* just in case our cwd was removed in the upgrade operation */ - if(chdir(root) != 0) { - _alpm_log(PM_LOG_ERROR, _("could not change directory to %s (%s)\n"), root, strerror(errno)); + if(chdir(handle->root) != 0) { + _alpm_log(handle, ALPM_LOG_ERROR, _("could not change directory to %s (%s)\n"), + handle->root, strerror(errno)); goto cleanup; } - _alpm_log(PM_LOG_DEBUG, "executing \"%s\" under chroot \"%s\"\n", path, root); + _alpm_log(handle, ALPM_LOG_DEBUG, "executing \"%s\" under chroot \"%s\"\n", + path, handle->root); /* Flush open fds before fork() to avoid cloning buffers */ fflush(NULL); if(pipe(pipefd) == -1) { - _alpm_log(PM_LOG_ERROR, _("could not create pipe (%s)\n"), strerror(errno)); + _alpm_log(handle, ALPM_LOG_ERROR, _("could not create pipe (%s)\n"), strerror(errno)); retval = 1; goto cleanup; } @@ -455,7 +518,7 @@ int _alpm_run_chroot(const char *root, const char *path, char *const argv[]) /* fork- parent and child each have seperate code blocks below */ pid = fork(); if(pid == -1) { - _alpm_log(PM_LOG_ERROR, _("could not fork a new process (%s)\n"), strerror(errno)); + _alpm_log(handle, ALPM_LOG_ERROR, _("could not fork a new process (%s)\n"), strerror(errno)); retval = 1; goto cleanup; } @@ -470,7 +533,7 @@ int _alpm_run_chroot(const char *root, const char *path, char *const argv[]) close(pipefd[1]); /* use fprintf instead of _alpm_log to send output through the parent */ - if(chroot(root) != 0) { + if(chroot(handle->root) != 0) { fprintf(stderr, _("could not change the root directory (%s)\n"), strerror(errno)); exit(1); } @@ -486,27 +549,27 @@ int _alpm_run_chroot(const char *root, const char *path, char *const argv[]) } else { /* this code runs for the parent only (wait on the child) */ int status; - FILE *pipe; + FILE *pipe_file; close(pipefd[1]); - pipe = fdopen(pipefd[0], "r"); - if(pipe == NULL) { + pipe_file = fdopen(pipefd[0], "r"); + if(pipe_file == NULL) { close(pipefd[0]); retval = 1; } else { - while(!feof(pipe)) { + while(!feof(pipe_file)) { char line[PATH_MAX]; - if(fgets(line, PATH_MAX, pipe) == NULL) + if(fgets(line, PATH_MAX, pipe_file) == NULL) break; - alpm_logaction("%s", line); - EVENT(handle->trans, PM_TRANS_EVT_SCRIPTLET_INFO, line, NULL); + alpm_logaction(handle, "%s", line); + EVENT(handle->trans, ALPM_TRANS_EVT_SCRIPTLET_INFO, line, NULL); } - fclose(pipe); + fclose(pipe_file); } while(waitpid(pid, &status, 0) == -1) { if(errno != EINTR) { - _alpm_log(PM_LOG_ERROR, _("call to waitpid failed (%s)\n"), strerror(errno)); + _alpm_log(handle, ALPM_LOG_ERROR, _("call to waitpid failed (%s)\n"), strerror(errno)); retval = 1; goto cleanup; } @@ -514,14 +577,14 @@ int _alpm_run_chroot(const char *root, const char *path, char *const argv[]) /* report error from above after the child has exited */ if(retval != 0) { - _alpm_log(PM_LOG_ERROR, _("could not open pipe (%s)\n"), strerror(errno)); + _alpm_log(handle, ALPM_LOG_ERROR, _("could not open pipe (%s)\n"), strerror(errno)); goto cleanup; } /* check the return status, make sure it is 0 (success) */ if(WIFEXITED(status)) { - _alpm_log(PM_LOG_DEBUG, "call to waitpid succeeded\n"); + _alpm_log(handle, ALPM_LOG_DEBUG, "call to waitpid succeeded\n"); if(WEXITSTATUS(status) != 0) { - _alpm_log(PM_LOG_ERROR, _("command failed to execute correctly\n")); + _alpm_log(handle, ALPM_LOG_ERROR, _("command failed to execute correctly\n")); retval = 1; } } @@ -529,42 +592,43 @@ int _alpm_run_chroot(const char *root, const char *path, char *const argv[]) cleanup: if(restore_cwd && chdir(cwd) != 0) { - _alpm_log(PM_LOG_ERROR, _("could not change directory to %s (%s)\n"), cwd, strerror(errno)); + _alpm_log(handle, ALPM_LOG_ERROR, _("could not change directory to %s (%s)\n"), cwd, strerror(errno)); } - return(retval); + return retval; } -int _alpm_ldconfig(const char *root) +int _alpm_ldconfig(alpm_handle_t *handle) { char line[PATH_MAX]; - _alpm_log(PM_LOG_DEBUG, "running ldconfig\n"); + _alpm_log(handle, ALPM_LOG_DEBUG, "running ldconfig\n"); - snprintf(line, PATH_MAX, "%setc/ld.so.conf", root); + snprintf(line, PATH_MAX, "%setc/ld.so.conf", handle->root); if(access(line, F_OK) == 0) { - snprintf(line, PATH_MAX, "%ssbin/ldconfig", root); + snprintf(line, PATH_MAX, "%ssbin/ldconfig", handle->root); if(access(line, X_OK) == 0) { char *argv[] = { "ldconfig", NULL }; - _alpm_run_chroot(root, "/sbin/ldconfig", argv); + _alpm_run_chroot(handle, "/sbin/ldconfig", argv); } } - return(0); + return 0; } /* Helper function for comparing strings using the * alpm "compare func" signature */ int _alpm_str_cmp(const void *s1, const void *s2) { - return(strcmp(s1, s2)); + return strcmp(s1, s2); } /** Find a filename in a registered alpm cachedir. + * @param handle the context handle * @param filename name of file to find * @return malloced path of file, NULL if not found */ -char *_alpm_filecache_find(const char* filename) +char *_alpm_filecache_find(alpm_handle_t *handle, const char *filename) { char path[PATH_MAX]; char *retpath; @@ -572,52 +636,56 @@ char *_alpm_filecache_find(const char* filename) struct stat buf; /* Loop through the cache dirs until we find a matching file */ - for(i = alpm_option_get_cachedirs(); i; i = alpm_list_next(i)) { - snprintf(path, PATH_MAX, "%s%s", (char*)alpm_list_getdata(i), + for(i = alpm_option_get_cachedirs(handle); i; i = alpm_list_next(i)) { + snprintf(path, PATH_MAX, "%s%s", (char *)alpm_list_getdata(i), filename); if(stat(path, &buf) == 0 && S_ISREG(buf.st_mode)) { retpath = strdup(path); - _alpm_log(PM_LOG_DEBUG, "found cached pkg: %s\n", retpath); - return(retpath); + _alpm_log(handle, ALPM_LOG_DEBUG, "found cached pkg: %s\n", retpath); + return retpath; } } /* package wasn't found in any cachedir */ - RET_ERR(PM_ERR_PKG_NOT_FOUND, NULL); + return NULL; } /** Check the alpm cachedirs for existance and find a writable one. * If no valid cache directory can be found, use /tmp. + * @param handle the context handle * @return pointer to a writable cache directory. */ -const char *_alpm_filecache_setup(void) +const char *_alpm_filecache_setup(alpm_handle_t *handle) { struct stat buf; alpm_list_t *i, *tmp; char *cachedir; /* Loop through the cache dirs until we find a writeable dir */ - for(i = alpm_option_get_cachedirs(); i; i = alpm_list_next(i)) { + for(i = alpm_option_get_cachedirs(handle); i; i = alpm_list_next(i)) { cachedir = alpm_list_getdata(i); if(stat(cachedir, &buf) != 0) { /* cache directory does not exist.... try creating it */ - _alpm_log(PM_LOG_WARNING, _("no %s cache exists, creating...\n"), + _alpm_log(handle, ALPM_LOG_WARNING, _("no %s cache exists, creating...\n"), cachedir); if(_alpm_makepath(cachedir) == 0) { - _alpm_log(PM_LOG_DEBUG, "using cachedir: %s\n", cachedir); - return(cachedir); + _alpm_log(handle, ALPM_LOG_DEBUG, "using cachedir: %s\n", cachedir); + return cachedir; } } else if(S_ISDIR(buf.st_mode) && (buf.st_mode & S_IWUSR)) { - _alpm_log(PM_LOG_DEBUG, "using cachedir: %s\n", cachedir); - return(cachedir); + _alpm_log(handle, ALPM_LOG_DEBUG, "using cachedir: %s\n", cachedir); + return cachedir; + } else { + _alpm_log(handle, ALPM_LOG_DEBUG, "skipping cachedir: %s\n", cachedir); } } /* we didn't find a valid cache directory. use /tmp. */ - tmp = alpm_list_add(NULL, strdup("/tmp/")); - alpm_option_set_cachedirs(tmp); - _alpm_log(PM_LOG_DEBUG, "using cachedir: %s", "/tmp/\n"); - _alpm_log(PM_LOG_WARNING, _("couldn't create package cache, using /tmp instead\n")); - return(alpm_list_getdata(tmp)); + tmp = alpm_list_add(NULL, "/tmp/"); + alpm_option_set_cachedirs(handle, tmp); + alpm_list_free(tmp); + _alpm_log(handle, ALPM_LOG_DEBUG, "using cachedir: %s\n", "/tmp/"); + _alpm_log(handle, ALPM_LOG_WARNING, _("couldn't create package cache, using /tmp instead\n")); + return "/tmp/"; } /** lstat wrapper that treats /path/dirsymlink/ the same as /path/dirsymlink. @@ -630,18 +698,19 @@ const char *_alpm_filecache_setup(void) int _alpm_lstat(const char *path, struct stat *buf) { int ret; - char *newpath = strdup(path); - size_t len = strlen(newpath); + size_t len = strlen(path); /* strip the trailing slash if one exists */ - if(len != 0 && newpath[len - 1] == '/') { - newpath[len - 1] = '\0'; + if(len != 0 && path[len - 1] == '/') { + char *newpath = strdup(path); + newpath[len - 1] = '\0'; + ret = lstat(newpath, buf); + free(newpath); + } else { + ret = lstat(path, buf); } - ret = lstat(newpath, buf); - - FREE(newpath); - return(ret); + return ret; } #ifdef HAVE_LIBSSL @@ -652,11 +721,11 @@ static int md5_file(const char *path, unsigned char output[16]) MD5_CTX ctx; unsigned char *buf; - CALLOC(buf, 8192, sizeof(unsigned char), return(1)); + CALLOC(buf, 8192, sizeof(unsigned char), return 1); if((f = fopen(path, "rb")) == NULL) { free(buf); - return(1); + return 1; } MD5_Init(&ctx); @@ -672,11 +741,11 @@ static int md5_file(const char *path, unsigned char output[16]) if(ferror(f) != 0) { fclose(f); - return(2); + return 2; } fclose(f); - return(0); + return 0; } #endif @@ -691,17 +760,15 @@ char SYMEXPORT *alpm_compute_md5sum(const char *filename) char *md5sum; int ret, i; - ALPM_LOG_FUNC; - - ASSERT(filename != NULL, return(NULL)); + ASSERT(filename != NULL, return NULL); /* allocate 32 chars plus 1 for null */ - md5sum = calloc(33, sizeof(char)); + CALLOC(md5sum, 33, sizeof(char), return NULL); /* defined above for OpenSSL, otherwise defined in md5.h */ ret = md5_file(filename, output); - if (ret > 0) { - RET_ERR(PM_ERR_NOT_A_FILE, NULL); + if(ret > 0) { + return NULL; } /* Convert the result to something readable */ @@ -709,10 +776,8 @@ char SYMEXPORT *alpm_compute_md5sum(const char *filename) /* sprintf is acceptable here because we know our output */ sprintf(md5sum +(i * 2), "%02x", output[i]); } - md5sum[32] = '\0'; - _alpm_log(PM_LOG_DEBUG, "md5(%s) = %s\n", filename, md5sum); - return(md5sum); + return md5sum; } int _alpm_test_md5sum(const char *filepath, const char *md5sum) @@ -731,7 +796,7 @@ int _alpm_test_md5sum(const char *filepath, const char *md5sum) } FREE(md5sum2); - return(ret); + return ret; } /* Note: does NOT handle sparse files on purpose for speed. */ @@ -753,13 +818,12 @@ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b) } /* zero-copy - this is the entire next block of data. */ - b->ret = archive_read_data_block(a, (void*)&b->block, + b->ret = archive_read_data_block(a, (void *)&b->block, &b->block_size, &offset); b->block_offset = b->block; - /* error or end of archive with no data read, cleanup */ - if(b->ret < ARCHIVE_OK || - (b->block_size == 0 && b->ret == ARCHIVE_EOF)) { + /* error, cleanup */ + if(b->ret < ARCHIVE_OK) { goto cleanup; } } @@ -776,20 +840,20 @@ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b) /* allocate our buffer, or ensure our existing one is big enough */ if(!b->line) { /* set the initial buffer to the read block_size */ - CALLOC(b->line, b->block_size + 1, sizeof(char), - RET_ERR(PM_ERR_MEMORY, -1)); + CALLOC(b->line, b->block_size + 1, sizeof(char), b->ret = -ENOMEM; goto cleanup); b->line_size = b->block_size + 1; b->line_offset = b->line; } else { size_t needed = (size_t)((b->line_offset - b->line) + (i - b->block_offset) + 1); if(needed > b->max_line_size) { - RET_ERR(PM_ERR_MEMORY, -1); + b->ret = -ERANGE; + goto cleanup; } if(needed > b->line_size) { /* need to realloc + copy data to fit total length */ char *new; - CALLOC(new, needed, sizeof(char), RET_ERR(PM_ERR_MEMORY, -1)); + CALLOC(new, needed, sizeof(char), b->ret = -ENOMEM; goto cleanup); memcpy(new, b->line, b->line_size); b->line_size = needed; b->line_offset = new + (b->line_offset - b->line); @@ -804,13 +868,19 @@ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b) b->line_offset[len] = '\0'; b->block_offset = ++i; /* this is the main return point; from here you can read b->line */ - return(ARCHIVE_OK); + return ARCHIVE_OK; } else { /* we've looked through the whole block but no newline, copy it */ size_t len = (size_t)(b->block + b->block_size - b->block_offset); memcpy(b->line_offset, b->block_offset, len); b->line_offset += len; b->block_offset = i; + /* there was no new data, return what is left; saved ARCHIVE_EOF will be + * returned on next call */ + if(len == 0) { + b->line_offset[0] = '\0'; + return ARCHIVE_OK; + } } } @@ -819,53 +889,60 @@ cleanup: int ret = b->ret; FREE(b->line); memset(b, 0, sizeof(b)); - return(ret); + return ret; } } -int _alpm_splitname(const char *target, pmpkg_t *pkg) +int _alpm_splitname(const char *target, char **name, char **version, + unsigned long *name_hash) { /* the format of a db entry is as follows: * package-version-rel/ + * package-version-rel/desc (we ignore the filename portion) * package name can contain hyphens, so parse from the back- go back * two hyphens and we have split the version from the name. */ - const char *version, *end; + const char *pkgver, *end; - if(target == NULL || pkg == NULL) { - return(-1); + if(target == NULL) { + return -1; } - end = target + strlen(target); - /* remove any trailing '/' */ - while (*(end - 1) == '/') { - --end; + /* remove anything trailing a '/' */ + end = strchr(target, '/'); + if(!end) { + end = target + strlen(target); } /* do the magic parsing- find the beginning of the version string * by doing two iterations of same loop to lop off two hyphens */ - for(version = end - 1; *version && *version != '-'; version--); - for(version = version - 1; *version && *version != '-'; version--); - if(*version != '-' || version == target) { - return(-1); + for(pkgver = end - 1; *pkgver && *pkgver != '-'; pkgver--); + for(pkgver = pkgver - 1; *pkgver && *pkgver != '-'; pkgver--); + if(*pkgver != '-' || pkgver == target) { + return -1; } /* copy into fields and return */ - if(pkg->version) { - FREE(pkg->version); + if(version) { + if(*version) { + FREE(*version); + } + /* version actually points to the dash, so need to increment 1 and account + * for potential end character */ + STRNDUP(*version, pkgver + 1, end - pkgver - 1, return -1); } - /* version actually points to the dash, so need to increment 1 and account - * for potential end character */ - STRNDUP(pkg->version, version + 1, end - version - 1, - RET_ERR(PM_ERR_MEMORY, -1)); - if(pkg->name) { - FREE(pkg->name); + if(name) { + if(*name) { + FREE(*name); + } + STRNDUP(*name, target, pkgver - target, return -1); + if(name_hash) { + *name_hash = _alpm_hash_sdbm(*name); + } } - STRNDUP(pkg->name, target, version - target, RET_ERR(PM_ERR_MEMORY, -1)); - pkg->name_hash = _alpm_hash_sdbm(pkg->name); - return(0); + return 0; } /** @@ -880,13 +957,13 @@ unsigned long _alpm_hash_sdbm(const char *str) int c; if(!str) { - return(hash); + return hash; } while((c = *str++)) { hash = c + (hash << 6) + (hash << 16) - hash; } - return(hash); + return hash; } long _alpm_parsedate(const char *line) @@ -897,9 +974,56 @@ long _alpm_parsedate(const char *line) setlocale(LC_TIME, "C"); strptime(line, "%a %b %e %H:%M:%S %Y", &tmp_tm); setlocale(LC_TIME, ""); - return(mktime(&tmp_tm)); + return mktime(&tmp_tm); + } + return atol(line); +} + +/** + * Wrapper around access() which takes a dir and file argument + * separately and generates an appropriate error message. + * If dir is NULL file will be treated as the whole path. + * @param handle an alpm handle + * @param dir directory path ending with and slash + * @param file filename + * @param amode access mode as described in access() + * @return int value returned by access() + */ + +int _alpm_access(alpm_handle_t *handle, const char *dir, const char *file, int amode) +{ + size_t len = 0; + int ret = 0; + + if (dir) { + char *check_path; + + len = strlen(dir) + strlen(file) + 1; + CALLOC(check_path, len, sizeof(char), RET_ERR(handle, ALPM_ERR_MEMORY, -1)); + snprintf(check_path, len, "%s%s", dir, file); + + ret = access(check_path, amode); + free(check_path); + } else { + dir = ""; + ret = access(file, amode); + } + + if(ret != 0) { + if (amode & R_OK) { + _alpm_log(handle, ALPM_LOG_DEBUG, _("\"%s%s\" is not readable: %s\n"), dir, file, strerror(errno)); + } + if (amode & W_OK) { + _alpm_log(handle, ALPM_LOG_DEBUG, _("\"%s%s\" is not writable: %s\n"), dir, file, strerror(errno)); + } + if (amode & X_OK) { + _alpm_log(handle, ALPM_LOG_DEBUG, _("\"%s%s\" is not executable: %s\n"), dir, file, strerror(errno)); + } + if (amode == F_OK) { + _alpm_log(handle, ALPM_LOG_DEBUG, _("\"%s%s\" does not exist: %s\n"), dir, file, strerror(errno)); + } } - return(atol(line)); + return ret; } #ifndef HAVE_STRNDUP @@ -908,7 +1032,7 @@ static size_t strnlen(const char *s, size_t max) { register const char *p; for(p = s; *p && max--; ++p); - return(p - s); + return (p - s); } char *strndup(const char *s, size_t n) @@ -916,11 +1040,11 @@ char *strndup(const char *s, size_t n) size_t len = strnlen(s, n); char *new = (char *) malloc(len + 1); - if (new == NULL) + if(new == NULL) return NULL; new[len] = '\0'; - return (char *) memcpy(new, s, len); + return (char *)memcpy(new, s, len); } #endif diff --git a/lib/libalpm/util.h b/lib/libalpm/util.h index c66e9881..9ee63709 100644 --- a/lib/libalpm/util.h +++ b/lib/libalpm/util.h @@ -27,7 +27,9 @@ #include "config.h" #include "alpm_list.h" -#include "package.h" /* pmpkg_t */ +#include "alpm.h" +#include "package.h" /* alpm_pkg_t */ +#include "handle.h" /* alpm_handle_t */ #include <stdio.h> #include <string.h> @@ -36,6 +38,8 @@ #include <time.h> #include <sys/stat.h> /* struct stat */ #include <archive.h> /* struct archive */ +#include <math.h> /* fabs */ +#include <float.h> /* DBL_EPSILON */ #ifdef ENABLE_NLS #include <libintl.h> /* here so it doesn't need to be included elsewhere */ @@ -45,7 +49,7 @@ #define _(s) s #endif -#define ALLOC_FAIL(s) do { _alpm_log(PM_LOG_ERROR, _("alloc failure: could not allocate %zd bytes\n"), s); } while(0) +#define ALLOC_FAIL(s) do { fprintf(stderr, "alloc failure: could not allocate %zd bytes\n", s); } while(0) #define MALLOC(p, s, action) do { p = calloc(1, s); if(p == NULL) { ALLOC_FAIL(s); action; } } while(0) #define CALLOC(p, l, s, action) do { p = calloc(l, s); if(p == NULL) { ALLOC_FAIL(s); action; } } while(0) @@ -57,13 +61,19 @@ #define ASSERT(cond, action) do { if(!(cond)) { action; } } while(0) -#define RET_ERR_VOID(err) do { pm_errno = (err); \ - _alpm_log(PM_LOG_DEBUG, "returning error %d from %s : %s\n", err, __func__, alpm_strerrorlast()); \ +#define RET_ERR_VOID(handle, err) do { \ + _alpm_log(handle, ALPM_LOG_DEBUG, "returning error %d from %s : %s\n", err, __func__, alpm_strerror(err)); \ + (handle)->pm_errno = (err); \ return; } while(0) -#define RET_ERR(err, ret) do { pm_errno = (err); \ - _alpm_log(PM_LOG_DEBUG, "returning error %d from %s : %s\n", err, __func__, alpm_strerrorlast()); \ - return(ret); } while(0) +#define RET_ERR(handle, err, ret) do { \ + _alpm_log(handle, ALPM_LOG_DEBUG, "returning error %d from %s : %s\n", err, __func__, alpm_strerror(err)); \ + (handle)->pm_errno = (err); \ + return (ret); } while(0) + +#define DOUBLE_EQ(x, y) (fabs((x) - (y)) < DBL_EPSILON) + +#define CHECK_HANDLE(handle, action) do { if(!(handle)) { action; } (handle)->pm_errno = 0; } while(0) /** * Used as a buffer/state holder for _alpm_archive_fgets(). @@ -85,21 +95,29 @@ int _alpm_makepath(const char *path); int _alpm_makepath_mode(const char *path, mode_t mode); int _alpm_copyfile(const char *src, const char *dest); char *_alpm_strtrim(char *str); -int _alpm_unpack_single(const char *archive, const char *prefix, const char *fn); -int _alpm_unpack(const char *archive, const char *prefix, alpm_list_t *list, int breakfirst); +size_t _alpm_strip_newline(char *str); +int _alpm_unpack_single(alpm_handle_t *handle, const char *archive, + const char *prefix, const char *filename); +int _alpm_unpack(alpm_handle_t *handle, const char *archive, const char *prefix, + alpm_list_t *list, int breakfirst); int _alpm_rmrf(const char *path); -int _alpm_logaction(int usesyslog, FILE *f, const char *fmt, va_list args); -int _alpm_run_chroot(const char *root, const char *path, char *const argv[]); -int _alpm_ldconfig(const char *root); +ssize_t _alpm_files_in_directory(alpm_handle_t *handle, const char *path, int full_count); +int _alpm_logaction(alpm_handle_t *handle, const char *fmt, va_list args); +int _alpm_run_chroot(alpm_handle_t *handle, const char *path, char *const argv[]); +int _alpm_ldconfig(alpm_handle_t *handle); int _alpm_str_cmp(const void *s1, const void *s2); -char *_alpm_filecache_find(const char *filename); -const char *_alpm_filecache_setup(void); +char *_alpm_filecache_find(alpm_handle_t *handle, const char *filename); +const char *_alpm_filecache_setup(alpm_handle_t *handle); int _alpm_lstat(const char *path, struct stat *buf); int _alpm_test_md5sum(const char *filepath, const char *md5sum); int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b); -int _alpm_splitname(const char *target, pmpkg_t *pkg); +int _alpm_splitname(const char *target, char **name, char **version, + unsigned long *name_hash); unsigned long _alpm_hash_sdbm(const char *str); long _alpm_parsedate(const char *line); +int _alpm_raw_cmp(const char *first, const char *second); +int _alpm_raw_ncmp(const char *first, const char *second, size_t max); +int _alpm_access(alpm_handle_t *handle, const char *dir, const char *file, int amode); #ifndef HAVE_STRSEP char *strsep(char **, const char *); @@ -113,6 +131,8 @@ char *strndup(const char *s, size_t n); #define SYMEXPORT __attribute__((visibility("default"))) #define SYMHIDDEN __attribute__((visibility("internal"))) +#define UNUSED __attribute__((unused)) + #endif /* _ALPM_UTIL_H */ /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/version.c b/lib/libalpm/version.c index eba66210..9f3a9b71 100644 --- a/lib/libalpm/version.c +++ b/lib/libalpm/version.c @@ -93,7 +93,7 @@ static int rpmvercmp(const char *a, const char *b) int ret = 0; /* easy comparison to see if versions are identical */ - if(strcmp(a, b) == 0) return(0); + if(strcmp(a, b) == 0) return 0; str1 = strdup(a); str2 = strdup(b); @@ -209,7 +209,7 @@ static int rpmvercmp(const char *a, const char *b) cleanup: free(str1); free(str2); - return(ret); + return ret; } /** Compare two version strings and determine which one is 'newer'. @@ -235,15 +235,15 @@ int SYMEXPORT alpm_pkg_vercmp(const char *a, const char *b) /* ensure our strings are not null */ if(!a && !b) { - return(0); + return 0; } else if(!a) { - return(-1); + return -1; } else if(!b) { - return(1); + return 1; } /* another quick shortcut- if full version specs are equal */ if(strcmp(a, b) == 0) { - return(0); + return 0; } /* Parse both versions into [epoch:]version[-release] triplets. We probably @@ -266,7 +266,7 @@ int SYMEXPORT alpm_pkg_vercmp(const char *a, const char *b) free(full1); free(full2); - return(ret); + return ret; } /* vim: set ts=2 sw=2 noet: */ |