summaryrefslogtreecommitdiff
path: root/lib/libalpm/package.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libalpm/package.c')
-rw-r--r--lib/libalpm/package.c615
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;