diff options
Diffstat (limited to 'lib/libalpm/package.c')
-rw-r--r-- | lib/libalpm/package.c | 615 |
1 files changed, 184 insertions, 431 deletions
diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c index 794a2f7d..3708a58a 100644 --- a/lib/libalpm/package.c +++ b/lib/libalpm/package.c @@ -31,7 +31,6 @@ #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> -#include <locale.h> /* setlocale */ /* libarchive */ #include <archive.h> @@ -42,7 +41,6 @@ #include "alpm_list.h" #include "log.h" #include "util.h" -#include "error.h" #include "db.h" #include "cache.h" #include "delta.h" @@ -54,42 +52,13 @@ * @{ */ -/** 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. - * @param filename location of the package tarball - * @param full whether to stop the load after metadata is read or continue - * through the full archive - * @param pkg address of the package pointer - * @return 0 on success, -1 on error (pm_errno is set accordingly) - */ -int SYMEXPORT alpm_pkg_load(const char *filename, unsigned short full, - pmpkg_t **pkg) -{ - _alpm_log(PM_LOG_FUNCTION, "enter alpm_pkg_load\n"); - - /* 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)); - - *pkg = _alpm_pkg_load(filename, full); - if(*pkg == NULL) { - /* pm_errno is set by pkg_load */ - return(-1); - } - - return(0); -} - /** Free a package. * @param pkg package pointer to free * @return 0 on success, -1 on error (pm_errno is set accordingly) */ int SYMEXPORT alpm_pkg_free(pmpkg_t *pkg) { - _alpm_log(PM_LOG_FUNCTION, "enter alpm_pkg_free\n"); + ALPM_LOG_FUNC; ASSERT(pkg != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); @@ -108,8 +77,7 @@ int SYMEXPORT alpm_pkg_free(pmpkg_t *pkg) int SYMEXPORT alpm_pkg_checkmd5sum(pmpkg_t *pkg) { char *fpath; - char *md5sum = NULL; - int retval = 0; + int retval; ALPM_LOG_FUNC; @@ -119,44 +87,19 @@ int SYMEXPORT alpm_pkg_checkmd5sum(pmpkg_t *pkg) ASSERT(pkg->origin_data.db != handle->db_local, RET_ERR(PM_ERR_PKG_INVALID, -1)); fpath = _alpm_filecache_find(alpm_pkg_get_filename(pkg)); - md5sum = alpm_get_md5sum(fpath); - if(md5sum == NULL) { - _alpm_log(PM_LOG_ERROR, _("could not get md5sum for package %s-%s\n"), - alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg)); - pm_errno = PM_ERR_NOT_A_FILE; + 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; retval = -1; - } else { - if(strcmp(md5sum, alpm_pkg_get_md5sum(pkg)) == 0) { - _alpm_log(PM_LOG_DEBUG, "md5sums for package %s-%s match\n", - alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg)); - } else { - _alpm_log(PM_LOG_ERROR, _("md5sums do not match for package %s-%s\n"), - alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg)); - pm_errno = PM_ERR_PKG_INVALID; - retval = -1; - } } - FREE(fpath); - FREE(md5sum); - return(retval); } -/** Compare versions. - * @param ver1 first version - * @param ver2 secont version - * @return postive, 0 or negative if ver1 is less, equal or more - * than ver2, respectively. - */ -int SYMEXPORT alpm_pkg_vercmp(const char *ver1, const char *ver2) -{ - ALPM_LOG_FUNC; - - return(_alpm_versioncmp(ver1, ver2)); -} - const char SYMEXPORT *alpm_pkg_get_filename(pmpkg_t *pkg) { ALPM_LOG_FUNC; @@ -169,45 +112,18 @@ const char SYMEXPORT *alpm_pkg_get_filename(pmpkg_t *pkg) _alpm_db_read(pkg->origin_data.db, pkg, INFRQ_DESC); } - if(!strlen(pkg->filename)) { - /* construct the file name, it's not in the desc file */ - if(pkg->arch && strlen(pkg->arch) > 0) { - snprintf(pkg->filename, PKG_FILENAME_LEN, "%s-%s-%s" PKGEXT, - pkg->name, pkg->version, pkg->arch); - } else { - snprintf(pkg->filename, PKG_FILENAME_LEN, "%s-%s" PKGEXT, - pkg->name, pkg->version); - } - } - return pkg->filename; } const char SYMEXPORT *alpm_pkg_get_name(pmpkg_t *pkg) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); ASSERT(pkg != NULL, return(NULL)); - - if(pkg->origin == PKG_FROM_CACHE && !(pkg->infolevel & INFRQ_BASE)) { - _alpm_db_read(pkg->origin_data.db, pkg, INFRQ_BASE); - } return pkg->name; } const char SYMEXPORT *alpm_pkg_get_version(pmpkg_t *pkg) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); ASSERT(pkg != NULL, return(NULL)); - - if(pkg->origin == PKG_FROM_CACHE && !(pkg->infolevel & INFRQ_BASE)) { - _alpm_db_read(pkg->origin_data.db, pkg, INFRQ_BASE); - } return pkg->version; } @@ -309,7 +225,7 @@ const char SYMEXPORT *alpm_pkg_get_arch(pmpkg_t *pkg) return pkg->arch; } -unsigned long SYMEXPORT alpm_pkg_get_size(pmpkg_t *pkg) +off_t SYMEXPORT alpm_pkg_get_size(pmpkg_t *pkg) { ALPM_LOG_FUNC; @@ -323,7 +239,7 @@ unsigned long SYMEXPORT alpm_pkg_get_size(pmpkg_t *pkg) return pkg->size; } -unsigned long SYMEXPORT alpm_pkg_get_isize(pmpkg_t *pkg) +off_t SYMEXPORT alpm_pkg_get_isize(pmpkg_t *pkg) { ALPM_LOG_FUNC; @@ -523,7 +439,7 @@ void SYMEXPORT *alpm_pkg_changelog_open(pmpkg_t *pkg) int ret = ARCHIVE_OK; if((archive = archive_read_new()) == NULL) { - RET_ERR(PM_ERR_LIBARCHIVE_ERROR, NULL); + RET_ERR(PM_ERR_LIBARCHIVE, NULL); } archive_read_support_compression_all(archive); @@ -650,108 +566,178 @@ alpm_list_t SYMEXPORT *alpm_pkg_compute_requiredby(pmpkg_t *pkg) return(reqs); } -/** @} */ - -/* this function was taken from rpm 4.0.4 and rewritten */ -int _alpm_versioncmp(const char *a, const char *b) +/** Compare two version strings and determine which one is 'newer'. + * Returns a value comparable to the way strcmp works. Returns 1 + * if a is newer than b, 0 if a and b are the same version, or -1 + * if b is newer than a. + * + * This function has been adopted from the rpmvercmp function located + * at lib/rpmvercmp.c, and was most recently updated against rpm + * version 4.4.2.3. Small modifications have been made to make it more + * consistent with the libalpm coding style. + * + * Keep in mind that the pkgrel is only compared if it is available + * on both versions handed to this function. For example, comparing + * 1.5-1 and 1.5 will yield 0; comparing 1.5-1 and 1.5-2 will yield + * -1 as expected. This is mainly for supporting versioned dependencies + * that do not include the pkgrel. + */ +int SYMEXPORT alpm_pkg_vercmp(const char *a, const char *b) { - char str1[64], str2[64]; + char oldch1, oldch2; + char *str1, *str2; char *ptr1, *ptr2; char *one, *two; - char *rel1 = NULL, *rel2 = NULL; - char oldch1, oldch2; - int is1num, is2num; int rc; + int isnum; + int ret = 0; ALPM_LOG_FUNC; - if(!strcmp(a,b)) { - return(0); + /* libalpm added code. ensure our strings are not null */ + if(!a) { + if(!b) return(0); + return(-1); } + if(!b) return(1); - strncpy(str1, a, 64); - str1[63] = 0; - strncpy(str2, b, 64); - str2[63] = 0; + /* easy comparison to see if versions are identical */ + if(strcmp(a, b) == 0) return(0); - /* lose the release number */ - for(one = str1; *one && *one != '-'; one++); - if(one) { - *one = '\0'; - rel1 = ++one; - } - for(two = str2; *two && *two != '-'; two++); - if(two) { - *two = '\0'; - rel2 = ++two; - } + str1 = strdup(a); + str2 = strdup(b); one = str1; two = str2; - while(*one || *two) { + /* loop through each version segment of str1 and str2 and compare them */ + while(*one && *two) { while(*one && !isalnum((int)*one)) one++; while(*two && !isalnum((int)*two)) two++; + /* If we ran to the end of either, we are finished with the loop */ + if(!(*one && *two)) break; + ptr1 = one; ptr2 = two; - /* find the next segment for each string */ + /* grab first completely alpha or completely numeric segment */ + /* leave one and two pointing to the start of the alpha or numeric */ + /* segment and walk ptr1 and ptr2 to end of segment */ if(isdigit((int)*ptr1)) { - is1num = 1; while(*ptr1 && isdigit((int)*ptr1)) ptr1++; - } else { - is1num = 0; - while(*ptr1 && isalpha((int)*ptr1)) ptr1++; - } - if(isdigit((int)*ptr2)) { - is2num = 1; while(*ptr2 && isdigit((int)*ptr2)) ptr2++; + isnum = 1; } else { - is2num = 0; + while(*ptr1 && isalpha((int)*ptr1)) ptr1++; while(*ptr2 && isalpha((int)*ptr2)) ptr2++; + isnum = 0; } + /* save character at the end of the alpha or numeric segment */ + /* so that they can be restored after the comparison */ oldch1 = *ptr1; *ptr1 = '\0'; oldch2 = *ptr2; *ptr2 = '\0'; - /* see if we ran out of segments on one string */ - if(one == ptr1 && two != ptr2) { - return(is2num ? -1 : 1); + /* this cannot happen, as we previously tested to make sure that */ + /* the first string has a non-null segment */ + if (one == ptr1) { + ret = -1; /* arbitrary */ + goto cleanup; } - if(one != ptr1 && two == ptr2) { - return(is1num ? 1 : -1); + + /* take care of the case where the two version segments are */ + /* different types: one numeric, the other alpha (i.e. empty) */ + /* numeric segments are always newer than alpha segments */ + /* XXX See patch #60884 (and details) from bugzilla #50977. */ + if (two == ptr2) { + ret = isnum ? 1 : -1; + goto cleanup; } - /* see if we have a type mismatch (ie, one is alpha and one is digits) */ - if(is1num && !is2num) return(1); - if(!is1num && is2num) return(-1); + if (isnum) { + /* this used to be done by converting the digit segments */ + /* to ints using atoi() - it's changed because long */ + /* digit segments can overflow an int - this should fix that. */ - if(is1num) while(*one == '0') one++; - if(is2num) while(*two == '0') two++; + /* throw away any leading zeros - it's a number, right? */ + while (*one == '0') one++; + while (*two == '0') two++; - rc = strverscmp(one, two); - if(rc) return(rc); + /* whichever number has more digits wins */ + if (strlen(one) > strlen(two)) { + ret = 1; + goto cleanup; + } + if (strlen(two) > strlen(one)) { + ret = -1; + goto cleanup; + } + } + /* strcmp will return which one is greater - even if the two */ + /* segments are alpha or if they are numeric. don't return */ + /* if they are equal because there might be more segments to */ + /* compare */ + rc = strcmp(one, two); + if (rc) { + ret = rc < 1 ? -1 : 1; + goto cleanup; + } + + /* restore character that was replaced by null above */ *ptr1 = oldch1; - *ptr2 = oldch2; one = ptr1; + *ptr2 = oldch2; two = ptr2; + + /* libalpm added code. check if version strings have hit the pkgrel + * portion. depending on which strings have hit, take correct action. + * this is all based on the premise that we only have one dash in + * the version string, and it separates pkgver from pkgrel. */ + if(*ptr1 == '-' && *ptr2 == '-') { + /* no-op, continue comparing since we are equivalent throughout */ + } else if(*ptr1 == '-') { + /* ptr1 has hit the pkgrel and ptr2 has not. + * version 2 is newer iff we are not at the end of ptr2; + * if we are at end then one version had pkgrel and one did not */ + ret = *ptr2 ? -1 : 0; + goto cleanup; + } else if(*ptr2 == '-') { + /* ptr2 has hit the pkgrel and ptr1 has not. + * version 1 is newer iff we are not at the end of ptr1; + * if we are at end then one version had pkgrel and one did not */ + ret = *ptr1 ? 1 : 0; + goto cleanup; + } } - if((!*one) && (!*two)) { - /* compare release numbers */ - if(rel1 && rel2 && strlen(rel1) && strlen(rel2)) return(_alpm_versioncmp(rel1, rel2)); - return(0); + /* this catches the case where all numeric and alpha segments have */ + /* compared identically but the segment separating characters were */ + /* different */ + if ((!*one) && (!*two)) { + ret = 0; + goto cleanup; + } + + /* whichever version still has characters left over wins */ + if (!*one) { + ret = -1; + } else { + ret = 1; } - return(*one ? 1 : -1); +cleanup: + free(str1); + free(str2); + return(ret); } +/** @} */ -pmpkg_t *_alpm_pkg_new(const char *name, const char *version) +pmpkg_t *_alpm_pkg_new(void) { pmpkg_t* pkg; @@ -759,47 +745,56 @@ pmpkg_t *_alpm_pkg_new(const char *name, const char *version) CALLOC(pkg, 1, sizeof(pmpkg_t), RET_ERR(PM_ERR_MEMORY, NULL)); - if(name && name[0] != 0) { - strncpy(pkg->name, name, PKG_NAME_LEN); - } else { - pkg->name[0] = '\0'; - } - if(version && version[0] != 0) { - strncpy(pkg->version, version, PKG_VERSION_LEN); - } else { - pkg->version[0] = '\0'; - } - return(pkg); } pmpkg_t *_alpm_pkg_dup(pmpkg_t *pkg) { - pmpkg_t* newpkg; + pmpkg_t *newpkg; + alpm_list_t *i; ALPM_LOG_FUNC; CALLOC(newpkg, 1, sizeof(pmpkg_t), RET_ERR(PM_ERR_MEMORY, NULL)); - memcpy(newpkg, pkg, sizeof(pmpkg_t)); + 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)); + 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)); + newpkg->size = pkg->size; + newpkg->isize = pkg->isize; + newpkg->scriptlet = pkg->scriptlet; + newpkg->force = pkg->force; + newpkg->reason = pkg->reason; + newpkg->licenses = alpm_list_strdup(alpm_pkg_get_licenses(pkg)); - newpkg->conflicts = alpm_list_strdup(alpm_pkg_get_conflicts(pkg)); + newpkg->replaces = alpm_list_strdup(alpm_pkg_get_replaces(pkg)); + newpkg->groups = alpm_list_strdup(alpm_pkg_get_groups(pkg)); newpkg->files = alpm_list_strdup(alpm_pkg_get_files(pkg)); newpkg->backup = alpm_list_strdup(alpm_pkg_get_backup(pkg)); - newpkg->depends = alpm_list_copy_data(alpm_pkg_get_depends(pkg), - sizeof(pmdepend_t)); + for(i = alpm_pkg_get_depends(pkg); i; i = alpm_list_next(i)) { + newpkg->depends = alpm_list_add(newpkg->depends, _alpm_dep_dup(i->data)); + } newpkg->optdepends = alpm_list_strdup(alpm_pkg_get_optdepends(pkg)); - newpkg->groups = alpm_list_strdup(alpm_pkg_get_groups(pkg)); + newpkg->conflicts = alpm_list_strdup(alpm_pkg_get_conflicts(pkg)); newpkg->provides = alpm_list_strdup(alpm_pkg_get_provides(pkg)); - newpkg->replaces = alpm_list_strdup(alpm_pkg_get_replaces(pkg)); newpkg->deltas = alpm_list_copy_data(alpm_pkg_get_deltas(pkg), - sizeof(pmdelta_t)); + sizeof(pmdelta_t)); + /* internal */ + newpkg->origin = pkg->origin; 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; return(newpkg); } @@ -812,16 +807,28 @@ void _alpm_pkg_free(pmpkg_t *pkg) return; } + FREE(pkg->filename); + FREE(pkg->name); + FREE(pkg->version); + FREE(pkg->desc); + FREE(pkg->url); + FREE(pkg->packager); + FREE(pkg->md5sum); + FREE(pkg->arch); FREELIST(pkg->licenses); + FREELIST(pkg->replaces); + FREELIST(pkg->groups); FREELIST(pkg->files); FREELIST(pkg->backup); - FREELIST(pkg->depends); + alpm_list_free_inner(pkg->depends, (alpm_list_fn_free)_alpm_dep_free); + alpm_list_free(pkg->depends); FREELIST(pkg->optdepends); FREELIST(pkg->conflicts); - FREELIST(pkg->groups); FREELIST(pkg->provides); - FREELIST(pkg->replaces); - FREELIST(pkg->deltas); + alpm_list_free_inner(pkg->deltas, (alpm_list_fn_free)_alpm_delta_free); + alpm_list_free(pkg->deltas); + alpm_list_free(pkg->delta_path); + if(pkg->origin == PKG_FROM_FILE) { FREE(pkg->origin_data.file); } @@ -841,7 +848,7 @@ int _alpm_pkg_compare_versions(pmpkg_t *local_pkg, pmpkg_t *pkg) } /* compare versions and see if we need to upgrade */ - cmp = _alpm_versioncmp(alpm_pkg_get_version(pkg), alpm_pkg_get_version(local_pkg)); + cmp = alpm_pkg_vercmp(alpm_pkg_get_version(pkg), alpm_pkg_get_version(local_pkg)); if(cmp != 0 && pkg->force) { cmp = 1; @@ -863,269 +870,15 @@ int _alpm_pkg_compare_versions(pmpkg_t *local_pkg, pmpkg_t *pkg) */ int _alpm_pkg_cmp(const void *p1, const void *p2) { - pmpkg_t *pk1 = (pmpkg_t *)p1; - pmpkg_t *pk2 = (pmpkg_t *)p2; - - return(strcmp(alpm_pkg_get_name(pk1), alpm_pkg_get_name(pk2))); -} - -/* Parses the package description file for the current package - * TODO: this should ALL be in a backend interface (be_files), we should - * be dealing with the abstracted concepts only in this file - * Returns: 0 on success, 1 on error - * - */ -static int parse_descfile(const char *descfile, pmpkg_t *info) -{ - FILE* fp = NULL; - char line[PATH_MAX]; - char *ptr = NULL; - char *key = NULL; - int linenum = 0; - - ALPM_LOG_FUNC; - - if((fp = fopen(descfile, "r")) == NULL) { - _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), descfile, strerror(errno)); - return(-1); - } - - while(!feof(fp)) { - fgets(line, PATH_MAX, fp); - linenum++; - _alpm_strtrim(line); - if(strlen(line) == 0 || line[0] == '#') { - continue; - } - ptr = line; - key = strsep(&ptr, "="); - if(key == NULL || ptr == NULL) { - _alpm_log(PM_LOG_DEBUG, "%s: syntax error in description file line %d\n", - info->name[0] != '\0' ? info->name : "error", linenum); - } else { - _alpm_strtrim(key); - _alpm_strtrim(ptr); - if(!strcmp(key, "pkgname")) { - strncpy(info->name, ptr, sizeof(info->name)); - } else if(!strcmp(key, "pkgver")) { - strncpy(info->version, ptr, sizeof(info->version)); - } else if(!strcmp(key, "pkgdesc")) { - strncpy(info->desc, ptr, sizeof(info->desc)); - } else if(!strcmp(key, "group")) { - info->groups = alpm_list_add(info->groups, strdup(ptr)); - } else if(!strcmp(key, "url")) { - strncpy(info->url, ptr, sizeof(info->url)); - } else if(!strcmp(key, "license")) { - info->licenses = alpm_list_add(info->licenses, strdup(ptr)); - } else if(!strcmp(key, "builddate")) { - char first = tolower(ptr[0]); - if(first > 'a' && first < 'z') { - struct tm tmp_tm = {0}; //initialize to null incase of failure - setlocale(LC_TIME, "C"); - strptime(ptr, "%a %b %e %H:%M:%S %Y", &tmp_tm); - info->builddate = mktime(&tmp_tm); - setlocale(LC_TIME, ""); - } else { - info->builddate = atol(ptr); - } - } else if(!strcmp(key, "packager")) { - strncpy(info->packager, ptr, sizeof(info->packager)); - } else if(!strcmp(key, "arch")) { - strncpy(info->arch, ptr, sizeof(info->arch)); - } else if(!strcmp(key, "size")) { - /* size in the raw package is uncompressed (installed) size */ - info->isize = atol(ptr); - } else if(!strcmp(key, "depend")) { - pmdepend_t *dep = alpm_splitdep(ptr); - info->depends = alpm_list_add(info->depends, dep); - } else if(!strcmp(key, "optdepend")) { - info->optdepends = alpm_list_add(info->optdepends, strdup(ptr)); - } else if(!strcmp(key, "conflict")) { - info->conflicts = alpm_list_add(info->conflicts, strdup(ptr)); - } else if(!strcmp(key, "replaces")) { - info->replaces = alpm_list_add(info->replaces, strdup(ptr)); - } else if(!strcmp(key, "provides")) { - info->provides = alpm_list_add(info->provides, strdup(ptr)); - } else if(!strcmp(key, "backup")) { - info->backup = alpm_list_add(info->backup, strdup(ptr)); - } else { - _alpm_log(PM_LOG_DEBUG, "%s: syntax error in description file line %d\n", - info->name[0] != '\0' ? info->name : "error", linenum); - } - } - line[0] = '\0'; - } - fclose(fp); - unlink(descfile); - - return(0); -} - - -/** - * Load a package and create the corresponding pmpkg_t struct. - * @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 - */ -pmpkg_t *_alpm_pkg_load(const char *pkgfile, unsigned short full) -{ - int ret = ARCHIVE_OK; - int config = 0; - struct archive *archive; - struct archive_entry *entry; - pmpkg_t *info = NULL; - char *descfile = NULL; - int fd = -1; - struct stat st; - - ALPM_LOG_FUNC; - - if(pkgfile == NULL || strlen(pkgfile) == 0) { - RET_ERR(PM_ERR_WRONG_ARGS, NULL); - } - - if((archive = archive_read_new()) == NULL) { - RET_ERR(PM_ERR_LIBARCHIVE_ERROR, NULL); - } - - archive_read_support_compression_all(archive); - archive_read_support_format_all(archive); - - if (archive_read_open_filename(archive, pkgfile, - ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) { - RET_ERR(PM_ERR_PKG_OPEN, NULL); - } - - info = _alpm_pkg_new(NULL, NULL); - if(info == NULL) { - archive_read_finish(archive); - RET_ERR(PM_ERR_MEMORY, NULL); - } - - if(stat(pkgfile, &st) == 0) { - info->size = st.st_size; - } - - /* TODO there is no reason to make temp files to read - * from a libarchive archive, it can be done by reading - * directly from the archive - * See: archive_read_data_into_buffer - * requires changes 'parse_descfile' as well - * */ - - /* 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 - * as a verfication of integrity and allows us to create the filelist. */ - while((ret = archive_read_next_header(archive, &entry)) == ARCHIVE_OK) { - const char *entry_name = archive_entry_pathname(entry); - - /* NOTE: we used to look for .FILELIST, but it is easier (and safer) for - * us to just generate this on our own. */ - if(strcmp(entry_name, ".PKGINFO") == 0) { - /* extract this file into /tmp. it has info for us */ - descfile = strdup("/tmp/alpm_XXXXXX"); - fd = mkstemp(descfile); - if(archive_read_data_into_fd(archive, fd) != ARCHIVE_OK) { - _alpm_log(PM_LOG_ERROR, _("error extracting package description file to %s\n"), - descfile); - goto pkg_invalid; - } - /* parse the info file */ - if(parse_descfile(descfile, info) == -1) { - _alpm_log(PM_LOG_ERROR, _("could not parse package description file in %s\n"), - pkgfile); - goto pkg_invalid; - } - if(!strlen(info->name)) { - _alpm_log(PM_LOG_ERROR, _("missing package name in %s\n"), pkgfile); - goto pkg_invalid; - } - if(!strlen(info->version)) { - _alpm_log(PM_LOG_ERROR, _("missing package version in %s\n"), pkgfile); - goto pkg_invalid; - } - config = 1; - unlink(descfile); - FREE(descfile); - close(fd); - continue; - } else if(strcmp(entry_name, ".INSTALL") == 0) { - info->scriptlet = 1; - } else if(*entry_name == '.') { - /* for now, ignore all files starting with '.' that haven't - * already been handled (for future possibilities) */ - } else { - /* Keep track of all files for filelist generation */ - info->files = alpm_list_add(info->files, strdup(entry_name)); - } - - if(archive_read_data_skip(archive)) { - _alpm_log(PM_LOG_ERROR, _("error while reading package %s: %s\n"), - pkgfile, archive_error_string(archive)); - pm_errno = PM_ERR_LIBARCHIVE_ERROR; - goto error; - } - - /* if we are not doing a full read, see if we have all we need */ - if(!full && config) { - break; - } - } - - if(ret != ARCHIVE_EOF && ret != ARCHIVE_OK) { /* An error occured */ - _alpm_log(PM_LOG_ERROR, _("error while reading package %s: %s\n"), - pkgfile, archive_error_string(archive)); - pm_errno = PM_ERR_LIBARCHIVE_ERROR; - goto error; - } - - if(!config) { - _alpm_log(PM_LOG_ERROR, _("missing package metadata in %s\n"), pkgfile); - goto pkg_invalid; - } - - archive_read_finish(archive); - - /* internal fields for package struct */ - info->origin = PKG_FROM_FILE; - info->origin_data.file = strdup(pkgfile); - - if(full) { - /* "checking for conflicts" requires a sorted list, so we ensure that here */ - _alpm_log(PM_LOG_DEBUG, "sorting package filelist for %s\n", pkgfile); - info->files = alpm_list_msort(info->files, alpm_list_count(info->files), - _alpm_str_cmp); - info->infolevel = INFRQ_ALL; - } else { - /* get rid of any partial filelist we may have collected, as it is invalid */ - FREELIST(info->files); - info->infolevel = INFRQ_BASE | INFRQ_DESC | INFRQ_DEPENDS; - } - - return(info); - -pkg_invalid: - pm_errno = PM_ERR_PKG_INVALID; - if(descfile) { - unlink(descfile); - FREE(descfile); - } - if(fd != -1) { - close(fd); - } -error: - _alpm_pkg_free(info); - archive_read_finish(archive); - - return(NULL); + pmpkg_t *pkg1 = (pmpkg_t *)p1; + pmpkg_t *pkg2 = (pmpkg_t *)p2; + return(strcmp(alpm_pkg_get_name(pkg1), alpm_pkg_get_name(pkg2))); } /* Test for existence of a package in a alpm_list_t* * of pmpkg_t* */ -pmpkg_t *_alpm_pkg_find(const char *needle, alpm_list_t *haystack) +pmpkg_t *_alpm_pkg_find(alpm_list_t *haystack, const char *needle) { alpm_list_t *lp; |