summaryrefslogtreecommitdiff
path: root/lib/libalpm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libalpm')
-rw-r--r--lib/libalpm/add.c43
-rw-r--r--lib/libalpm/alpm.h20
-rw-r--r--lib/libalpm/be_files.c226
-rw-r--r--lib/libalpm/cache.c15
-rw-r--r--lib/libalpm/conflict.c62
-rw-r--r--lib/libalpm/conflict.h17
-rw-r--r--lib/libalpm/db.c16
-rw-r--r--lib/libalpm/delta.c23
-rw-r--r--lib/libalpm/delta.h18
-rw-r--r--lib/libalpm/deps.c141
-rw-r--r--lib/libalpm/deps.h21
-rw-r--r--lib/libalpm/package.c104
-rw-r--r--lib/libalpm/package.h30
-rw-r--r--lib/libalpm/remove.c27
-rw-r--r--lib/libalpm/server.c5
-rw-r--r--lib/libalpm/sync.c516
-rw-r--r--lib/libalpm/sync.h6
-rw-r--r--lib/libalpm/trans.c3
-rw-r--r--lib/libalpm/util.h3
19 files changed, 688 insertions, 608 deletions
diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c
index eddf637e..6c0a1eae 100644
--- a/lib/libalpm/add.c
+++ b/lib/libalpm/add.c
@@ -79,30 +79,22 @@ int _alpm_add_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name)
/* check if an older version of said package is already in transaction
* packages. if so, replace it in the list */
for(i = trans->packages; i; i = i->next) {
- pmpkg_t *pkg = i->data;
- if(strcmp(pkg->name, pkgname) == 0) {
- if(_alpm_versioncmp(pkg->version, pkgver) < 0) {
- pmpkg_t *newpkg;
+ pmpkg_t *transpkg = i->data;
+ if(strcmp(transpkg->name, pkgname) == 0) {
+ if(_alpm_versioncmp(transpkg->version, pkgver) < 0) {
_alpm_log(PM_LOG_WARNING, _("replacing older version %s-%s by %s in target list\n"),
- pkg->name, pkg->version, pkgver);
- if((newpkg = _alpm_pkg_load(name, 1)) == NULL) {
- /* pm_errno is already set by pkg_load() */
- goto error;
- }
+ transpkg->name, transpkg->version, pkgver);
_alpm_pkg_free(i->data);
- i->data = newpkg;
+ i->data = pkg;
} else {
- _alpm_log(PM_LOG_WARNING, _("newer version %s-%s is in the target list -- skipping\n"),
- pkg->name, pkg->version);
+ _alpm_log(PM_LOG_WARNING, _("skipping %s-%s because newer version %s is in the target list\n"),
+ pkgname, pkgver, transpkg->version);
+ _alpm_pkg_free(pkg);
}
return(0);
}
}
- if(trans->flags & PM_TRANS_FLAG_ALLDEPS) {
- pkg->reason = PM_PKG_REASON_DEPEND;
- }
-
/* add the package to the transaction */
trans->packages = alpm_list_add(trans->packages, pkg);
@@ -143,7 +135,8 @@ int _alpm_add_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data)
if(data) {
*data = lp;
} else {
- FREELIST(lp);
+ alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_depmiss_free);
+ alpm_list_free(lp);
}
RET_ERR(PM_ERR_UNSATISFIED_DEPS, -1);
}
@@ -193,7 +186,8 @@ int _alpm_add_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data)
if(data) {
*data = lp;
} else {
- FREELIST(lp);
+ alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_fileconflict_free);
+ alpm_list_free(lp);
}
RET_ERR(PM_ERR_FILE_CONFLICTS, -1);
}
@@ -667,12 +661,8 @@ static int commit_single_pkg(pmpkg_t *newpkg, int pkg_current, int pkg_count,
/* we'll need to save some record for backup checks later */
oldpkg = _alpm_pkg_dup(local);
- /* copy over the install reason (unless alldeps is set) */
- if(trans->flags & PM_TRANS_FLAG_ALLDEPS) {
- newpkg->reason = PM_PKG_REASON_DEPEND;
- } else {
+ /* copy over the install reason */
newpkg->reason = alpm_pkg_get_reason(local);
- }
/* pre_upgrade scriptlet */
if(alpm_pkg_has_scriptlet(newpkg) && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) {
@@ -693,6 +683,13 @@ static int commit_single_pkg(pmpkg_t *newpkg, int pkg_current, int pkg_count,
}
}
+ /* 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(oldpkg) {
/* set up fake remove transaction */
int ret = upgrade_remove(oldpkg, newpkg, trans, db);
diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h
index 4797fcfa..b19e1dd9 100644
--- a/lib/libalpm/alpm.h
+++ b/lib/libalpm/alpm.h
@@ -246,16 +246,9 @@ const alpm_list_t *alpm_grp_get_pkgs(const pmgrp_t *grp);
* Sync
*/
-/* Types */
-typedef enum _pmsynctype_t {
- PM_SYNC_TYPE_REPLACE = 1,
- PM_SYNC_TYPE_UPGRADE,
- PM_SYNC_TYPE_DEPEND
-} pmsynctype_t;
-
-pmsynctype_t alpm_sync_get_type(const pmsyncpkg_t *sync);
pmpkg_t *alpm_sync_get_pkg(const pmsyncpkg_t *sync);
-void *alpm_sync_get_data(const pmsyncpkg_t *sync);
+alpm_list_t *alpm_sync_get_removes(const pmsyncpkg_t *sync);
+pmpkg_t *alpm_sync_newversion(pmpkg_t *pkg, alpm_list_t *dbs_sync);
int alpm_sync_sysupgrade(pmdb_t *db_local,
alpm_list_t *dbs_sync, alpm_list_t **syncpkgs);
@@ -287,7 +280,9 @@ typedef enum _pmtransflag_t {
PM_TRANS_FLAG_NOSCRIPTLET = 0x400,
PM_TRANS_FLAG_NOCONFLICTS = 0x800,
PM_TRANS_FLAG_PRINTURIS = 0x1000,
- PM_TRANS_FLAG_NEEDED = 0x2000
+ PM_TRANS_FLAG_NEEDED = 0x2000,
+ PM_TRANS_FLAG_ALLEXPLICIT = 0x4000,
+ PM_TRANS_FLAG_UNNEEDED = 0x8000
} pmtransflag_t;
/* Transaction Events */
@@ -377,13 +372,16 @@ typedef enum _pmdepmod_t {
PM_DEP_MOD_LT
} pmdepmod_t;
-pmdepend_t *alpm_splitdep(const char *depstring);
int alpm_depcmp(pmpkg_t *pkg, pmdepend_t *dep);
alpm_list_t *alpm_checkdeps(pmdb_t *db, int reversedeps,
alpm_list_t *remove, alpm_list_t *upgrade);
+alpm_list_t *alpm_deptest(pmdb_t *db, alpm_list_t *targets);
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);
+
+alpm_list_t *alpm_checkdbconflicts(pmdb_t *db_local);
const char *alpm_conflict_get_package1(pmconflict_t *conflict);
const char *alpm_conflict_get_package2(pmconflict_t *conflict);
diff --git a/lib/libalpm/be_files.c b/lib/libalpm/be_files.c
index 4cd0985e..d3ec89a4 100644
--- a/lib/libalpm/be_files.c
+++ b/lib/libalpm/be_files.c
@@ -106,7 +106,7 @@ void _alpm_db_rewind(pmdb_t *db)
rewinddir(db->handle);
}
-static int _alpm_db_splitname(const char *target, char *name, char *version)
+static int splitname(const char *target, pmpkg_t *pkg)
{
/* the format of a db entry is as follows:
* package-version-rel/
@@ -115,10 +115,10 @@ static int _alpm_db_splitname(const char *target, char *name, char *version)
*/
char *tmp, *p, *q;
- if(target == NULL) {
+ if(target == NULL || pkg == NULL) {
return(-1);
}
- tmp = strdup(target);
+ STRDUP(tmp, target, RET_ERR(PM_ERR_MEMORY, -1));
p = tmp + strlen(tmp);
/* do the magic parsing- find the beginning of the version string
@@ -130,14 +130,16 @@ static int _alpm_db_splitname(const char *target, char *name, char *version)
}
/* copy into fields and return */
- if(version) {
- strncpy(version, p+1, PKG_VERSION_LEN);
+ if(pkg->version) {
+ FREE(pkg->version);
}
+ STRDUP(pkg->version, p+1, RET_ERR(PM_ERR_MEMORY, -1));
/* insert a terminator at the end of the name (on hyphen)- then copy it */
*p = '\0';
- if(name) {
- strncpy(name, tmp, PKG_NAME_LEN);
+ if(pkg->name) {
+ FREE(pkg->name);
}
+ STRDUP(pkg->name, tmp, RET_ERR(PM_ERR_MEMORY, -1));
free(tmp);
return(0);
@@ -148,7 +150,6 @@ pmpkg_t *_alpm_db_scan(pmdb_t *db, const char *target)
struct dirent *ent = NULL;
struct stat sbuf;
char path[PATH_MAX];
- char name[PKG_FULLNAME_LEN];
char *ptr = NULL;
int found = 0;
pmpkg_t *pkg = NULL;
@@ -168,7 +169,9 @@ pmpkg_t *_alpm_db_scan(pmdb_t *db, const char *target)
/* search for a specific package (by name only) */
rewinddir(db->handle);
while(!found && (ent = readdir(db->handle)) != NULL) {
- if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) {
+ char *name;
+
+ if(strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) {
continue;
}
/* stat the entry, make sure it's a directory */
@@ -176,7 +179,9 @@ pmpkg_t *_alpm_db_scan(pmdb_t *db, const char *target)
if(stat(path, &sbuf) || !S_ISDIR(sbuf.st_mode)) {
continue;
}
- strncpy(name, ent->d_name, PKG_FULLNAME_LEN);
+
+ STRDUP(name, ent->d_name, return(NULL));
+
/* truncate the string at the second-to-last hyphen, */
/* which will give us the package name */
if((ptr = rindex(name, '-'))) {
@@ -185,10 +190,12 @@ pmpkg_t *_alpm_db_scan(pmdb_t *db, const char *target)
if((ptr = rindex(name, '-'))) {
*ptr = '\0';
}
- if(!strcmp(name, target)) {
+ if(strcmp(name, target) == 0) {
found = 1;
}
+ FREE(name);
}
+
if(!found) {
return(NULL);
}
@@ -199,7 +206,7 @@ pmpkg_t *_alpm_db_scan(pmdb_t *db, const char *target)
if(ent == NULL) {
return(NULL);
}
- if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) {
+ if(strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) {
isdir = 0;
continue;
}
@@ -217,7 +224,7 @@ pmpkg_t *_alpm_db_scan(pmdb_t *db, const char *target)
return(NULL);
}
/* split the db entry name */
- if(_alpm_db_splitname(ent->d_name, pkg->name, pkg->version) != 0) {
+ if(splitname(ent->d_name, pkg) != 0) {
_alpm_log(PM_LOG_ERROR, _("invalid name for database entry '%s'\n"),
ent->d_name);
alpm_pkg_free(pkg);
@@ -251,7 +258,7 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)
RET_ERR(PM_ERR_DB_NULL, -1);
}
- if(info == NULL || info->name[0] == 0 || info->version[0] == 0) {
+ if(info == NULL || info->name == NULL || info->version == NULL) {
_alpm_log(PM_LOG_DEBUG, "invalid package entry provided to _alpm_db_read, skipping\n");
return(-1);
}
@@ -296,120 +303,115 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)
break;
}
_alpm_strtrim(line);
- if(!strcmp(line, "%FILENAME%")) {
- if(fgets(info->filename, sizeof(info->filename), fp) == NULL) {
+ if(strcmp(line, "%FILENAME%") == 0) {
+ if(fgets(line, 512, fp) == NULL) {
goto error;
}
- _alpm_strtrim(info->filename);
- } else if(!strcmp(line, "%DESC%")) {
- if(fgets(info->desc, sizeof(info->desc), fp) == NULL) {
+ STRDUP(info->filename, _alpm_strtrim(line), goto error);
+ } else if(strcmp(line, "%DESC%") == 0) {
+ if(fgets(line, 512, fp) == NULL) {
goto error;
}
- _alpm_strtrim(info->desc);
- } else if(!strcmp(line, "%GROUPS%")) {
+ STRDUP(info->desc, _alpm_strtrim(line), goto error);
+ } else if(strcmp(line, "%GROUPS%") == 0) {
while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {
- info->groups = alpm_list_add(info->groups, strdup(line));
+ char *linedup;
+ STRDUP(linedup, _alpm_strtrim(line), goto error);
+ info->groups = alpm_list_add(info->groups, linedup);
}
- } else if(!strcmp(line, "%URL%")) {
- if(fgets(info->url, sizeof(info->url), fp) == NULL) {
+ } else if(strcmp(line, "%URL%") == 0) {
+ if(fgets(line, 512, fp) == NULL) {
goto error;
}
- _alpm_strtrim(info->url);
- } else if(!strcmp(line, "%LICENSE%")) {
+ STRDUP(info->url, _alpm_strtrim(line), goto error);
+ } else if(strcmp(line, "%LICENSE%") == 0) {
while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {
- info->licenses = alpm_list_add(info->licenses, strdup(line));
+ char *linedup;
+ STRDUP(linedup, _alpm_strtrim(line), goto error);
+ info->licenses = alpm_list_add(info->licenses, linedup);
}
- } else if(!strcmp(line, "%ARCH%")) {
- if(fgets(info->arch, sizeof(info->arch), fp) == NULL) {
+ } else if(strcmp(line, "%ARCH%") == 0) {
+ if(fgets(line, 512, fp) == NULL) {
goto error;
}
- _alpm_strtrim(info->arch);
- } else if(!strcmp(line, "%BUILDDATE%")) {
- char tmp[32];
- if(fgets(tmp, sizeof(tmp), fp) == NULL) {
+ STRDUP(info->arch, _alpm_strtrim(line), goto error);
+ } else if(strcmp(line, "%BUILDDATE%") == 0) {
+ if(fgets(line, 512, fp) == NULL) {
goto error;
}
- _alpm_strtrim(tmp);
+ _alpm_strtrim(line);
- char first = tolower(tmp[0]);
+ char first = tolower(line[0]);
if(first > 'a' && first < 'z') {
struct tm tmp_tm = {0}; //initialize to null incase of failure
setlocale(LC_TIME, "C");
- strptime(tmp, "%a %b %e %H:%M:%S %Y", &tmp_tm);
+ strptime(line, "%a %b %e %H:%M:%S %Y", &tmp_tm);
info->builddate = mktime(&tmp_tm);
setlocale(LC_TIME, "");
} else {
- info->builddate = atol(tmp);
+ info->builddate = atol(line);
}
- } else if(!strcmp(line, "%INSTALLDATE%")) {
- char tmp[32];
- if(fgets(tmp, sizeof(tmp), fp) == NULL) {
+ } else if(strcmp(line, "%INSTALLDATE%") == 0) {
+ if(fgets(line, 512, fp) == NULL) {
goto error;
}
- _alpm_strtrim(tmp);
+ _alpm_strtrim(line);
- char first = tolower(tmp[0]);
+ char first = tolower(line[0]);
if(first > 'a' && first < 'z') {
struct tm tmp_tm = {0}; //initialize to null incase of failure
setlocale(LC_TIME, "C");
- strptime(tmp, "%a %b %e %H:%M:%S %Y", &tmp_tm);
+ strptime(line, "%a %b %e %H:%M:%S %Y", &tmp_tm);
info->installdate = mktime(&tmp_tm);
setlocale(LC_TIME, "");
} else {
- info->installdate = atol(tmp);
+ info->installdate = atol(line);
}
- } else if(!strcmp(line, "%PACKAGER%")) {
- if(fgets(info->packager, sizeof(info->packager), fp) == NULL) {
+ } else if(strcmp(line, "%PACKAGER%") == 0) {
+ if(fgets(line, 512, fp) == NULL) {
goto error;
}
- _alpm_strtrim(info->packager);
- } else if(!strcmp(line, "%REASON%")) {
- char tmp[32];
- if(fgets(tmp, sizeof(tmp), fp) == NULL) {
+ STRDUP(info->packager, _alpm_strtrim(line), goto error);
+ } else if(strcmp(line, "%REASON%") == 0) {
+ if(fgets(line, 512, fp) == NULL) {
goto error;
}
- _alpm_strtrim(tmp);
- info->reason = atol(tmp);
- } else if(!strcmp(line, "%SIZE%") || !strcmp(line, "%CSIZE%")) {
+ info->reason = atol(_alpm_strtrim(line));
+ } else if(strcmp(line, "%SIZE%") == 0 || strcmp(line, "%CSIZE%") == 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.
*/
- char tmp[32];
- if(fgets(tmp, sizeof(tmp), fp) == NULL) {
+ if(fgets(line, 512, fp) == NULL) {
goto error;
}
- _alpm_strtrim(tmp);
- info->size = atol(tmp);
+ info->size = atol(_alpm_strtrim(line));
/* also store this value to isize if isize is unset */
if(info->isize == 0) {
- info->isize = atol(tmp);
+ info->isize = info->size;
}
- } else if(!strcmp(line, "%ISIZE%")) {
+ } else if(strcmp(line, "%ISIZE%") == 0) {
/* ISIZE (installed size) tag only appears in sync repositories,
* not the local one. */
- char tmp[32];
- if(fgets(tmp, sizeof(tmp), fp) == NULL) {
+ if(fgets(line, 512, fp) == NULL) {
goto error;
}
- _alpm_strtrim(tmp);
- info->isize = atol(tmp);
- } else if(!strcmp(line, "%MD5SUM%")) {
+ info->isize = atol(_alpm_strtrim(line));
+ } else if(strcmp(line, "%MD5SUM%") == 0) {
/* MD5SUM tag only appears in sync repositories,
* not the local one. */
- if(fgets(info->md5sum, sizeof(info->md5sum), fp) == NULL) {
+ if(fgets(line, 512, fp) == NULL) {
goto error;
}
- } else if(!strcmp(line, "%REPLACES%")) {
- /* the REPLACES tag is special -- it only appears in sync repositories,
- * not the local one. */
+ STRDUP(info->md5sum, _alpm_strtrim(line), goto error);
+ } else if(strcmp(line, "%REPLACES%") == 0) {
while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {
- info->replaces = alpm_list_add(info->replaces, strdup(line));
+ char *linedup;
+ STRDUP(linedup, _alpm_strtrim(line), goto error);
+ info->replaces = alpm_list_add(info->replaces, linedup);
}
- } else if(!strcmp(line, "%FORCE%")) {
- /* FORCE tag only appears in sync repositories,
- * not the local one. */
+ } else if(strcmp(line, "%FORCE%") == 0) {
info->force = 1;
}
}
@@ -426,13 +428,17 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)
}
while(fgets(line, 256, fp)) {
_alpm_strtrim(line);
- if(!strcmp(line, "%FILES%")) {
+ if(strcmp(line, "%FILES%") == 0) {
while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {
- info->files = alpm_list_add(info->files, strdup(line));
+ char *linedup;
+ STRDUP(linedup, _alpm_strtrim(line), goto error);
+ info->files = alpm_list_add(info->files, linedup);
}
- } else if(!strcmp(line, "%BACKUP%")) {
+ } else if(strcmp(line, "%BACKUP%") == 0) {
while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {
- info->backup = alpm_list_add(info->backup, strdup(line));
+ char *linedup;
+ STRDUP(linedup, _alpm_strtrim(line), goto error);
+ info->backup = alpm_list_add(info->backup, linedup);
}
}
}
@@ -450,37 +456,30 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)
while(!feof(fp)) {
fgets(line, 255, fp);
_alpm_strtrim(line);
- if(!strcmp(line, "%DEPENDS%")) {
+ if(strcmp(line, "%DEPENDS%") == 0) {
while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {
- pmdepend_t *dep = alpm_splitdep(line);
+ pmdepend_t *dep = _alpm_splitdep(_alpm_strtrim(line));
info->depends = alpm_list_add(info->depends, dep);
}
- } else if(!strcmp(line, "%OPTDEPENDS%")) {
+ } else if(strcmp(line, "%OPTDEPENDS%") == 0) {
while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {
- info->optdepends = alpm_list_add(info->optdepends, strdup(line));
+ char *linedup;
+ STRDUP(linedup, _alpm_strtrim(line), goto error);
+ info->optdepends = alpm_list_add(info->optdepends, linedup);
}
- } else if(!strcmp(line, "%CONFLICTS%")) {
+ } else if(strcmp(line, "%CONFLICTS%") == 0) {
while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {
- info->conflicts = alpm_list_add(info->conflicts, strdup(line));
+ char *linedup;
+ STRDUP(linedup, _alpm_strtrim(line), goto error);
+ info->conflicts = alpm_list_add(info->conflicts, linedup);
}
- } else if(!strcmp(line, "%PROVIDES%")) {
+ } else if(strcmp(line, "%PROVIDES%") == 0) {
while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {
- info->provides = alpm_list_add(info->provides, strdup(line));
+ char *linedup;
+ STRDUP(linedup, _alpm_strtrim(line), goto error);
+ info->provides = alpm_list_add(info->provides, linedup);
}
}
- /* TODO: we were going to move these things here, but it should wait.
- * A better change would be to figure out how to restructure the DB. */
- /* else if(!strcmp(line, "%REPLACES%")) {
- * the REPLACES tag is special -- it only appears in sync repositories,
- * not the local one. *
- while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {
- info->replaces = alpm_list_add(info->replaces, strdup(line));
- }
- } else if(!strcmp(line, "%FORCE%")) {
- * FORCE tag only appears in sync repositories,
- * not the local one. *
- info->force = 1;
- } */
}
fclose(fp);
fp = NULL;
@@ -488,12 +487,13 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)
/* DELTAS */
if(inforeq & INFRQ_DELTAS) {
- snprintf(path, PATH_MAX, "%s/%s-%s/deltas", db->path, info->name, info->version);
+ snprintf(path, PATH_MAX, "%s/%s-%s/deltas", db->path,
+ info->name, info->version);
if((fp = fopen(path, "r"))) {
while(!feof(fp)) {
fgets(line, 255, fp);
_alpm_strtrim(line);
- if(!strcmp(line, "%DELTAS%")) {
+ if(strcmp(line, "%DELTAS%") == 0) {
while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {
info->deltas = alpm_list_add(info->deltas, _alpm_delta_parse(line));
}
@@ -561,7 +561,7 @@ int _alpm_db_write(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)
}
fprintf(fp, "%%NAME%%\n%s\n\n"
"%%VERSION%%\n%s\n\n", info->name, info->version);
- if(info->desc[0]) {
+ if(info->desc) {
fprintf(fp, "%%DESC%%\n"
"%s\n\n", info->desc);
}
@@ -573,7 +573,7 @@ int _alpm_db_write(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)
fprintf(fp, "\n");
}
if(local) {
- if(info->url[0]) {
+ if(info->url) {
fprintf(fp, "%%URL%%\n"
"%s\n\n", info->url);
}
@@ -584,7 +584,7 @@ int _alpm_db_write(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)
}
fprintf(fp, "\n");
}
- if(info->arch[0]) {
+ if(info->arch) {
fprintf(fp, "%%ARCH%%\n"
"%s\n\n", info->arch);
}
@@ -596,7 +596,7 @@ int _alpm_db_write(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)
fprintf(fp, "%%INSTALLDATE%%\n"
"%ju\n\n", (uintmax_t)info->installdate);
}
- if(info->packager[0]) {
+ if(info->packager) {
fprintf(fp, "%%PACKAGER%%\n"
"%s\n\n", info->packager);
}
@@ -695,18 +695,16 @@ int _alpm_db_write(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)
}
fprintf(fp, "\n");
}
- if(!local) {
- if(info->replaces) {
- fputs("%REPLACES%\n", fp);
- for(lp = info->replaces; lp; lp = lp->next) {
- fprintf(fp, "%s\n", (char *)lp->data);
- }
- fprintf(fp, "\n");
- }
- if(info->force) {
- fprintf(fp, "%%FORCE%%\n"
- "\n");
+ if(info->replaces) {
+ fputs("%REPLACES%\n", fp);
+ for(lp = info->replaces; lp; lp = lp->next) {
+ fprintf(fp, "%s\n", (char *)lp->data);
}
+ fprintf(fp, "\n");
+ }
+ if(info->force) {
+ /* note the extra newline character, which is necessary! */
+ fprintf(fp, "%%FORCE%%\n\n");
}
fclose(fp);
fp = NULL;
diff --git a/lib/libalpm/cache.c b/lib/libalpm/cache.c
index 0ad923a5..09fa74c2 100644
--- a/lib/libalpm/cache.c
+++ b/lib/libalpm/cache.c
@@ -81,10 +81,7 @@ void _alpm_db_free_pkgcache(pmdb_t *db)
_alpm_log(PM_LOG_DEBUG, "freeing package cache for repository '%s'\n",
db->treename);
- alpm_list_t *tmp;
- for(tmp = db->pkgcache; tmp; tmp = alpm_list_next(tmp)) {
- _alpm_pkg_free(tmp->data);
- }
+ alpm_list_free_inner(db->pkgcache, (alpm_list_fn_free)_alpm_pkg_free);
alpm_list_free(db->pkgcache);
db->pkgcache = NULL;
@@ -115,21 +112,15 @@ alpm_list_t *_alpm_db_get_pkgcache(pmdb_t *db)
int _alpm_db_add_pkgincache(pmdb_t *db, pmpkg_t *pkg)
{
- pmpkg_t *newpkg;
-
ALPM_LOG_FUNC;
if(db == NULL || pkg == NULL) {
return(-1);
}
- newpkg = _alpm_pkg_dup(pkg);
- if(newpkg == NULL) {
- return(-1);
- }
_alpm_log(PM_LOG_DEBUG, "adding entry '%s' in '%s' cache\n",
- alpm_pkg_get_name(newpkg), db->treename);
- db->pkgcache = alpm_list_add_sorted(db->pkgcache, newpkg, _alpm_pkg_cmp);
+ alpm_pkg_get_name(pkg), db->treename);
+ db->pkgcache = alpm_list_add_sorted(db->pkgcache, pkg, _alpm_pkg_cmp);
_alpm_db_free_grpcache(db);
diff --git a/lib/libalpm/conflict.c b/lib/libalpm/conflict.c
index 3442902c..19352d11 100644
--- a/lib/libalpm/conflict.c
+++ b/lib/libalpm/conflict.c
@@ -49,12 +49,30 @@ pmconflict_t *_alpm_conflict_new(const char *package1, const char *package2)
MALLOC(conflict, sizeof(pmconflict_t), RET_ERR(PM_ERR_MEMORY, NULL));
- strncpy(conflict->package1, package1, PKG_NAME_LEN);
- strncpy(conflict->package2, package2, PKG_NAME_LEN);
+ STRDUP(conflict->package1, package1, RET_ERR(PM_ERR_MEMORY, NULL));
+ STRDUP(conflict->package2, package2, RET_ERR(PM_ERR_MEMORY, NULL));
return(conflict);
}
+void _alpm_conflict_free(pmconflict_t *conflict)
+{
+ FREE(conflict->package2);
+ FREE(conflict->package1);
+ FREE(conflict);
+}
+
+pmconflict_t *_alpm_conflict_dup(const pmconflict_t *conflict)
+{
+ pmconflict_t *newconflict;
+ CALLOC(newconflict, 1, sizeof(pmconflict_t), RET_ERR(PM_ERR_MEMORY, NULL));
+
+ STRDUP(newconflict->package1, conflict->package1, RET_ERR(PM_ERR_MEMORY, NULL));
+ STRDUP(newconflict->package2, conflict->package2, RET_ERR(PM_ERR_MEMORY, NULL));
+
+ return(newconflict);
+}
+
int _alpm_conflict_isin(pmconflict_t *needle, alpm_list_t *haystack)
{
alpm_list_t *i;
@@ -86,7 +104,7 @@ static int does_conflict(pmpkg_t *pkg1, const char *conflict, pmpkg_t *pkg2)
{
const char *pkg1name = alpm_pkg_get_name(pkg1);
const char *pkg2name = alpm_pkg_get_name(pkg2);
- pmdepend_t *conf = alpm_splitdep(conflict);
+ pmdepend_t *conf = _alpm_splitdep(conflict);
int match = 0;
match = alpm_depcmp(pkg2, conf);
@@ -94,7 +112,7 @@ static int does_conflict(pmpkg_t *pkg1, const char *conflict, pmpkg_t *pkg2)
_alpm_log(PM_LOG_DEBUG, "package %s conflicts with %s (by %s)\n",
pkg1name, pkg2name, conflict);
}
- FREE(conf);
+ _alpm_dep_free(conf);
return(match);
}
@@ -110,7 +128,7 @@ static void add_conflict(alpm_list_t **baddeps, const char *pkg1,
if(conflict && !_alpm_conflict_isin(conflict, *baddeps)) {
*baddeps = alpm_list_add(*baddeps, conflict);
} else {
- FREE(conflict);
+ _alpm_conflict_free(conflict);
}
}
@@ -200,9 +218,13 @@ alpm_list_t *_alpm_outerconflicts(pmdb_t *db, alpm_list_t *packages)
return(baddeps);
}
-/* Check for transaction conflicts */
-alpm_list_t *_alpm_checkconflicts(pmdb_t *db, alpm_list_t *packages) {
- return(alpm_list_join(_alpm_innerconflicts(packages), _alpm_outerconflicts(db, packages)));
+/** Check the package conflicts in a database
+ *
+ * @param db_local the database to check
+ * @return an alpm_list_t of pmconflict_t
+ */
+alpm_list_t SYMEXPORT *alpm_checkdbconflicts(pmdb_t *db_local) {
+ return(_alpm_innerconflicts(_alpm_db_get_pkgcache(db_local)));
}
/* Returns a alpm_list_t* of file conflicts.
@@ -299,15 +321,15 @@ static alpm_list_t *add_fileconflict(alpm_list_t *conflicts,
const char* name1, const char* name2)
{
pmfileconflict_t *conflict;
- MALLOC(conflict, sizeof(pmfileconflict_t), return(conflicts));
+ MALLOC(conflict, sizeof(pmfileconflict_t), RET_ERR(PM_ERR_MEMORY, NULL));
conflict->type = type;
- strncpy(conflict->target, name1, PKG_NAME_LEN);
- strncpy(conflict->file, filestr, CONFLICT_FILE_LEN);
+ STRDUP(conflict->target, name1, RET_ERR(PM_ERR_MEMORY, NULL));
+ STRDUP(conflict->file, filestr, RET_ERR(PM_ERR_MEMORY, NULL));
if(name2) {
- strncpy(conflict->ctarget, name2, PKG_NAME_LEN);
+ STRDUP(conflict->ctarget, name2, RET_ERR(PM_ERR_MEMORY, NULL));
} else {
- conflict->ctarget[0] = '\0';
+ conflict->ctarget = "";
}
conflicts = alpm_list_add(conflicts, conflict);
@@ -317,6 +339,16 @@ static alpm_list_t *add_fileconflict(alpm_list_t *conflicts,
return(conflicts);
}
+void _alpm_fileconflict_free(pmfileconflict_t *conflict)
+{
+ if(strlen(conflict->ctarget) > 0) {
+ FREE(conflict->ctarget);
+ }
+ FREE(conflict->file);;
+ FREE(conflict->target);
+ FREE(conflict);
+}
+
/* 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 */
@@ -351,13 +383,13 @@ alpm_list_t *_alpm_db_find_fileconflicts(pmdb_t *db, pmtrans_t *trans, char *roo
PROGRESS(trans, PM_TRANS_PROGRESS_CONFLICTS_START, "", (percent * 100),
numtargs, current);
/* CHECK 1: check every target against every target */
+ _alpm_log(PM_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;
}
- _alpm_log(PM_LOG_DEBUG, "searching for file conflicts: %s and %s\n",
- alpm_pkg_get_name(p1), alpm_pkg_get_name(p2));
tmpfiles = chk_fileconflicts(alpm_pkg_get_files(p1), alpm_pkg_get_files(p2));
if(tmpfiles) {
diff --git a/lib/libalpm/conflict.h b/lib/libalpm/conflict.h
index a846aace..71ed579d 100644
--- a/lib/libalpm/conflict.h
+++ b/lib/libalpm/conflict.h
@@ -23,27 +23,28 @@
#include "db.h"
#include "package.h"
-#define CONFLICT_FILE_LEN 512
-
struct __pmconflict_t {
- char package1[PKG_NAME_LEN];
- char package2[PKG_NAME_LEN];
+ char *package1;
+ char *package2;
};
struct __pmfileconflict_t {
- char target[PKG_NAME_LEN];
+ char *target;
pmfileconflicttype_t type;
- char file[CONFLICT_FILE_LEN];
- char ctarget[PKG_NAME_LEN];
+ char *file;
+ char *ctarget;
};
pmconflict_t *_alpm_conflict_new(const char *package1, const char *package2);
+pmconflict_t *_alpm_conflict_dup(const pmconflict_t *conflict);
+void _alpm_conflict_free(pmconflict_t *conflict);
int _alpm_conflict_isin(pmconflict_t *needle, alpm_list_t *haystack);
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_checkconflicts(pmdb_t *db, alpm_list_t *packages);
alpm_list_t *_alpm_db_find_fileconflicts(pmdb_t *db, pmtrans_t *trans, char *root);
+void _alpm_fileconflict_free(pmfileconflict_t *conflict);
+
#endif /* _ALPM_CONFLICT_H */
/* vim: set ts=2 sw=2 noet: */
diff --git a/lib/libalpm/db.c b/lib/libalpm/db.c
index 1485c34a..3bddea65 100644
--- a/lib/libalpm/db.c
+++ b/lib/libalpm/db.c
@@ -500,18 +500,16 @@ alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles)
for(j = _alpm_db_get_pkgcache(db); j; j = j->next) {
pmpkg_t *pkg = j->data;
const char *matched = NULL;
+ const char *name = alpm_pkg_get_name(pkg);
+ const char *desc = alpm_pkg_get_desc(pkg);
- /* check name */
- if (regexec(&reg, alpm_pkg_get_name(pkg), 0, 0, 0) == 0) {
- matched = alpm_pkg_get_name(pkg);
- }
- /* check plain text name */
- else if (strstr(alpm_pkg_get_name(pkg), targ)) {
- matched = alpm_pkg_get_name(pkg);
+ /* check name as regex AND as plain text */
+ if(name && (regexec(&reg, name, 0, 0, 0) == 0 || strstr(name, targ))) {
+ matched = name;
}
/* check desc */
- else if (regexec(&reg, alpm_pkg_get_desc(pkg), 0, 0, 0) == 0) {
- matched = alpm_pkg_get_desc(pkg);
+ else if (desc && regexec(&reg, desc, 0, 0, 0) == 0) {
+ matched = desc;
}
/* check provides */
/* TODO: should we be doing this, and should we print something
diff --git a/lib/libalpm/delta.c b/lib/libalpm/delta.c
index 3d33c595..9eb6e82f 100644
--- a/lib/libalpm/delta.c
+++ b/lib/libalpm/delta.c
@@ -1,7 +1,7 @@
/*
* delta.c
*
- * Copyright (c) 2007 by Judd Vinet <jvinet@zeroflux.org>
+ * Copyright (c) 2007-2008 by Judd Vinet <jvinet@zeroflux.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
@@ -99,7 +99,7 @@ unsigned long _alpm_delta_path_size(alpm_list_t *deltas)
alpm_list_t *dlts = deltas;
while(dlts) {
- pmdelta_t *d = (pmdelta_t *)alpm_list_getdata(dlts);
+ pmdelta_t *d = alpm_list_getdata(dlts);
sum += d->size;
dlts = alpm_list_next(dlts);
@@ -121,7 +121,7 @@ unsigned long _alpm_delta_path_size_uncached(alpm_list_t *deltas)
alpm_list_t *dlts = deltas;
while(dlts) {
- pmdelta_t *d = (pmdelta_t *)alpm_list_getdata(dlts);
+ pmdelta_t *d = alpm_list_getdata(dlts);
char *fname = _alpm_filecache_find(d->filename);
if(!fname) {
@@ -241,12 +241,12 @@ pmdelta_t *_alpm_delta_parse(char *line)
tmp2 = tmp;
tmp = strchr(tmp, ' ');
*(tmp++) = '\0';
- strncpy(delta->from, tmp2, DLT_VERSION_LEN);
+ STRDUP(delta->from, tmp2, RET_ERR(PM_ERR_MEMORY, NULL));
tmp2 = tmp;
tmp = strchr(tmp, ' ');
*(tmp++) = '\0';
- strncpy(delta->to, tmp2, DLT_VERSION_LEN);
+ STRDUP(delta->to, tmp2, RET_ERR(PM_ERR_MEMORY, NULL));
tmp2 = tmp;
tmp = strchr(tmp, ' ');
@@ -256,11 +256,20 @@ pmdelta_t *_alpm_delta_parse(char *line)
tmp2 = tmp;
tmp = strchr(tmp, ' ');
*(tmp++) = '\0';
- strncpy(delta->filename, tmp2, DLT_FILENAME_LEN);
+ STRDUP(delta->filename, tmp2, RET_ERR(PM_ERR_MEMORY, NULL));
- strncpy(delta->md5sum, tmp, DLT_MD5SUM_LEN);
+ STRDUP(delta->md5sum, tmp, RET_ERR(PM_ERR_MEMORY, NULL));
return(delta);
}
+void _alpm_delta_free(pmdelta_t *delta)
+{
+ FREE(delta->from);
+ FREE(delta->to);
+ FREE(delta->filename);
+ FREE(delta->md5sum);
+ FREE(delta);
+}
+
/* vim: set ts=2 sw=2 noet: */
diff --git a/lib/libalpm/delta.h b/lib/libalpm/delta.h
index 3065d4d1..007e5d45 100644
--- a/lib/libalpm/delta.h
+++ b/lib/libalpm/delta.h
@@ -1,7 +1,7 @@
/*
* delta.h
*
- * Copyright (c) 2007 by Judd Vinet <jvinet@zeroflux.org>
+ * Copyright (c) 2007-2008 by Judd Vinet <jvinet@zeroflux.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
@@ -21,22 +21,20 @@
#include "alpm.h"
-#define DLT_FILENAME_LEN 512
-#define DLT_VERSION_LEN 64
-#define DLT_MD5SUM_LEN 33
-
struct __pmdelta_t {
- char from[DLT_VERSION_LEN];
- char to[DLT_VERSION_LEN];
+ char *from;
+ char *to;
unsigned long size;
- char filename[DLT_FILENAME_LEN];
- char md5sum[DLT_MD5SUM_LEN];
+ char *filename;
+ char *md5sum;
};
unsigned long _alpm_delta_path_size(alpm_list_t *deltas);
unsigned long _alpm_delta_path_size_uncached(alpm_list_t *deltas);
pmdelta_t *_alpm_delta_parse(char *line);
-alpm_list_t *_alpm_shortest_delta_path(alpm_list_t *deltas, const char *from, const char *to);
+void _alpm_delta_free(pmdelta_t *delta);
+alpm_list_t *_alpm_shortest_delta_path(alpm_list_t *deltas,
+ const char *from, const char *to);
#endif /* _ALPM_DELTA_H */
diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c
index ec52083e..c08c59e9 100644
--- a/lib/libalpm/deps.c
+++ b/lib/libalpm/deps.c
@@ -36,10 +36,19 @@
#include "cache.h"
#include "handle.h"
+void _alpm_dep_free(pmdepend_t *dep)
+{
+ FREE(dep->name);
+ FREE(dep->version);
+ FREE(dep);
+}
+
static pmgraph_t *_alpm_graph_new(void)
{
pmgraph_t *graph = NULL;
+ ALPM_LOG_FUNC;
+
MALLOC(graph, sizeof(pmgraph_t), RET_ERR(PM_ERR_MEMORY, NULL));
if(graph) {
@@ -59,8 +68,8 @@ static void _alpm_graph_free(void *data)
free(graph);
}
-pmdepmissing_t *_alpm_depmiss_new(const char *target, pmdepmod_t depmod,
- const char *depname, const char *depversion)
+pmdepmissing_t *_alpm_depmiss_new(const char *target, pmdepend_t *dep,
+ const char *causingpkg)
{
pmdepmissing_t *miss;
@@ -68,18 +77,21 @@ pmdepmissing_t *_alpm_depmiss_new(const char *target, pmdepmod_t depmod,
MALLOC(miss, sizeof(pmdepmissing_t), RET_ERR(PM_ERR_MEMORY, NULL));
- strncpy(miss->target, target, PKG_NAME_LEN);
- miss->depend.mod = depmod;
- strncpy(miss->depend.name, depname, PKG_NAME_LEN);
- if(depversion) {
- strncpy(miss->depend.version, depversion, PKG_VERSION_LEN);
- } else {
- miss->depend.version[0] = 0;
- }
+ STRDUP(miss->target, target, RET_ERR(PM_ERR_MEMORY, NULL));
+ miss->depend = _alpm_dep_dup(dep);
+ STRDUP(miss->causingpkg, causingpkg, RET_ERR(PM_ERR_MEMORY, NULL));
return(miss);
}
+void _alpm_depmiss_free(pmdepmissing_t *miss)
+{
+ _alpm_dep_free(miss->depend);
+ FREE(miss->target);
+ FREE(miss->causingpkg);
+ FREE(miss);
+}
+
/* Convert a list of pmpkg_t * to a graph structure,
* with a edge for each dependency.
* Returns a list of vertices (one vertex = one package)
@@ -217,6 +229,31 @@ static int satisfycmp(const void *pkg, const void *depend)
/** Checks dependencies and returns missing ones in a list.
* Dependencies can include versions with depmod operators.
* @param db pointer to the local package database
+ * @param targets an alpm_list_t* of dependencies strings to satisfy
+ * @return an alpm_list_t* of missing dependencies strings
+ */
+alpm_list_t SYMEXPORT *alpm_deptest(pmdb_t *db, alpm_list_t *targets)
+{
+ alpm_list_t *i, *ret = NULL;
+
+ for(i = targets; i; i = alpm_list_next(i)) {
+ pmdepend_t *dep;
+ char *target;
+
+ target = alpm_list_getdata(i);
+ dep = _alpm_splitdep(target);
+
+ if(!alpm_list_find(_alpm_db_get_pkgcache(db), dep, satisfycmp)) {
+ ret = alpm_list_add(ret, target);
+ }
+ _alpm_dep_free(dep);
+ }
+ return(ret);
+}
+
+/** Checks dependencies and returns missing ones in a list.
+ * Dependencies can include versions with depmod operators.
+ * @param db pointer to the local package database
* @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)
@@ -264,8 +301,7 @@ alpm_list_t SYMEXPORT *alpm_checkdeps(pmdb_t *db, int reversedeps,
_alpm_log(PM_LOG_DEBUG, "checkdeps: missing dependency '%s' for package '%s'\n",
missdepstring, alpm_pkg_get_name(tp));
free(missdepstring);
- miss = _alpm_depmiss_new(alpm_pkg_get_name(tp), depend->mod,
- depend->name, depend->version);
+ miss = _alpm_depmiss_new(alpm_pkg_get_name(tp), depend, "");
baddeps = alpm_list_add(baddeps, miss);
}
}
@@ -278,18 +314,18 @@ alpm_list_t SYMEXPORT *alpm_checkdeps(pmdb_t *db, int reversedeps,
pmpkg_t *lp = i->data;
for(j = alpm_pkg_get_depends(lp); j; j = j->next) {
pmdepend_t *depend = j->data;
+ pmpkg_t *causingpkg = alpm_list_find(modified, depend, satisfycmp);
/* 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(alpm_list_find(modified, depend, satisfycmp) &&
+ if(causingpkg &&
!alpm_list_find(upgrade, depend, satisfycmp) &&
!alpm_list_find(dblist, depend, satisfycmp)) {
char *missdepstring = alpm_dep_get_string(depend);
_alpm_log(PM_LOG_DEBUG, "checkdeps: transaction would break '%s' dependency of '%s'\n",
missdepstring, alpm_pkg_get_name(lp));
free(missdepstring);
- miss = _alpm_depmiss_new(lp->name, depend->mod,
- depend->name, depend->version);
+ miss = _alpm_depmiss_new(lp->name, depend, alpm_pkg_get_name(causingpkg));
baddeps = alpm_list_add(baddeps, miss);
}
}
@@ -357,7 +393,7 @@ int SYMEXPORT alpm_depcmp(pmpkg_t *pkg, pmdepend_t *dep)
return(satisfy);
}
-pmdepend_t SYMEXPORT *alpm_splitdep(const char *depstring)
+pmdepend_t *_alpm_splitdep(const char *depstring)
{
pmdepend_t *depend;
char *ptr = NULL;
@@ -366,9 +402,9 @@ pmdepend_t SYMEXPORT *alpm_splitdep(const char *depstring)
if(depstring == NULL) {
return(NULL);
}
- newstr = strdup(depstring);
+ STRDUP(newstr, depstring, RET_ERR(PM_ERR_MEMORY, NULL));
- MALLOC(depend, sizeof(pmdepend_t), return(NULL));
+ CALLOC(depend, 1, sizeof(pmdepend_t), RET_ERR(PM_ERR_MEMORY, 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. */
@@ -392,25 +428,36 @@ pmdepend_t SYMEXPORT *alpm_splitdep(const char *depstring)
depend->mod = PM_DEP_MOD_GT;
*ptr = '\0';
ptr += 1;
-
} else {
- /* no version specified - copy in the name and return it */
+ /* no version specified - copy the name and return it */
depend->mod = PM_DEP_MOD_ANY;
- strncpy(depend->name, newstr, PKG_NAME_LEN);
- depend->version[0] = '\0';
+ STRDUP(depend->name, newstr, RET_ERR(PM_ERR_MEMORY, NULL));
+ depend->version = NULL;
free(newstr);
return(depend);
}
/* if we get here, we have a version comparator, copy the right parts
* to the right places */
- strncpy(depend->name, newstr, PKG_NAME_LEN);
- strncpy(depend->version, ptr, PKG_VERSION_LEN);
+ STRDUP(depend->name, newstr, RET_ERR(PM_ERR_MEMORY, NULL));
+ STRDUP(depend->version, ptr, RET_ERR(PM_ERR_MEMORY, NULL));
free(newstr);
return(depend);
}
+pmdepend_t *_alpm_dep_dup(const pmdepend_t *dep)
+{
+ pmdepend_t *newdep;
+ CALLOC(newdep, 1, sizeof(pmdepend_t), RET_ERR(PM_ERR_MEMORY, NULL));
+
+ STRDUP(newdep->name, dep->name, RET_ERR(PM_ERR_MEMORY, NULL));
+ STRDUP(newdep->version, dep->version, RET_ERR(PM_ERR_MEMORY, NULL));
+ newdep->mod = dep->mod;
+
+ 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
@@ -524,7 +571,7 @@ int _alpm_resolvedeps(pmdb_t *local, alpm_list_t *dbs_sync, pmpkg_t *syncpkg,
for(i = deps; i; i = i->next) {
int found = 0;
pmdepmissing_t *miss = i->data;
- pmdepend_t *missdep = &(miss->depend);
+ pmdepend_t *missdep = alpm_miss_get_dep(miss);
pmpkg_t *sync = NULL;
/* check if one of the packages in *list already satisfies this dependency */
@@ -612,7 +659,8 @@ int _alpm_resolvedeps(pmdb_t *local, alpm_list_t *dbs_sync, pmpkg_t *syncpkg,
_alpm_log(PM_LOG_DEBUG, "finished resolving dependencies\n");
- FREELIST(deps);
+ alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_depmiss_free);
+ alpm_list_free(deps);
return(0);
@@ -628,7 +676,17 @@ const char SYMEXPORT *alpm_miss_get_target(const pmdepmissing_t *miss)
/* Sanity checks */
ASSERT(miss != NULL, return(NULL));
- return miss->target;
+ 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)
@@ -638,7 +696,7 @@ pmdepend_t SYMEXPORT *alpm_miss_get_dep(pmdepmissing_t *miss)
/* Sanity checks */
ASSERT(miss != NULL, return(NULL));
- return &(miss->depend);
+ return(miss->depend);
}
pmdepmod_t SYMEXPORT alpm_dep_get_mod(const pmdepend_t *dep)
@@ -648,7 +706,7 @@ pmdepmod_t SYMEXPORT alpm_dep_get_mod(const pmdepend_t *dep)
/* Sanity checks */
ASSERT(dep != NULL, return(-1));
- return dep->mod;
+ return(dep->mod);
}
const char SYMEXPORT *alpm_dep_get_name(const pmdepend_t *dep)
@@ -658,7 +716,7 @@ const char SYMEXPORT *alpm_dep_get_name(const pmdepend_t *dep)
/* Sanity checks */
ASSERT(dep != NULL, return(NULL));
- return dep->name;
+ return(dep->name);
}
const char SYMEXPORT *alpm_dep_get_version(const pmdepend_t *dep)
@@ -668,7 +726,7 @@ const char SYMEXPORT *alpm_dep_get_version(const pmdepend_t *dep)
/* Sanity checks */
ASSERT(dep != NULL, return(NULL));
- return dep->version;
+ return(dep->version);
}
/** Reverse of splitdep; make a dep string from a pmdepend_t struct.
@@ -678,7 +736,7 @@ const char SYMEXPORT *alpm_dep_get_version(const pmdepend_t *dep)
*/
char SYMEXPORT *alpm_dep_get_string(const pmdepend_t *dep)
{
- char *opr, *str = NULL;
+ char *name, *opr, *ver, *str = NULL;
size_t len;
ALPM_LOG_FUNC;
@@ -686,6 +744,12 @@ char SYMEXPORT *alpm_dep_get_string(const pmdepend_t *dep)
/* Sanity checks */
ASSERT(dep != NULL, return(NULL));
+ if(dep->name) {
+ name = dep->name;
+ } else {
+ name = "";
+ }
+
switch(dep->mod) {
case PM_DEP_MOD_ANY:
opr = "";
@@ -710,11 +774,18 @@ char SYMEXPORT *alpm_dep_get_string(const pmdepend_t *dep)
break;
}
+ if(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 */
- len = strlen(dep->name) + strlen(opr) + strlen(dep->version) + 1;
+ * and ver will be empty when PM_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));
- snprintf(str, len, "%s%s%s", dep->name, opr, dep->version);
+ snprintf(str, len, "%s%s%s", name, opr, ver);
return(str);
}
diff --git a/lib/libalpm/deps.h b/lib/libalpm/deps.h
index 75cbb5bc..439a92a2 100644
--- a/lib/libalpm/deps.h
+++ b/lib/libalpm/deps.h
@@ -29,14 +29,15 @@
/* Dependency */
struct __pmdepend_t {
pmdepmod_t mod;
- char name[PKG_NAME_LEN];
- char version[PKG_VERSION_LEN];
+ char *name;
+ char *version;
};
/* Missing dependency */
struct __pmdepmissing_t {
- char target[PKG_NAME_LEN];
- pmdepend_t depend;
+ char *target;
+ pmdepend_t *depend;
+ char *causingpkg; /* this is used in case of remove dependency error only */
};
/* Graphs */
@@ -48,12 +49,18 @@ struct __pmgraph_t {
alpm_list_t *childptr; /* points to a child in children list */
};
-pmdepmissing_t *_alpm_depmiss_new(const char *target, pmdepmod_t depmod,
- const char *depname, const char *depversion);
+
+void _alpm_dep_free(pmdepend_t *dep);
+pmdepend_t *_alpm_dep_dup(const pmdepend_t *dep);
+pmdepmissing_t *_alpm_depmiss_new(const char *target, pmdepend_t *dep,
+ const char *causinpkg);
+void _alpm_depmiss_free(pmdepmissing_t *miss);
alpm_list_t *_alpm_sortbydeps(alpm_list_t *targets, pmtranstype_t mode);
void _alpm_recursedeps(pmdb_t *db, alpm_list_t *targs, int include_explicit);
int _alpm_resolvedeps(pmdb_t *local, alpm_list_t *dbs_sync, pmpkg_t *syncpkg,
- alpm_list_t **list, alpm_list_t *remove, pmtrans_t *trans, alpm_list_t **data);
+ alpm_list_t **list, alpm_list_t *remove, pmtrans_t *trans, alpm_list_t
+ **data);
+pmdepend_t *_alpm_splitdep(const char *depstring);
#endif /* _ALPM_DEPS_H */
diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c
index 363cf313..98417155 100644
--- a/lib/libalpm/package.c
+++ b/lib/libalpm/package.c
@@ -166,15 +166,17 @@ const char SYMEXPORT *alpm_pkg_get_filename(pmpkg_t *pkg)
_alpm_db_read(pkg->origin_data.db, pkg, INFRQ_DESC);
}
- if(!strlen(pkg->filename)) {
+ if(pkg->filename == NULL || strlen(pkg->filename) == 0) {
/* construct the file name, it's not in the desc file */
+ char buffer[PATH_MAX];
if(pkg->arch && strlen(pkg->arch) > 0) {
- snprintf(pkg->filename, PKG_FILENAME_LEN, "%s-%s-%s" PKGEXT,
+ snprintf(buffer, PATH_MAX, "%s-%s-%s" PKGEXT,
pkg->name, pkg->version, pkg->arch);
} else {
- snprintf(pkg->filename, PKG_FILENAME_LEN, "%s-%s" PKGEXT,
+ snprintf(buffer, PATH_MAX, "%s-%s" PKGEXT,
pkg->name, pkg->version);
}
+ STRDUP(pkg->filename, buffer, RET_ERR(PM_ERR_MEMORY, NULL));
}
return pkg->filename;
@@ -756,15 +758,12 @@ 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(name) {
+ STRDUP(pkg->name, name, RET_ERR(PM_ERR_MEMORY, pkg));
}
- if(version && version[0] != 0) {
- strncpy(pkg->version, version, PKG_VERSION_LEN);
- } else {
- pkg->version[0] = '\0';
+
+ if(version) {
+ STRDUP(pkg->version, version, RET_ERR(PM_ERR_MEMORY, pkg));
}
return(pkg);
@@ -772,31 +771,51 @@ pmpkg_t *_alpm_pkg_new(const char *name, const char *version)
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);
}
@@ -809,16 +828,27 @@ 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);
+
if(pkg->origin == PKG_FROM_FILE) {
FREE(pkg->origin_data.file);
}
@@ -866,6 +896,12 @@ int _alpm_pkg_cmp(const void *p1, const void *p2)
return(strcmp(alpm_pkg_get_name(pk1), alpm_pkg_get_name(pk2)));
}
+int _alpm_pkgname_pkg_cmp(const void *pkgname, const void *package)
+{
+ return(strcmp(alpm_pkg_get_name((pmpkg_t *) package), (char *) pkgname));
+}
+
+
/* 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
@@ -900,18 +936,18 @@ static int parse_descfile(const char *descfile, pmpkg_t *info)
_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);
+ key = _alpm_strtrim(key);
+ ptr = _alpm_strtrim(ptr);
if(!strcmp(key, "pkgname")) {
- strncpy(info->name, ptr, sizeof(info->name));
+ STRDUP(info->name, ptr, RET_ERR(PM_ERR_MEMORY, -1));
} else if(!strcmp(key, "pkgver")) {
- strncpy(info->version, ptr, sizeof(info->version));
+ STRDUP(info->version, ptr, RET_ERR(PM_ERR_MEMORY, -1));
} else if(!strcmp(key, "pkgdesc")) {
- strncpy(info->desc, ptr, sizeof(info->desc));
+ STRDUP(info->desc, ptr, RET_ERR(PM_ERR_MEMORY, -1));
} 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));
+ STRDUP(info->url, ptr, RET_ERR(PM_ERR_MEMORY, -1));
} else if(!strcmp(key, "license")) {
info->licenses = alpm_list_add(info->licenses, strdup(ptr));
} else if(!strcmp(key, "builddate")) {
@@ -926,14 +962,14 @@ static int parse_descfile(const char *descfile, pmpkg_t *info)
info->builddate = atol(ptr);
}
} else if(!strcmp(key, "packager")) {
- strncpy(info->packager, ptr, sizeof(info->packager));
+ STRDUP(info->packager, ptr, RET_ERR(PM_ERR_MEMORY, -1));
} else if(!strcmp(key, "arch")) {
- strncpy(info->arch, ptr, sizeof(info->arch));
+ STRDUP(info->arch, ptr, RET_ERR(PM_ERR_MEMORY, -1));
} 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);
+ 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));
@@ -1035,11 +1071,11 @@ pmpkg_t *_alpm_pkg_load(const char *pkgfile, unsigned short full)
pkgfile);
goto pkg_invalid;
}
- if(!strlen(info->name)) {
+ if(info->name == NULL || strlen(info->name) == 0) {
_alpm_log(PM_LOG_ERROR, _("missing package name in %s\n"), pkgfile);
goto pkg_invalid;
}
- if(!strlen(info->version)) {
+ if(info->version == NULL || strlen(info->version) == 0) {
_alpm_log(PM_LOG_ERROR, _("missing package version in %s\n"), pkgfile);
goto pkg_invalid;
}
diff --git a/lib/libalpm/package.h b/lib/libalpm/package.h
index d6c3eff9..f3de05d6 100644
--- a/lib/libalpm/package.h
+++ b/lib/libalpm/package.h
@@ -33,30 +33,17 @@ typedef enum _pmpkgfrom_t {
PKG_FROM_FILE
} pmpkgfrom_t;
-/* Packages */
-#define PKG_FILENAME_LEN 512
-#define PKG_NAME_LEN 256
-#define PKG_VERSION_LEN 64
-#define PKG_FULLNAME_LEN (PKG_NAME_LEN + PKG_VERSION_LEN)
-#define PKG_DESC_LEN 512
-#define PKG_URL_LEN 256
-#define PKG_DATE_LEN 32
-#define PKG_TYPE_LEN 32
-#define PKG_PACKAGER_LEN 64
-#define PKG_MD5SUM_LEN 33
-#define PKG_ARCH_LEN 32
-
struct __pmpkg_t {
- char filename[PKG_FILENAME_LEN];
- char name[PKG_NAME_LEN];
- char version[PKG_VERSION_LEN];
- char desc[PKG_DESC_LEN];
- char url[PKG_URL_LEN];
+ char *filename;
+ char *name;
+ char *version;
+ char *desc;
+ char *url;
time_t builddate;
time_t installdate;
- char packager[PKG_PACKAGER_LEN];
- char md5sum[PKG_MD5SUM_LEN];
- char arch[PKG_ARCH_LEN];
+ char *packager;
+ char *md5sum;
+ char *arch;
unsigned long size;
unsigned long isize;
unsigned short scriptlet;
@@ -90,6 +77,7 @@ pmpkg_t* _alpm_pkg_new(const char *name, const char *version);
pmpkg_t *_alpm_pkg_dup(pmpkg_t *pkg);
void _alpm_pkg_free(pmpkg_t *pkg);
int _alpm_pkg_cmp(const void *p1, const void *p2);
+int _alpm_pkgname_pkg_cmp(const void *pkgname, const void *package);
int _alpm_pkg_compare_versions(pmpkg_t *local_pkg, pmpkg_t *pkg);
pmpkg_t *_alpm_pkg_load(const char *pkgfile, unsigned short full);
pmpkg_t *_alpm_pkg_find(const char *needle, alpm_list_t *haystack);
diff --git a/lib/libalpm/remove.c b/lib/libalpm/remove.c
index be7b3eda..44d305f2 100644
--- a/lib/libalpm/remove.c
+++ b/lib/libalpm/remove.c
@@ -120,14 +120,37 @@ int _alpm_remove_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data)
miss->target);
}
}
- FREELIST(lp);
+ alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_depmiss_free);
+ alpm_list_free(lp);
+ lp = alpm_checkdeps(db, 1, trans->packages, NULL);
+ }
+ } else if (trans->flags & PM_TRANS_FLAG_UNNEEDED) {
+ /* Remove needed packages (which break dependencies) from the target list */
+ while(lp != NULL) {
+ alpm_list_t *i;
+ for(i = lp; i; i = i->next) {
+ pmdepmissing_t *miss = (pmdepmissing_t *)i->data;
+ void *vpkg;
+ pmpkg_t *pkg;
+ trans->packages = alpm_list_remove(trans->packages, miss->causingpkg,
+ _alpm_pkgname_pkg_cmp, &vpkg);
+ pkg = vpkg;
+ if(pkg) {
+ _alpm_log(PM_LOG_WARNING, "removing %s from the 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(db, 1, trans->packages, NULL);
}
} else {
if(data) {
*data = lp;
} else {
- FREELIST(lp);
+ alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_depmiss_free);
+ alpm_list_free(lp);
}
RET_ERR(PM_ERR_UNSATISFIED_DEPS, -1);
}
diff --git a/lib/libalpm/server.c b/lib/libalpm/server.c
index 4bccf3ca..c0622552 100644
--- a/lib/libalpm/server.c
+++ b/lib/libalpm/server.c
@@ -188,7 +188,7 @@ int _alpm_downloadfiles_forreal(alpm_list_t *servers, const char *localpath,
char realfile[PATH_MAX];
char output[PATH_MAX];
char *fn = (char *)lp->data;
- char pkgname[PKG_NAME_LEN];
+ char *pkgname;
fileurl = url_for_file(server, fn);
if(!fileurl) {
@@ -196,7 +196,7 @@ int _alpm_downloadfiles_forreal(alpm_list_t *servers, const char *localpath,
}
/* pass the raw filename for passing to the callback function */
- strncpy(pkgname, fn, PKG_NAME_LEN);
+ STRDUP(pkgname, fn, (void)0);
_alpm_log(PM_LOG_DEBUG, "using '%s' for download progress\n", pkgname);
snprintf(realfile, PATH_MAX, "%s%s", localpath, fn);
@@ -403,6 +403,7 @@ int _alpm_downloadfiles_forreal(alpm_list_t *servers, const char *localpath,
}
chdir(cwd);
}
+ FREE(pkgname);
}
if(alpm_list_count(complete) == alpm_list_count(files)) {
diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c
index ced20c5a..41011583 100644
--- a/lib/libalpm/sync.c
+++ b/lib/libalpm/sync.c
@@ -47,7 +47,7 @@
#include "server.h"
#include "delta.h"
-pmsyncpkg_t *_alpm_sync_new(int type, pmpkg_t *spkg, void *data)
+pmsyncpkg_t *_alpm_sync_new(pmpkgreason_t newreason, pmpkg_t *spkg, alpm_list_t *removes)
{
pmsyncpkg_t *sync;
@@ -55,9 +55,9 @@ pmsyncpkg_t *_alpm_sync_new(int type, pmpkg_t *spkg, void *data)
CALLOC(sync, 1, sizeof(pmsyncpkg_t), RET_ERR(PM_ERR_MEMORY, NULL));
- sync->type = type;
+ sync->newreason = newreason;
sync->pkg = spkg;
- sync->data = data;
+ sync->removes = removes;
return(sync);
}
@@ -70,32 +70,11 @@ void _alpm_sync_free(pmsyncpkg_t *sync)
return;
}
- /* TODO wow this is ugly */
- if(sync->type == PM_SYNC_TYPE_REPLACE) {
- alpm_list_free_inner(sync->data, (alpm_list_fn_free)_alpm_pkg_free);
- alpm_list_free(sync->data);
- sync->data = NULL;
- } else {
- _alpm_pkg_free(sync->data);
- sync->data = NULL;
- }
+ alpm_list_free(sync->removes);
+ sync->removes = NULL;
FREE(sync);
}
-static void synclist_free(alpm_list_t *syncpkgs)
-{
- if(syncpkgs) {
- alpm_list_t *tmp;
- for(tmp = syncpkgs; tmp; tmp = alpm_list_next(tmp)) {
- if(tmp->data) {
- _alpm_sync_free(tmp->data);
- }
- }
- alpm_list_free(syncpkgs);
- }
-
-}
-
/* Find recommended replacements for packages during a sync.
*/
static int find_replacements(pmtrans_t *trans, pmdb_t *db_local,
@@ -147,27 +126,28 @@ static int find_replacements(pmtrans_t *trans, pmdb_t *db_local,
* the package to replace.
*/
pmsyncpkg_t *sync;
- pmpkg_t *dummy = _alpm_pkg_dup(lpkg);
- if(dummy == NULL) {
- pm_errno = PM_ERR_MEMORY;
- synclist_free(*syncpkgs);
- return(-1);
- }
+
/* check if spkg->name is already in the packages list. */
sync = _alpm_sync_find(*syncpkgs, alpm_pkg_get_name(spkg));
if(sync) {
- /* found it -- just append to the replaces list */
- sync->data = alpm_list_add(sync->data, dummy);
+ /* found it -- just append to the removes list */
+ sync->removes = alpm_list_add(sync->removes, lpkg);
+ /* check the to-be-replaced package's reason field */
+ if(lpkg->reason == PM_PKG_REASON_EXPLICIT) {
+ sync->newreason = PM_PKG_REASON_EXPLICIT;
+ }
} else {
/* none found -- enter pkg into the final sync list */
- sync = _alpm_sync_new(PM_SYNC_TYPE_REPLACE, spkg, NULL);
+ /* copy over reason */
+ sync = _alpm_sync_new(alpm_pkg_get_reason(lpkg), spkg, NULL);
if(sync == NULL) {
- _alpm_pkg_free(dummy);
pm_errno = PM_ERR_MEMORY;
- synclist_free(*syncpkgs);
+ alpm_list_free_inner(*syncpkgs, (alpm_list_fn_free)_alpm_sync_free);
+ alpm_list_free(*syncpkgs);
+ *syncpkgs = NULL;
return(-1);
}
- sync->data = alpm_list_add(NULL, dummy);
+ sync->removes = alpm_list_add(NULL, lpkg);
*syncpkgs = alpm_list_add(*syncpkgs, sync);
}
_alpm_log(PM_LOG_DEBUG, "%s-%s elected for upgrade (to be replaced by %s-%s)\n",
@@ -180,6 +160,35 @@ static int find_replacements(pmtrans_t *trans, pmdb_t *db_local,
return(0);
}
+/** 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_list_t *i;
+ pmpkg_t *spkg = NULL;
+
+ 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_pkg_get_name(pkg));
+ return(NULL);
+ }
+
+ /* compare versions and see if spkg is an upgrade */
+ if(_alpm_pkg_compare_versions(pkg, spkg)) {
+ _alpm_log(PM_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);
+ } else {
+ return(NULL);
+ }
+}
+
/** Get a list of upgradable packages on the current system
* Adds out of date packages to *list.
* @arg list pointer to a list of pmsyncpkg_t.
@@ -193,7 +202,7 @@ int SYMEXPORT alpm_sync_sysupgrade(pmdb_t *db_local,
int _alpm_sync_sysupgrade(pmtrans_t *trans,
pmdb_t *db_local, alpm_list_t *dbs_sync, alpm_list_t **syncpkgs)
{
- alpm_list_t *i, *j;
+ alpm_list_t *i, *j, *replaced = NULL;
ALPM_LOG_FUNC;
@@ -205,76 +214,61 @@ int _alpm_sync_sysupgrade(pmtrans_t *trans,
return(-1);
}
- /* match installed packages with the sync dbs and compare versions */
+ /* compute the to-be-replaced packages for efficiency */
+ for(i = *syncpkgs; i; i = i->next) {
+ pmsyncpkg_t *sync = i->data;
+ for(j = sync->removes; j; j = j->next) {
+ replaced = alpm_list_add(replaced, j->data);
+ }
+ }
+
+ /* for all not-replaced local package we check for upgrade */
_alpm_log(PM_LOG_DEBUG, "checking for package upgrades\n");
for(i = _alpm_db_get_pkgcache(db_local); i; i = i->next) {
- int replace = 0;
pmpkg_t *local = i->data;
- pmpkg_t *spkg = NULL;
- pmsyncpkg_t *sync;
- for(j = dbs_sync; !spkg && j; j = j->next) {
- spkg = _alpm_db_get_pkgfromcache(j->data, alpm_pkg_get_name(local));
- }
- if(spkg == NULL) {
- _alpm_log(PM_LOG_DEBUG, "'%s' not found in sync db -- skipping\n",
- alpm_pkg_get_name(local));
- continue;
- }
-
- /* we don't care about a to-be-replaced package's newer version */
- for(j = *syncpkgs; j && !replace; j=j->next) {
- sync = j->data;
- if(sync->type == PM_SYNC_TYPE_REPLACE) {
- if(_alpm_pkg_find(alpm_pkg_get_name(spkg), sync->data)) {
- replace = 1;
- }
- }
- }
- if(replace) {
+ if(_alpm_pkg_find(alpm_pkg_get_name(local), replaced)) {
_alpm_log(PM_LOG_DEBUG, "'%s' is already elected for removal -- skipping\n",
alpm_pkg_get_name(local));
continue;
}
- /* compare versions and see if we need to upgrade */
- if(_alpm_pkg_compare_versions(local, spkg)) {
- _alpm_log(PM_LOG_DEBUG, "%s elected for upgrade (%s => %s)\n",
- alpm_pkg_get_name(local), alpm_pkg_get_version(local),
- alpm_pkg_get_version(spkg));
- if(!_alpm_sync_find(*syncpkgs, alpm_pkg_get_name(spkg))) {
- /* If package is in the ignorepkg list, skip it */
- if(_alpm_pkg_should_ignore(spkg)) {
- _alpm_log(PM_LOG_WARNING, _("%s: ignoring package upgrade (%s => %s)\n"),
- alpm_pkg_get_name(local), alpm_pkg_get_version(local),
- alpm_pkg_get_version(spkg));
- continue;
- }
+ pmpkg_t *spkg = alpm_sync_newversion(local, dbs_sync);
+ if(spkg) {
+ /* we found a new version */
+ /* skip packages in IgnorePkg or in IgnoreGroup */
+ if(_alpm_pkg_should_ignore(spkg)) {
+ _alpm_log(PM_LOG_WARNING, _("%s: ignoring package upgrade (%s => %s)\n"),
+ alpm_pkg_get_name(local), alpm_pkg_get_version(local),
+ alpm_pkg_get_version(spkg));
+ continue;
+ }
- pmpkg_t *tmp = _alpm_pkg_dup(local);
- if(tmp == NULL) {
- pm_errno = PM_ERR_MEMORY;
- synclist_free(*syncpkgs);
- return(-1);
- }
- sync = _alpm_sync_new(PM_SYNC_TYPE_UPGRADE, spkg, tmp);
- if(sync == NULL) {
- _alpm_pkg_free(tmp);
- pm_errno = PM_ERR_MEMORY;
- synclist_free(*syncpkgs);
- return(-1);
- }
- *syncpkgs = alpm_list_add(*syncpkgs, sync);
+ /* add the upgrade package to our pmsyncpkg_t list */
+ if(_alpm_sync_find(*syncpkgs, alpm_pkg_get_name(spkg))) {
+ /* it is already there, done */
+ continue;
+ }
+ /* we can set any reason here, it will be overridden by add_commit */
+ pmsyncpkg_t *sync = _alpm_sync_new(PM_PKG_REASON_EXPLICIT, spkg, NULL);
+ if(sync == NULL) {
+ alpm_list_free_inner(*syncpkgs, (alpm_list_fn_free)_alpm_sync_free);
+ alpm_list_free(*syncpkgs);
+ *syncpkgs = NULL;
+ alpm_list_free(replaced);
+ return(-1);
}
+ *syncpkgs = alpm_list_add(*syncpkgs, sync);
}
}
+ alpm_list_free(replaced);
return(0);
}
int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, char *name)
{
- char targline[PKG_FULLNAME_LEN];
+ char *targline;
char *targ;
alpm_list_t *j;
pmpkg_t *local;
@@ -287,8 +281,8 @@ int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sy
ASSERT(db_local != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
ASSERT(name != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1));
+ STRDUP(targline, name, RET_ERR(PM_ERR_MEMORY, -1));
- strncpy(targline, name, PKG_FULLNAME_LEN);
targ = strchr(targline, '/');
if(targ) {
/* we are looking for a package in a specific database */
@@ -301,13 +295,15 @@ int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sy
repo_found = 1;
spkg = _alpm_db_get_pkgfromcache(db, targ);
if(spkg == NULL) {
- RET_ERR(PM_ERR_PKG_NOT_FOUND, -1);
+ pm_errno = PM_ERR_PKG_NOT_FOUND;
+ goto error;
}
}
}
if(!repo_found) {
_alpm_log(PM_LOG_ERROR, _("repository '%s' not found\n"), targline);
- RET_ERR(PM_ERR_PKG_REPO_NOT_FOUND, -1);
+ pm_errno = PM_ERR_PKG_REPO_NOT_FOUND;
+ goto error;
}
} else {
targ = targline;
@@ -316,7 +312,8 @@ int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sy
spkg = _alpm_db_get_pkgfromcache(db, targ);
}
if(spkg == NULL) {
- RET_ERR(PM_ERR_PKG_NOT_FOUND, -1);
+ pm_errno = PM_ERR_PKG_NOT_FOUND;
+ goto error;
}
}
@@ -345,36 +342,35 @@ int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sy
/* add the package to the transaction */
if(!_alpm_sync_find(trans->packages, alpm_pkg_get_name(spkg))) {
- pmpkg_t *dummy = NULL;
- if(local) {
- dummy = _alpm_pkg_dup(local);
- if(dummy == NULL) {
- RET_ERR(PM_ERR_MEMORY, -1);
- }
- }
- sync = _alpm_sync_new(PM_SYNC_TYPE_UPGRADE, spkg, dummy);
+ sync = _alpm_sync_new(PM_PKG_REASON_EXPLICIT, spkg, NULL);
if(sync == NULL) {
- _alpm_pkg_free(dummy);
- RET_ERR(PM_ERR_MEMORY, -1);
+ goto error;
}
_alpm_log(PM_LOG_DEBUG, "adding target '%s' to the transaction set\n",
alpm_pkg_get_name(spkg));
trans->packages = alpm_list_add(trans->packages, sync);
}
+ FREE(targline);
return(0);
+
+error:
+ if(targline) {
+ FREE(targline);
+ }
+ return(-1);
}
/* Helper functions for alpm_list_remove
- */
+*/
static int syncpkg_cmp(const void *s1, const void *s2)
{
const pmsyncpkg_t *sp1 = s1;
const pmsyncpkg_t *sp2 = s2;
pmpkg_t *p1, *p2;
- p1 = alpm_sync_get_pkg(sp1);
- p2 = alpm_sync_get_pkg(sp2);
+ p1 = alpm_sync_get_pkg(sp1);
+ p2 = alpm_sync_get_pkg(sp2);
return(strcmp(alpm_pkg_get_name(p1), alpm_pkg_get_name(p2)));
}
@@ -410,10 +406,8 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
/* build remove list for resolvedeps */
for(i = trans->packages; i; i = i->next) {
pmsyncpkg_t *sync = i->data;
- if(sync->type == PM_SYNC_TYPE_REPLACE) {
- for(j = sync->data; j; j = j->next) {
- remove = alpm_list_add(remove, j->data);
- }
+ for(j = sync->removes; j; j = j->next) {
+ remove = alpm_list_add(remove, j->data);
}
}
@@ -435,7 +429,7 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
/* add the dependencies found by resolvedeps to the transaction set */
pmpkg_t *spkg = i->data;
if(!_alpm_sync_find(trans->packages, alpm_pkg_get_name(spkg))) {
- pmsyncpkg_t *sync = _alpm_sync_new(PM_SYNC_TYPE_DEPEND, spkg, NULL);
+ pmsyncpkg_t *sync = _alpm_sync_new(PM_PKG_REASON_DEPEND, spkg, NULL);
if(sync == NULL) {
ret = -1;
goto cleanup;
@@ -470,180 +464,129 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
EVENT(trans, PM_TRANS_EVT_INTERCONFLICTS_START, NULL, NULL);
_alpm_log(PM_LOG_DEBUG, "looking for conflicts\n");
- deps = _alpm_checkconflicts(db_local, list);
- if(deps) {
- int errorout = 0;
- alpm_list_t *asked = NULL;
- pmconflict_t *conflict = NULL;
-
- for(i = deps; i && !errorout; i = i->next) {
- pmsyncpkg_t *sync;
- pmpkg_t *found = NULL;
-
- conflict = i->data;
- _alpm_log(PM_LOG_DEBUG, "package '%s' conflicts with '%s'\n",
- conflict->package1, conflict->package2);
- /* check if the conflicting package is about to be removed/replaced.
- * if so, then just ignore it. */
- for(j = trans->packages; j && !found; j = j->next) {
- sync = j->data;
- if(sync->type == PM_SYNC_TYPE_REPLACE) {
- found = _alpm_pkg_find(conflict->package2, sync->data);
- }
- }
- if(found) {
- _alpm_log(PM_LOG_DEBUG, "'%s' is already elected for removal -- skipping\n",
- alpm_pkg_get_name(found));
- continue;
- }
- sync = _alpm_sync_find(trans->packages, conflict->package1);
- if(sync == NULL) {
- _alpm_log(PM_LOG_DEBUG, "'%s' not found in transaction set -- skipping\n",
- conflict->package1);
- continue;
- }
- pmpkg_t *local = _alpm_db_get_pkgfromcache(db_local, conflict->package2);
- /* check if this package provides the package it's conflicting with */
- if(alpm_list_find(alpm_pkg_get_provides(sync->pkg),
- conflict->package2, _alpm_prov_cmp)) {
- /* treat like a replaces item so requiredby fields are
- * inherited properly. */
- _alpm_log(PM_LOG_DEBUG, "package '%s' provides its own conflict\n",
- conflict->package1);
- if(!local) {
- char *rmpkg = NULL;
- void *target, *depend;
- /* hmmm, package2 isn't installed, so it must be conflicting
- * with another package in our final list. For example:
- *
- * pacman -S blackbox xfree86
- *
- * If no x-servers are installed and blackbox pulls in xorg, then
- * xorg and xfree86 will conflict with each other. In this case,
- * we should follow the user's preference and rip xorg out of final,
- * opting for xfree86 instead.
- */
-
- /* figure out which one was requested in targets. If they both
- * were, then it's still an unresolvable conflict. */
- target = alpm_list_find_str(trans->targets, conflict->package1);
- depend = alpm_list_find_str(trans->targets, conflict->package2);
- if(depend && !target) {
- _alpm_log(PM_LOG_DEBUG, "'%s' is in the target list -- keeping it\n",
- conflict->package2);
- /* remove conflict->package1 */
- rmpkg = conflict->package1;
- } else if(target && !depend) {
- _alpm_log(PM_LOG_DEBUG, "'%s' is in the target list -- keeping it\n",
- conflict->package1);
- /* remove conflict->package2 */
- rmpkg = conflict->package2;
- } else {
- /* miss->target2 is not needed, miss->target already provides
- * it, let's resolve the conflict */
- rmpkg = conflict->package2;
- }
- if(rmpkg) {
- pmsyncpkg_t *rsync = _alpm_sync_find(trans->packages, rmpkg);
- if(rsync) {
- void *vpkg;
- _alpm_log(PM_LOG_DEBUG, "removing '%s' from target list\n",
- rsync->pkg->name);
- trans->packages = alpm_list_remove(trans->packages, rsync,
- syncpkg_cmp, &vpkg);
- _alpm_sync_free(vpkg);
- }
- continue;
- }
+ /* 1. check for conflicts in the target list */
+ _alpm_log(PM_LOG_DEBUG, "check targets vs targets\n");
+ deps = _alpm_innerconflicts(list);
+
+ for(i = deps; i; i = i->next) {
+ pmconflict_t *conflict = i->data;
+ pmsyncpkg_t *rsync, *sync, *sync1, *sync2;
+
+ /* have we already removed one of the conflicting targets? */
+ sync1 = _alpm_sync_find(trans->packages, conflict->package1);
+ sync2 = _alpm_sync_find(trans->packages, conflict->package2);
+ if(!sync1 || !sync2) {
+ continue;
+ }
+
+ _alpm_log(PM_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 */
+ if(alpm_list_find(alpm_pkg_get_provides(sync1->pkg),
+ conflict->package2, _alpm_prov_cmp)) {
+ rsync = sync2;
+ sync = sync1;
+ } else if(alpm_list_find(alpm_pkg_get_provides(sync2->pkg),
+ conflict->package1, _alpm_prov_cmp)) {
+ rsync = sync1;
+ sync = sync2;
+ } else {
+ _alpm_log(PM_LOG_ERROR, _("unresolvable package conflicts detected\n"));
+ pm_errno = PM_ERR_CONFLICTING_DEPS;
+ ret = -1;
+ if(data) {
+ pmconflict_t *newconflict = _alpm_conflict_dup(conflict);
+ if(newconflict) {
+ *data = alpm_list_add(*data, newconflict);
}
}
- /* It's a conflict -- see if they want to remove it */
- _alpm_log(PM_LOG_DEBUG, "resolving package '%s' conflict\n",
- conflict->package1);
- if(local) {
- int doremove = 0;
- if(!alpm_list_find_str(asked, conflict->package2)) {
- QUESTION(trans, PM_TRANS_CONV_CONFLICT_PKG, conflict->package1,
- conflict->package2, NULL, &doremove);
- asked = alpm_list_add(asked, strdup(conflict->package2));
- if(doremove) {
- pmpkg_t *q = _alpm_pkg_dup(local);
- if(sync->type != PM_SYNC_TYPE_REPLACE) {
- /* switch this sync type to REPLACE */
- sync->type = PM_SYNC_TYPE_REPLACE;
- _alpm_pkg_free(sync->data);
- sync->data = NULL;
- }
- /* append to the replaces list */
- _alpm_log(PM_LOG_DEBUG, "electing '%s' for removal\n",
- conflict->package2);
- sync->data = alpm_list_add(sync->data, q);
- /* see if the package is in the current target list */
- pmsyncpkg_t *rsync = _alpm_sync_find(trans->packages,
- conflict->package2);
- if(rsync) {
- /* remove it from the target list */
- void *vpkg;
- _alpm_log(PM_LOG_DEBUG, "removing '%s' from target list\n",
- conflict->package2);
- trans->packages = alpm_list_remove(trans->packages, rsync,
- syncpkg_cmp, &vpkg);
- _alpm_sync_free(vpkg);
- }
- } else {
- /* abort */
- _alpm_log(PM_LOG_ERROR, _("unresolvable package conflicts detected\n"));
- errorout = 1;
- }
- }
- } else {
- _alpm_log(PM_LOG_ERROR, _("unresolvable package conflicts detected\n"));
- errorout = 1;
+ alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_conflict_free);
+ alpm_list_free(deps);
+ goto cleanup;
+ }
+
+ _alpm_log(PM_LOG_DEBUG, "removing '%s' from target list\n", rsync->pkg->name);
+ /* Only prints a warning if rsync is an explicit target. */
+ if(alpm_list_find_str(trans->targets, rsync->pkg->name)) {
+ _alpm_log(PM_LOG_WARNING,
+ _("removing '%s' from target list because it conflicts with '%s'\n"),
+ rsync->pkg->name, sync->pkg->name);
+ }
+ void *vpkg;
+ trans->packages = alpm_list_remove(trans->packages, rsync,
+ syncpkg_cmp, &vpkg);
+ pmsyncpkg_t *syncpkg = vpkg;
+ list = alpm_list_remove(list, syncpkg->pkg, _alpm_pkg_cmp, NULL);
+ _alpm_sync_free(syncpkg);
+ continue;
+ }
+
+ alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_conflict_free);
+ alpm_list_free(deps);
+ 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, list);
+
+ for(i = deps; i; i = i->next) {
+ pmconflict_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->packages; j && !found; j = j->next) {
+ pmsyncpkg_t *sync = j->data;
+ if(_alpm_pkg_find(conflict->package2, sync->removes)) {
+ found = 1;
}
}
- if(errorout) {
- /* The last conflict was unresolvable, so we duplicate it and add it to *data */
+ if(found) {
+ continue;
+ }
+
+ _alpm_log(PM_LOG_DEBUG, "package '%s' conflicts with '%s'\n",
+ conflict->package1, conflict->package2);
+
+ pmsyncpkg_t *sync = _alpm_sync_find(trans->packages, conflict->package1);
+ pmpkg_t *local = _alpm_db_get_pkgfromcache(db_local, conflict->package2);
+ int doremove = 0;
+ QUESTION(trans, PM_TRANS_CONV_CONFLICT_PKG, conflict->package1,
+ conflict->package2, NULL, &doremove);
+ if(doremove) {
+ /* append to the removes list */
+ _alpm_log(PM_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;
+ ret = -1;
if(data) {
- pmconflict_t *lastconflict = conflict;
- if((conflict = malloc(sizeof(pmconflict_t))) == NULL) {
- _alpm_log(PM_LOG_ERROR, _("malloc failure: could not allocate %zd bytes\n"),
- sizeof(pmconflict_t));
- FREELIST(*data);
- pm_errno = PM_ERR_MEMORY;
- } else {
- *conflict = *lastconflict;
- *data = alpm_list_add(*data, conflict);
+ pmconflict_t *newconflict = _alpm_conflict_dup(conflict);
+ if(newconflict) {
+ *data = alpm_list_add(*data, newconflict);
}
}
- FREELIST(asked);
- FREELIST(deps);
- ret = -1;
+ alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_conflict_free);
+ alpm_list_free(deps);
goto cleanup;
}
- FREELIST(asked);
- FREELIST(deps);
}
EVENT(trans, PM_TRANS_EVT_INTERCONFLICTS_DONE, NULL, NULL);
+ alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_conflict_free);
+ alpm_list_free(deps);
}
if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) {
- /* rebuild remove and list */
- alpm_list_free(list);
- list = NULL;
- for(i = trans->packages; i; i = i->next) {
- pmsyncpkg_t *sync = i->data;
- list = alpm_list_add(list, sync->pkg);
- }
+ /* rebuild remove list */
alpm_list_free(remove);
remove = NULL;
for(i = trans->packages; i; i = i->next) {
pmsyncpkg_t *sync = i->data;
- if(sync->type == PM_SYNC_TYPE_REPLACE) {
- for(j = sync->data; j; j = j->next) {
- remove = alpm_list_add(remove, j->data);
- }
+ for(j = sync->removes; j; j = j->next) {
+ remove = alpm_list_add(remove, j->data);
}
}
@@ -655,7 +598,8 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
if(data) {
*data = deps;
} else {
- FREELIST(deps);
+ alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_depmiss_free);
+ alpm_list_free(deps);
}
goto cleanup;
}
@@ -776,7 +720,7 @@ static int apply_deltas(pmtrans_t *trans, alpm_list_t *patches)
pmpkg_t *pkg;
pmdelta_t *d;
char command[PATH_MAX], fname[PATH_MAX];
- char pkgfilename[PKG_FILENAME_LEN];
+ char pkgfilename[PATH_MAX];
pkg = alpm_list_getdata(p);
p = alpm_list_next(p);
@@ -811,7 +755,7 @@ static int apply_deltas(pmtrans_t *trans, alpm_list_t *patches)
_alpm_log(PM_LOG_DEBUG, _("command: %s\n"), command);
- snprintf(pkgfilename, PKG_FILENAME_LEN, "%s-%s-%s" PKGEXT,
+ snprintf(pkgfilename, PATH_MAX, "%s-%s-%s" PKGEXT,
pkg->name, d->to, pkg->arch);
EVENT(trans, PM_TRANS_EVT_DELTA_PATCH_START, pkgfilename, d->filename);
@@ -1128,7 +1072,6 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
tr = _alpm_trans_new();
if(tr == NULL) {
_alpm_log(PM_LOG_ERROR, _("could not create removal transaction\n"));
- pm_errno = PM_ERR_MEMORY;
goto error;
}
@@ -1139,16 +1082,14 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
for(i = trans->packages; i; i = i->next) {
pmsyncpkg_t *sync = i->data;
- if(sync->type == PM_SYNC_TYPE_REPLACE) {
- alpm_list_t *j;
- for(j = sync->data; j; j = j->next) {
- pmpkg_t *pkg = j->data;
- if(!_alpm_pkg_find(pkg->name, tr->packages)) {
- if(_alpm_trans_addtarget(tr, pkg->name) == -1) {
- goto error;
- }
- replaces++;
+ alpm_list_t *j;
+ for(j = sync->removes; j; j = j->next) {
+ pmpkg_t *pkg = j->data;
+ if(!_alpm_pkg_find(pkg->name, tr->packages)) {
+ if(_alpm_trans_addtarget(tr, pkg->name) == -1) {
+ goto error;
}
+ replaces++;
}
}
}
@@ -1173,7 +1114,6 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
tr = _alpm_trans_new();
if(tr == NULL) {
_alpm_log(PM_LOG_ERROR, _("could not create transaction\n"));
- pm_errno = PM_ERR_MEMORY;
goto error;
}
if(_alpm_trans_init(tr, PM_TRANS_TYPE_UPGRADE, trans->flags | PM_TRANS_FLAG_NODEPS, trans->cb_event, trans->cb_conv, trans->cb_progress) == -1) {
@@ -1199,9 +1139,7 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
/* using alpm_list_last() is ok because addtarget() adds the new target at the
* end of the tr->packages list */
spkg = alpm_list_last(tr->packages)->data;
- if(sync->type == PM_SYNC_TYPE_DEPEND) {
- spkg->reason = PM_PKG_REASON_DEPEND;
- }
+ spkg->reason = sync->newreason;
}
if(_alpm_trans_prepare(tr, data) == -1) {
_alpm_log(PM_LOG_ERROR, _("could not prepare transaction\n"));
@@ -1244,14 +1182,6 @@ pmsyncpkg_t *_alpm_sync_find(alpm_list_t *syncpkgs, const char* pkgname)
return(NULL); /* not found */
}
-pmsynctype_t SYMEXPORT alpm_sync_get_type(const pmsyncpkg_t *sync)
-{
- /* Sanity checks */
- ASSERT(sync != NULL, return(-1));
-
- return sync->type;
-}
-
pmpkg_t SYMEXPORT *alpm_sync_get_pkg(const pmsyncpkg_t *sync)
{
/* Sanity checks */
@@ -1260,12 +1190,12 @@ pmpkg_t SYMEXPORT *alpm_sync_get_pkg(const pmsyncpkg_t *sync)
return sync->pkg;
}
-void SYMEXPORT *alpm_sync_get_data(const pmsyncpkg_t *sync)
+alpm_list_t SYMEXPORT *alpm_sync_get_removes(const pmsyncpkg_t *sync)
{
/* Sanity checks */
ASSERT(sync != NULL, return(NULL));
- return sync->data;
+ return sync->removes;
}
/* vim: set ts=2 sw=2 noet: */
diff --git a/lib/libalpm/sync.h b/lib/libalpm/sync.h
index a6a3e74f..b71f0ef2 100644
--- a/lib/libalpm/sync.h
+++ b/lib/libalpm/sync.h
@@ -25,12 +25,12 @@
/* Sync package */
struct __pmsyncpkg_t {
- pmsynctype_t type;
+ pmpkgreason_t newreason;
pmpkg_t *pkg;
- void *data;
+ alpm_list_t *removes;
};
-pmsyncpkg_t *_alpm_sync_new(int type, pmpkg_t *spkg, void *data);
+pmsyncpkg_t *_alpm_sync_new(pmpkgreason_t newreason, pmpkg_t *spkg, alpm_list_t *removes);
void _alpm_sync_free(pmsyncpkg_t *data);
int _alpm_sync_sysupgrade(pmtrans_t *trans,
diff --git a/lib/libalpm/trans.c b/lib/libalpm/trans.c
index ecc40a0f..52dbe7a9 100644
--- a/lib/libalpm/trans.c
+++ b/lib/libalpm/trans.c
@@ -253,7 +253,8 @@ void _alpm_trans_free(pmtrans_t *trans)
FREELIST(trans->targets);
if(trans->type == PM_TRANS_TYPE_SYNC) {
alpm_list_free_inner(trans->packages, (alpm_list_fn_free)_alpm_sync_free);
- } else {
+ } else if (trans->type == PM_TRANS_TYPE_REMOVE ||
+ trans->type == PM_TRANS_TYPE_REMOVEUPGRADE) {
alpm_list_free_inner(trans->packages, (alpm_list_fn_free)_alpm_pkg_free);
}
alpm_list_free(trans->packages);
diff --git a/lib/libalpm/util.h b/lib/libalpm/util.h
index e9e0af1f..4a06e3b0 100644
--- a/lib/libalpm/util.h
+++ b/lib/libalpm/util.h
@@ -43,7 +43,8 @@
#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)
-#define STRDUP(r, s, action) do { r = strdup(s); if(r == NULL) { ALLOC_FAIL(strlen(s)); action; } } while(0)
+/* This strdup macro is NULL safe- copying NULL will yield NULL */
+#define STRDUP(r, s, action) do { if(s != NULL) { r = strdup(s); if(r == NULL) { ALLOC_FAIL(strlen(s)); action; } } else { r = NULL; } } while(0)
#define FREE(p) do { if(p) { free(p); p = NULL; } } while(0)