summaryrefslogtreecommitdiff
path: root/lib/libalpm/add.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libalpm/add.c')
-rw-r--r--lib/libalpm/add.c223
1 files changed, 112 insertions, 111 deletions
diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c
index 0a1a1924..6cf865ab 100644
--- a/lib/libalpm/add.c
+++ b/lib/libalpm/add.c
@@ -27,6 +27,8 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
+#include <inttypes.h> /* int64_t */
+#include <stdint.h> /* intmax_t */
/* libarchive */
#include <archive.h>
@@ -37,7 +39,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 +69,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_pkg_vercmp(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);
@@ -113,15 +98,6 @@ error:
return(-1);
}
-
-/* This is still messy. We have a lot of compare functions, and we should
- * try to consolidate them as much as we can (between add and sync) */
-/*static int deppkg_cmp(const void *p1, const void *p2)
-{
- return(strcmp(((pmdepmissing_t *)p1)->target,
- ((pmdepmissing_t *)p2)->target));
-}*/
-
int _alpm_add_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data)
{
alpm_list_t *lp = NULL;
@@ -138,12 +114,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 +144,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 +152,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 +170,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 +188,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,29 +271,30 @@ 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 */
if(strcmp(entryname, ".INSTALL") == 0) {
/* the install script goes inside the db */
- snprintf(filename, PATH_MAX, "%s/%s-%s/install", db->path,
+ snprintf(filename, PATH_MAX, "%s%s-%s/install", db->path,
newpkg->name, newpkg->version);
archive_entry_set_mode(entry, 0644);
} else if(strcmp(entryname, ".CHANGELOG") == 0) {
/* the changelog goes inside the db */
- snprintf(filename, PATH_MAX, "%s/%s-%s/changelog", db->path,
+ snprintf(filename, PATH_MAX, "%s%s-%s/changelog", db->path,
newpkg->name, newpkg->version);
archive_entry_set_mode(entry, 0644);
} else if(*entryname == '.') {
@@ -338,7 +320,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 +420,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 +428,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 +464,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 +478,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 +492,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 +518,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 +567,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 +590,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 +610,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 +627,7 @@ static int extract_single_file(struct archive *archive,
b->data = backup;
}
}
+ FREE(entryname_orig);
return(errors);
}
@@ -644,14 +635,12 @@ 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 +655,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 +677,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 +693,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);
@@ -734,17 +731,22 @@ static int commit_single_pkg(pmpkg_t *newpkg, int pkg_current, int pkg_count,
}
for(i = 0; archive_read_next_header(archive, &entry) == ARCHIVE_OK; i++) {
+ double percent;
+
if(newpkg->size != 0) {
/* Using compressed size for calculations here, as newpkg->isize is not
* exact when it comes to comparing to the ACTUAL uncompressed size
* (missing metadata sizes) */
- unsigned long pos = archive_position_compressed(archive);
+ int64_t pos = archive_position_compressed(archive);
percent = (double)pos / (double)newpkg->size;
- _alpm_log(PM_LOG_DEBUG, "decompression progress: %f%% (%ld / %ld)\n",
- percent*100.0, pos, newpkg->size);
+ _alpm_log(PM_LOG_DEBUG, "decompression progress: "
+ "%f%% (%"PRId64" / %jd)\n",
+ percent*100.0, pos, (intmax_t)newpkg->size);
if(percent >= 1.0) {
percent = 1.0;
}
+ } else {
+ percent = 0.0;
}
if(is_upgrade) {
@@ -810,7 +812,6 @@ static int commit_single_pkg(pmpkg_t *newpkg, int pkg_current, int pkg_count,
PROGRESS(trans, PM_TRANS_PROGRESS_ADD_START,
alpm_pkg_get_name(newpkg), 100, pkg_count, pkg_current);
}
- EVENT(trans, PM_TRANS_EVT_EXTRACT_DONE, NULL, NULL);
/* run the post-install script if it exists */
if(alpm_pkg_has_scriptlet(newpkg)
@@ -850,7 +851,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 */