summaryrefslogtreecommitdiffstats
path: root/lib/libalpm/add.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libalpm/add.c')
-rw-r--r--lib/libalpm/add.c195
1 files changed, 100 insertions, 95 deletions
diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c
index 0a1a1924..33898934 100644
--- a/lib/libalpm/add.c
+++ b/lib/libalpm/add.c
@@ -37,7 +37,6 @@
#include "alpm_list.h"
#include "trans.h"
#include "util.h"
-#include "error.h"
#include "cache.h"
#include "log.h"
#include "backup.h"
@@ -68,41 +67,25 @@ int _alpm_add_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name)
pkgname = alpm_pkg_get_name(pkg);
pkgver = alpm_pkg_get_version(pkg);
- if(trans->type != PM_TRANS_TYPE_UPGRADE) {
- /* only install this package if it is not already installed */
- if(_alpm_db_get_pkgfromcache(db, pkgname)) {
- pm_errno = PM_ERR_PKG_INSTALLED;
- goto error;
- }
- }
-
/* 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);
@@ -138,12 +121,13 @@ int _alpm_add_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data)
/* look for unsatisfied dependencies */
_alpm_log(PM_LOG_DEBUG, "looking for unsatisfied dependencies\n");
- lp = alpm_checkdeps(db, trans->type == PM_TRANS_TYPE_UPGRADE, NULL, trans->packages);
+ lp = alpm_checkdeps(db, 1, NULL, trans->packages);
if(lp != NULL) {
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);
}
@@ -167,7 +151,7 @@ int _alpm_add_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data)
_alpm_log(PM_LOG_ERROR, _("you cannot install two conflicting packages at the same time\n"));
}
if(outer) {
- _alpm_log(PM_LOG_ERROR, _("replacing packages with -A and -U is not supported yet\n"));
+ _alpm_log(PM_LOG_ERROR, _("replacing packages with -U is not supported yet\n"));
_alpm_log(PM_LOG_ERROR, _("you can replace packages manually using -Rd and -U\n"));
}
RET_ERR(PM_ERR_CONFLICTING_DEPS, -1);
@@ -175,7 +159,7 @@ int _alpm_add_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data)
/* re-order w.r.t. dependencies */
_alpm_log(PM_LOG_DEBUG, "sorting by dependencies\n");
- lp = _alpm_sortbydeps(trans->packages, PM_TRANS_TYPE_ADD);
+ lp = _alpm_sortbydeps(trans->packages, 0);
/* free the old alltargs */
alpm_list_free(trans->packages);
trans->packages = lp;
@@ -193,7 +177,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);
}
@@ -210,6 +195,9 @@ static int upgrade_remove(pmpkg_t *oldpkg, pmpkg_t *newpkg, pmtrans_t *trans, pm
* with the type PM_TRANS_TYPE_REMOVEUPGRADE. TODO: kill this weird
* behavior. */
pmtrans_t *tr = _alpm_trans_new();
+
+ ALPM_LOG_FUNC;
+
_alpm_log(PM_LOG_DEBUG, "removing old package first (%s-%s)\n",
oldpkg->name, oldpkg->version);
@@ -290,17 +278,18 @@ static int extract_single_file(struct archive *archive,
struct archive_entry *entry, pmpkg_t *newpkg, pmpkg_t *oldpkg,
pmtrans_t *trans, pmdb_t *db)
{
- char entryname[PATH_MAX]; /* the name of the file in the archive */
+ const char *entryname;
mode_t entrymode;
char filename[PATH_MAX]; /* the actual file we're extracting */
int needbackup = 0, notouch = 0;
char *hash_orig = NULL;
+ char *entryname_orig = NULL;
const int archive_flags = ARCHIVE_EXTRACT_OWNER |
ARCHIVE_EXTRACT_PERM |
ARCHIVE_EXTRACT_TIME;
int errors = 0;
- strncpy(entryname, archive_entry_pathname(entry), PATH_MAX);
+ entryname = archive_entry_pathname(entry);
entrymode = archive_entry_mode(entry);
memset(filename, 0, PATH_MAX); /* just to be sure */
@@ -338,7 +327,8 @@ static int extract_single_file(struct archive *archive,
/* if a file is in the add skiplist we never extract it */
if(alpm_list_find_str(trans->skip_add, filename)) {
- _alpm_log(PM_LOG_DEBUG, "%s is in trans->skip_add, skipping extraction\n", entryname);
+ _alpm_log(PM_LOG_DEBUG, "%s is in trans->skip_add, skipping extraction\n",
+ entryname);
archive_read_data_skip(archive);
return(0);
}
@@ -437,7 +427,7 @@ static int extract_single_file(struct archive *archive,
/* if we force hash_orig to be non-NULL retroactive backup works */
if(needbackup && !hash_orig) {
- hash_orig = strdup("");
+ STRDUP(hash_orig, "", RET_ERR(PM_ERR_MEMORY, -1));
}
}
}
@@ -445,34 +435,35 @@ static int extract_single_file(struct archive *archive,
/* case 5,8: don't need to do anything special */
}
+ /* we need access to the original entryname later after calls to
+ * archive_entry_set_pathname(), so we need to dupe it and free() later */
+ STRDUP(entryname_orig, entryname, RET_ERR(PM_ERR_MEMORY, -1));
+
if(needbackup) {
- char *tempfile;
+ char checkfile[PATH_MAX];
char *hash_local = NULL, *hash_pkg = NULL;
- int fd;
+ int ret;
- /* extract the package's version to a temporary file and checksum it */
- tempfile = strdup("/tmp/alpm_XXXXXX");
- fd = mkstemp(tempfile);
+ snprintf(checkfile, PATH_MAX, "%s.paccheck", filename);
+ archive_entry_set_pathname(entry, checkfile);
- int ret = archive_read_data_into_fd(archive, fd);
- close(fd);
+ ret = archive_read_extract(archive, entry, archive_flags);
if(ret == ARCHIVE_WARN) {
/* operation succeeded but a non-critical error was encountered */
_alpm_log(PM_LOG_DEBUG, "warning extracting %s (%s)\n",
- entryname, archive_error_string(archive));
+ entryname_orig, archive_error_string(archive));
} else if(ret != ARCHIVE_OK) {
_alpm_log(PM_LOG_ERROR, _("could not extract %s (%s)\n"),
- entryname, archive_error_string(archive));
+ entryname_orig, archive_error_string(archive));
alpm_logaction("error: could not extract %s (%s)\n",
- entryname, archive_error_string(archive));
- unlink(tempfile);
- FREE(tempfile);
+ entryname_orig, archive_error_string(archive));
FREE(hash_orig);
+ FREE(entryname_orig);
return(1);
}
hash_local = alpm_get_md5sum(filename);
- hash_pkg = alpm_get_md5sum(tempfile);
+ hash_pkg = alpm_get_md5sum(checkfile);
/* append the new md5 hash to it's respective entry
* in newpkg's backup (it will be the new orginal) */
@@ -480,16 +471,13 @@ static int extract_single_file(struct archive *archive,
for(backups = alpm_pkg_get_backup(newpkg); backups;
backups = alpm_list_next(backups)) {
char *oldbackup = alpm_list_getdata(backups);
- if(!oldbackup || strcmp(oldbackup, entryname) != 0) {
+ if(!oldbackup || strcmp(oldbackup, entryname_orig) != 0) {
continue;
}
char *backup = NULL;
/* length is tab char, null byte and MD5 (32 char) */
- int backup_len = strlen(oldbackup) + 34;
- backup = malloc(backup_len);
- if(!backup) {
- RET_ERR(PM_ERR_MEMORY, -1);
- }
+ size_t backup_len = strlen(oldbackup) + 34;
+ MALLOC(backup, backup_len, RET_ERR(PM_ERR_MEMORY, -1));
sprintf(backup, "%s\t%s", oldbackup, hash_pkg);
backup[backup_len-1] = '\0';
@@ -497,7 +485,7 @@ static int extract_single_file(struct archive *archive,
backups->data = backup;
}
- _alpm_log(PM_LOG_DEBUG, "checking hashes for %s\n", entryname);
+ _alpm_log(PM_LOG_DEBUG, "checking hashes for %s\n", entryname_orig);
_alpm_log(PM_LOG_DEBUG, "current: %s\n", hash_local);
_alpm_log(PM_LOG_DEBUG, "new: %s\n", hash_pkg);
_alpm_log(PM_LOG_DEBUG, "original: %s\n", hash_orig);
@@ -511,19 +499,20 @@ static int extract_single_file(struct archive *archive,
/* move the existing file to the "pacorig" */
if(rename(filename, newpath)) {
- archive_entry_set_pathname(entry, filename);
- _alpm_log(PM_LOG_ERROR, _("could not rename %s (%s)\n"), filename, strerror(errno));
- alpm_logaction("error: could not rename %s (%s)\n", filename, strerror(errno));
+ _alpm_log(PM_LOG_ERROR, _("could not rename %s to %s (%s)\n"),
+ filename, newpath, strerror(errno));
+ alpm_logaction("error: could not rename %s to %s (%s)\n",
+ filename, newpath, strerror(errno));
errors++;
} else {
- /* copy the tempfile we extracted to the real path */
- if(_alpm_copyfile(tempfile, filename)) {
- archive_entry_set_pathname(entry, filename);
- _alpm_log(PM_LOG_ERROR, _("could not copy tempfile to %s (%s)\n"), filename, strerror(errno));
- alpm_logaction("error: could not copy tempfile to %s (%s)\n", filename, strerror(errno));
+ /* rename the file we extracted to the real name */
+ if(rename(checkfile, filename)) {
+ _alpm_log(PM_LOG_ERROR, _("could not rename %s to %s (%s)\n"),
+ checkfile, filename, strerror(errno));
+ alpm_logaction("error: could not rename %s to %s (%s)\n",
+ checkfile, filename, strerror(errno));
errors++;
} else {
- archive_entry_set_pathname(entry, filename);
_alpm_log(PM_LOG_WARNING, _("%s saved as %s\n"), filename, newpath);
alpm_logaction("warning: %s saved as %s\n", filename, newpath);
}
@@ -536,38 +525,48 @@ static int extract_single_file(struct archive *archive,
/* installed file has NOT been changed by user */
if(strcmp(hash_orig, hash_pkg) != 0) {
_alpm_log(PM_LOG_DEBUG, "action: installing new file: %s\n",
- entryname);
+ entryname_orig);
- if(_alpm_copyfile(tempfile, filename)) {
- _alpm_log(PM_LOG_ERROR, _("could not copy tempfile to %s (%s)\n"), filename, strerror(errno));
+ if(rename(checkfile, filename)) {
+ _alpm_log(PM_LOG_ERROR, _("could not rename %s to %s (%s)\n"),
+ checkfile, filename, strerror(errno));
+ alpm_logaction("error: could not rename %s to %s (%s)\n",
+ checkfile, filename, strerror(errno));
errors++;
}
- archive_entry_set_pathname(entry, filename);
} else {
/* there's no sense in installing the same file twice, install
* ONLY is the original and package hashes differ */
_alpm_log(PM_LOG_DEBUG, "action: leaving existing file in place\n");
+ unlink(checkfile);
}
} else if(strcmp(hash_orig, hash_pkg) == 0) {
/* originally installed file and new file are the same - this
* implies the case above failed - i.e. the file was changed by a
* user */
_alpm_log(PM_LOG_DEBUG, "action: leaving existing file in place\n");
+ unlink(checkfile);
} else if(strcmp(hash_local, hash_pkg) == 0) {
/* this would be magical. The above two cases failed, but the
* user changes just so happened to make the new file exactly the
* same as the one in the package... skip it */
_alpm_log(PM_LOG_DEBUG, "action: leaving existing file in place\n");
+ unlink(checkfile);
} else {
char newpath[PATH_MAX];
- _alpm_log(PM_LOG_DEBUG, "action: keeping current file and installing new one with .pacnew ending\n");
+ _alpm_log(PM_LOG_DEBUG, "action: keeping current file and installing"
+ " new one with .pacnew ending\n");
snprintf(newpath, PATH_MAX, "%s.pacnew", filename);
- if(_alpm_copyfile(tempfile, newpath)) {
- _alpm_log(PM_LOG_ERROR, _("could not install %s as %s: %s\n"), filename, newpath, strerror(errno));
- alpm_logaction("error: could not install %s as %s: %s\n", filename, newpath, strerror(errno));
+ if(rename(checkfile, newpath)) {
+ _alpm_log(PM_LOG_ERROR, _("could not install %s as %s (%s)\n"),
+ filename, newpath, strerror(errno));
+ alpm_logaction("error: could not install %s as %s (%s)\n",
+ filename, newpath, strerror(errno));
} else {
- _alpm_log(PM_LOG_WARNING, _("%s installed as %s\n"), filename, newpath);
- alpm_logaction("warning: %s installed as %s\n", filename, newpath);
+ _alpm_log(PM_LOG_WARNING, _("%s installed as %s\n"),
+ filename, newpath);
+ alpm_logaction("warning: %s installed as %s\n",
+ filename, newpath);
}
}
}
@@ -575,9 +574,9 @@ static int extract_single_file(struct archive *archive,
FREE(hash_local);
FREE(hash_pkg);
FREE(hash_orig);
- unlink(tempfile);
- FREE(tempfile);
} else {
+ int ret;
+
/* we didn't need a backup */
if(notouch) {
/* change the path to a .pacnew extension */
@@ -598,16 +597,17 @@ static int extract_single_file(struct archive *archive,
archive_entry_set_pathname(entry, filename);
- int ret = archive_read_extract(archive, entry, archive_flags);
+ ret = archive_read_extract(archive, entry, archive_flags);
if(ret == ARCHIVE_WARN) {
/* operation succeeded but a non-critical error was encountered */
_alpm_log(PM_LOG_DEBUG, "warning extracting %s (%s)\n",
- entryname, archive_error_string(archive));
+ entryname_orig, archive_error_string(archive));
} else if(ret != ARCHIVE_OK) {
_alpm_log(PM_LOG_ERROR, _("could not extract %s (%s)\n"),
- entryname, archive_error_string(archive));
+ entryname_orig, archive_error_string(archive));
alpm_logaction("error: could not extract %s (%s)\n",
- entryname, archive_error_string(archive));
+ entryname_orig, archive_error_string(archive));
+ FREE(entryname_orig);
return(1);
}
@@ -617,18 +617,15 @@ static int extract_single_file(struct archive *archive,
char *backup = NULL, *hash = NULL;
char *oldbackup = alpm_list_getdata(b);
/* length is tab char, null byte and MD5 (32 char) */
- int backup_len = strlen(oldbackup) + 34;
+ size_t backup_len = strlen(oldbackup) + 34;
- if(!oldbackup || strcmp(oldbackup, entryname) != 0) {
+ if(!oldbackup || strcmp(oldbackup, entryname_orig) != 0) {
continue;
}
_alpm_log(PM_LOG_DEBUG, "appending backup entry for %s\n", filename);
hash = alpm_get_md5sum(filename);
- backup = malloc(backup_len);
- if(!backup) {
- RET_ERR(PM_ERR_MEMORY, -1);
- }
+ MALLOC(backup, backup_len, RET_ERR(PM_ERR_MEMORY, -1));
sprintf(backup, "%s\t%s", oldbackup, hash);
backup[backup_len-1] = '\0';
@@ -637,6 +634,7 @@ static int extract_single_file(struct archive *archive,
b->data = backup;
}
}
+ FREE(entryname_orig);
return(errors);
}
@@ -644,14 +642,13 @@ static int commit_single_pkg(pmpkg_t *newpkg, int pkg_current, int pkg_count,
pmtrans_t *trans, pmdb_t *db)
{
int i, ret = 0, errors = 0;
- struct archive *archive;
- struct archive_entry *entry;
- char cwd[PATH_MAX] = "";
char scriptlet[PATH_MAX+1];
int is_upgrade = 0;
double percent = 0.0;
pmpkg_t *oldpkg = NULL;
+ ALPM_LOG_FUNC;
+
snprintf(scriptlet, PATH_MAX, "%s%s-%s/install", db->path,
alpm_pkg_get_name(newpkg), alpm_pkg_get_version(newpkg));
@@ -666,12 +663,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)) {
@@ -692,6 +685,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);
@@ -701,15 +701,20 @@ static int commit_single_pkg(pmpkg_t *newpkg, int pkg_current, int pkg_count,
}
if(!(trans->flags & PM_TRANS_FLAG_DBONLY)) {
+ struct archive *archive;
+ struct archive_entry *entry;
+ char cwd[PATH_MAX] = "";
+
_alpm_log(PM_LOG_DEBUG, "extracting files\n");
if ((archive = archive_read_new()) == NULL) {
- RET_ERR(PM_ERR_LIBARCHIVE_ERROR, -1);
+ RET_ERR(PM_ERR_LIBARCHIVE, -1);
}
archive_read_support_compression_all(archive);
archive_read_support_format_all(archive);
+ _alpm_log(PM_LOG_DEBUG, "archive: %s\n", newpkg->origin_data.file);
if(archive_read_open_filename(archive, newpkg->origin_data.file,
ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) {
RET_ERR(PM_ERR_PKG_OPEN, -1);
@@ -850,7 +855,7 @@ int _alpm_add_commit(pmtrans_t *trans, pmdb_t *db)
return(0);
}
- pkg_count = alpm_list_count(trans->targets);
+ pkg_count = alpm_list_count(trans->packages);
pkg_current = 1;
/* loop through our package list adding/upgrading one at a time */