summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/libalpm/add.c231
-rw-r--r--lib/libalpm/add.h4
-rw-r--r--lib/libalpm/alpm.h108
-rw-r--r--lib/libalpm/alpm_list.c87
-rw-r--r--lib/libalpm/alpm_list.h2
-rw-r--r--lib/libalpm/backup.c8
-rw-r--r--lib/libalpm/be_files.c174
-rw-r--r--lib/libalpm/be_package.c7
-rw-r--r--lib/libalpm/conflict.c26
-rw-r--r--lib/libalpm/conflict.h3
-rw-r--r--lib/libalpm/db.c61
-rw-r--r--lib/libalpm/db.h22
-rw-r--r--lib/libalpm/delta.c67
-rw-r--r--lib/libalpm/deps.c2
-rw-r--r--lib/libalpm/dload.c239
-rw-r--r--lib/libalpm/dload.h4
-rw-r--r--lib/libalpm/error.c4
-rw-r--r--lib/libalpm/handle.c25
-rw-r--r--lib/libalpm/handle.h6
-rw-r--r--lib/libalpm/package.c28
-rw-r--r--lib/libalpm/package.h4
-rw-r--r--lib/libalpm/po/LINGUAS1
-rw-r--r--lib/libalpm/po/ca.po569
-rw-r--r--lib/libalpm/remove.c228
-rw-r--r--lib/libalpm/remove.h5
-rw-r--r--lib/libalpm/sync.c360
-rw-r--r--lib/libalpm/sync.h3
-rw-r--r--lib/libalpm/trans.c320
-rw-r--r--lib/libalpm/trans.h9
-rw-r--r--lib/libalpm/util.c131
-rw-r--r--lib/libalpm/util.h8
31 files changed, 1605 insertions, 1141 deletions
diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c
index 1d143c6f..ebcd6a55 100644
--- a/lib/libalpm/add.c
+++ b/lib/libalpm/add.c
@@ -50,21 +50,30 @@
#include "remove.h"
#include "handle.h"
-int _alpm_add_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name)
+/** Add a file target to the transaction.
+ * @param target the name of the file target to add
+ * @return 0 on success, -1 on error (pm_errno is set accordingly)
+ */
+int SYMEXPORT alpm_add_target(char *target)
{
pmpkg_t *pkg = NULL;
const char *pkgname, *pkgver;
alpm_list_t *i;
+ pmtrans_t *trans;
ALPM_LOG_FUNC;
+ /* Sanity checks */
+ ASSERT(target != NULL && strlen(target) != 0, RET_ERR(PM_ERR_WRONG_ARGS, -1));
+ ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1));
+ trans = handle->trans;
+ ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
+ ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1));
ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
- ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
- ASSERT(name != NULL && strlen(name) != 0, RET_ERR(PM_ERR_WRONG_ARGS, -1));
- _alpm_log(PM_LOG_DEBUG, "loading target '%s'\n", name);
+ _alpm_log(PM_LOG_DEBUG, "loading target '%s'\n", target);
- if(alpm_pkg_load(name, 1, &pkg) != 0) {
+ if(alpm_pkg_load(target, 1, &pkg) != 0) {
goto error;
}
pkgname = alpm_pkg_get_name(pkg);
@@ -72,17 +81,19 @@ 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) {
+ for(i = trans->add; i; i = i->next) {
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"),
- transpkg->name, transpkg->version, pkgver);
+ _alpm_log(PM_LOG_WARNING,
+ _("replacing older version %s-%s by %s in target list\n"),
+ transpkg->name, transpkg->version, pkgver);
_alpm_pkg_free(i->data);
i->data = pkg;
} else {
- _alpm_log(PM_LOG_WARNING, _("skipping %s-%s because newer version %s is in target list\n"),
- pkgname, pkgver, transpkg->version);
+ _alpm_log(PM_LOG_WARNING,
+ _("skipping %s-%s because newer version %s is in target list\n"),
+ pkgname, pkgver, transpkg->version);
_alpm_pkg_free(pkg);
}
return(0);
@@ -90,7 +101,7 @@ int _alpm_add_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name)
}
/* add the package to the transaction */
- trans->packages = alpm_list_add(trans->packages, pkg);
+ trans->add = alpm_list_add(trans->add, pkg);
return(0);
@@ -99,176 +110,6 @@ error:
return(-1);
}
-int _alpm_add_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data)
-{
- alpm_list_t *lp = NULL;
-
- ALPM_LOG_FUNC;
-
- ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
- ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
-
- /* Check dependencies
- */
- if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) {
- EVENT(trans, PM_TRANS_EVT_CHECKDEPS_START, NULL, NULL);
-
- /* look for unsatisfied dependencies */
- _alpm_log(PM_LOG_DEBUG, "looking for unsatisfied dependencies\n");
- lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, NULL, trans->packages);
- if(lp != NULL) {
- if(data) {
- *data = lp;
- } else {
- alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_depmiss_free);
- alpm_list_free(lp);
- }
- RET_ERR(PM_ERR_UNSATISFIED_DEPS, -1);
- }
-
- /* no unsatisfied deps, so look for conflicts */
- _alpm_log(PM_LOG_DEBUG, "looking for conflicts\n");
- alpm_list_t *inner = _alpm_innerconflicts(trans->packages);
- alpm_list_t *outer = _alpm_outerconflicts(db, trans->packages);
- lp = alpm_list_join(inner, outer);
-
- /* TODO : factorize the conflict resolving code from sync.c to use it here (FS#3492) */
-
- if(lp != NULL) {
- if(data) {
- *data = lp;
- } else {
- alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_conflict_free);
- alpm_list_free(lp);
- }
- if(inner) {
- _alpm_log(PM_LOG_ERROR, _("conflicting packages were found in target list\n"));
- _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 -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);
- }
-
- /* re-order w.r.t. dependencies */
- _alpm_log(PM_LOG_DEBUG, "sorting by dependencies\n");
- lp = _alpm_sortbydeps(trans->packages, 0);
- /* free the old alltargs */
- alpm_list_free(trans->packages);
- trans->packages = lp;
-
- EVENT(trans, PM_TRANS_EVT_CHECKDEPS_DONE, NULL, NULL);
- }
-
- /* Check for file conflicts */
- if(!(trans->flags & PM_TRANS_FLAG_FORCE)) {
- EVENT(trans, PM_TRANS_EVT_FILECONFLICTS_START, NULL, NULL);
-
- _alpm_log(PM_LOG_DEBUG, "looking for file conflicts\n");
- lp = _alpm_db_find_fileconflicts(db, trans, trans->packages, NULL);
- if(lp != NULL) {
- if(data) {
- *data = lp;
- } else {
- alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_fileconflict_free);
- alpm_list_free(lp);
- }
- RET_ERR(PM_ERR_FILE_CONFLICTS, -1);
- }
-
- EVENT(trans, PM_TRANS_EVT_FILECONFLICTS_DONE, NULL, NULL);
- }
-
- return(0);
-}
-
-static int upgrade_remove(pmpkg_t *oldpkg, pmpkg_t *newpkg, pmtrans_t *trans, pmdb_t *db) {
- /* this is kinda odd. If the old package exists, at this point we make a
- * NEW transaction, unrelated to handle->trans, and instantiate a "remove"
- * 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);
-
- if(!tr) {
- RET_ERR(PM_ERR_TRANS_ABORT, -1);
- }
-
- if(_alpm_trans_init(tr, PM_TRANS_TYPE_REMOVEUPGRADE, trans->flags,
- NULL, NULL, NULL) == -1) {
- _alpm_trans_free(tr);
- tr = NULL;
- RET_ERR(PM_ERR_TRANS_ABORT, -1);
- }
-
- if(_alpm_remove_loadtarget(tr, db, newpkg->name) == -1) {
- _alpm_trans_free(tr);
- tr = NULL;
- RET_ERR(PM_ERR_TRANS_ABORT, -1);
- }
-
- /* copy the remove skiplist over */
- tr->skip_remove = alpm_list_strdup(trans->skip_remove);
- const alpm_list_t *b;
-
- /* Add files in the NEW backup array to the NoUpgrade array
- * so this removal operation doesn't kill them */
- alpm_list_t *old_noupgrade = alpm_list_strdup(handle->noupgrade);
- /* old package backup list */
- alpm_list_t *filelist = alpm_pkg_get_files(newpkg);
- for(b = alpm_pkg_get_backup(newpkg); b; b = b->next) {
- char *backup = _alpm_backup_file(b->data);
- /* safety check (fix the upgrade026 pactest) */
- if(!alpm_list_find_str(filelist, backup)) {
- FREE(backup);
- continue;
- }
- _alpm_log(PM_LOG_DEBUG, "adding %s to the NoUpgrade array temporarily\n",
- backup);
- handle->noupgrade = alpm_list_add(handle->noupgrade,
- backup);
- }
-
- /* TODO: we could also add files in the OLD backup array, but this would
- * change the backup handling behavior, and break several pactests, and we
- * can't do this just before 3.1 release.
- * The unlink_file function in remove.c would also need to be reviewed. */
-#if 0
- /* new package backup list */
- for(b = alpm_pkg_get_backup(oldpkg); b; b = b->next) {
- char *backup = _alpm_backup_file(b->data);
- /* make sure we don't add duplicate entries */
- if(!alpm_list_find_ptr(handle->noupgrade, backup)) {
- _alpm_log(PM_LOG_DEBUG, "adding %s to the NoUpgrade array temporarily\n",
- backup);
- handle->noupgrade = alpm_list_add(handle->noupgrade,
- backup);
- }
- }
-#endif
-
- int ret = _alpm_remove_commit(tr, db);
-
- _alpm_trans_free(tr);
- tr = NULL;
-
- /* restore our "NoUpgrade" list to previous state */
- FREELIST(handle->noupgrade);
- handle->noupgrade = old_noupgrade;
-
- if(ret == -1) {
- RET_ERR(PM_ERR_TRANS_ABORT, -1);
- }
-
- return(0);
-}
-
static int extract_single_file(struct archive *archive,
struct archive_entry *entry, pmpkg_t *newpkg, pmpkg_t *oldpkg,
pmtrans_t *trans, pmdb_t *db)
@@ -291,13 +132,13 @@ static int extract_single_file(struct archive *archive,
if(strcmp(entryname, ".INSTALL") == 0) {
/* the install script goes inside the db */
- snprintf(filename, PATH_MAX, "%s%s-%s/install", db->path,
- newpkg->name, newpkg->version);
+ snprintf(filename, PATH_MAX, "%s%s-%s/install",
+ _alpm_db_path(db), newpkg->name, newpkg->version);
archive_entry_set_perm(entry, 0644);
} else if(strcmp(entryname, ".CHANGELOG") == 0) {
/* the changelog goes inside the db */
- snprintf(filename, PATH_MAX, "%s%s-%s/changelog", db->path,
- newpkg->name, newpkg->version);
+ snprintf(filename, PATH_MAX, "%s%s-%s/changelog",
+ _alpm_db_path(db), newpkg->name, newpkg->version);
archive_entry_set_perm(entry, 0644);
} else if(*entryname == '.') {
/* for now, ignore all files starting with '.' that haven't
@@ -358,7 +199,7 @@ static int extract_single_file(struct archive *archive,
/* case 12: existing dir, ignore it */
if(lsbuf.st_mode != entrymode) {
/* if filesystem perms are different than pkg perms, warn user */
- int mask = 07777;
+ mode_t mask = 07777;
_alpm_log(PM_LOG_WARNING, _("directory permissions differ on %s\n"
"filesystem: %o package: %o\n"), entryname, lsbuf.st_mode & mask,
entrymode & mask);
@@ -642,8 +483,9 @@ static int commit_single_pkg(pmpkg_t *newpkg, int pkg_current, int pkg_count,
ALPM_LOG_FUNC;
- snprintf(scriptlet, PATH_MAX, "%s%s-%s/install", db->path,
- alpm_pkg_get_name(newpkg), alpm_pkg_get_version(newpkg));
+ snprintf(scriptlet, PATH_MAX, "%s%s-%s/install",
+ _alpm_db_path(db), alpm_pkg_get_name(newpkg),
+ alpm_pkg_get_version(newpkg));
/* see if this is an upgrade. if so, remove the old package first */
pmpkg_t *local = _alpm_db_get_pkgfromcache(db, newpkg->name);
@@ -691,8 +533,9 @@ static int commit_single_pkg(pmpkg_t *newpkg, int pkg_current, int pkg_count,
if(oldpkg) {
/* set up fake remove transaction */
- int ret = upgrade_remove(oldpkg, newpkg, trans, db);
- if(ret != 0) {
+ if(_alpm_upgraderemove_package(oldpkg, newpkg, trans) == -1) {
+ pm_errno = PM_ERR_TRANS_ABORT;
+ ret = -1;
goto cleanup;
}
}
@@ -858,7 +701,7 @@ cleanup:
return(ret);
}
-int _alpm_add_commit(pmtrans_t *trans, pmdb_t *db)
+int _alpm_upgrade_packages(pmtrans_t *trans, pmdb_t *db)
{
int pkg_count, pkg_current;
alpm_list_t *targ;
@@ -868,15 +711,15 @@ int _alpm_add_commit(pmtrans_t *trans, pmdb_t *db)
ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
- if(trans->packages == NULL) {
+ if(trans->add == NULL) {
return(0);
}
- pkg_count = alpm_list_count(trans->packages);
+ pkg_count = alpm_list_count(trans->add);
pkg_current = 1;
/* loop through our package list adding/upgrading one at a time */
- for(targ = trans->packages; targ; targ = targ->next) {
+ for(targ = trans->add; targ; targ = targ->next) {
if(handle->trans->state == STATE_INTERRUPTED) {
return(0);
}
diff --git a/lib/libalpm/add.h b/lib/libalpm/add.h
index 6983de9e..b0467507 100644
--- a/lib/libalpm/add.h
+++ b/lib/libalpm/add.h
@@ -24,9 +24,7 @@
#include "alpm_list.h"
#include "trans.h"
-int _alpm_add_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name);
-int _alpm_add_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data);
-int _alpm_add_commit(pmtrans_t *trans, pmdb_t *db);
+int _alpm_upgrade_packages(pmtrans_t *trans, pmdb_t *db);
#endif /* _ALPM_ADD_H */
diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h
index ce8c6919..05ad82eb 100644
--- a/lib/libalpm/alpm.h
+++ b/lib/libalpm/alpm.h
@@ -67,10 +67,10 @@ const char *alpm_version(void);
/* Levels */
typedef enum _pmloglevel_t {
- PM_LOG_ERROR = 0x01,
- PM_LOG_WARNING = 0x02,
- PM_LOG_DEBUG = 0x04,
- PM_LOG_FUNCTION = 0x08
+ PM_LOG_ERROR = 1,
+ PM_LOG_WARNING = (1 << 1),
+ PM_LOG_DEBUG = (1 << 2),
+ PM_LOG_FUNCTION = (1 << 3)
} pmloglevel_t;
typedef void (*alpm_cb_log)(pmloglevel_t, char *, va_list);
@@ -86,14 +86,12 @@ typedef void (*alpm_cb_totaldl)(off_t total);
/** A callback for downloading files
* @param url the URL of the file to be downloaded
* @param localpath the directory to which the file should be downloaded
- * @param mtimeold the modification time of the file previously downloaded
- * @param mtimenew the modification time of the newly downloaded file.
- * This should be set by the callback.
- * @return 0 on success, 1 if the modification times are identical, -1 on
+ * @param force whether to force an update, even if the file is the same
+ * @return 0 on success, 1 if the file exists and is identical, -1 on
* error.
*/
typedef int (*alpm_cb_fetch)(const char *url, const char *localpath,
- time_t mtimeold, time_t *mtimenew);
+ int force);
/*
* Options
@@ -128,8 +126,8 @@ int alpm_option_set_logfile(const char *logfile);
const char *alpm_option_get_lockfile();
/* no set_lockfile, path is determined from dbpath */
-unsigned short alpm_option_get_usesyslog();
-void alpm_option_set_usesyslog(unsigned short usesyslog);
+int alpm_option_get_usesyslog();
+void alpm_option_set_usesyslog(int usesyslog);
alpm_list_t *alpm_option_get_noupgrades();
void alpm_option_add_noupgrade(const char *pkg);
@@ -151,9 +149,11 @@ void alpm_option_add_ignoregrp(const char *grp);
void alpm_option_set_ignoregrps(alpm_list_t *ignoregrps);
int alpm_option_remove_ignoregrp(const char *grp);
-unsigned short alpm_option_get_nopassiveftp();
-void alpm_option_set_nopassiveftp(unsigned short nopasv);
-void alpm_option_set_usedelta(unsigned short usedelta);
+const char *alpm_option_get_arch();
+void alpm_option_set_arch(const char *arch);
+
+int alpm_option_get_usedelta();
+void alpm_option_set_usedelta(int usedelta);
pmdb_t *alpm_option_get_localdb();
alpm_list_t *alpm_option_get_syncdbs();
@@ -194,7 +194,7 @@ typedef enum _pmpkgreason_t {
PM_PKG_REASON_DEPEND = 1 /* installed as a dependency for another package */
} pmpkgreason_t;
-int alpm_pkg_load(const char *filename, unsigned short full, pmpkg_t **pkg);
+int alpm_pkg_load(const char *filename, int full, pmpkg_t **pkg);
int alpm_pkg_free(pmpkg_t *pkg);
int alpm_pkg_checkmd5sum(pmpkg_t *pkg);
char *alpm_fetch_pkgurl(const char *url);
@@ -224,15 +224,14 @@ alpm_list_t *alpm_pkg_get_deltas(pmpkg_t *pkg);
alpm_list_t *alpm_pkg_get_replaces(pmpkg_t *pkg);
alpm_list_t *alpm_pkg_get_files(pmpkg_t *pkg);
alpm_list_t *alpm_pkg_get_backup(pmpkg_t *pkg);
-alpm_list_t *alpm_pkg_get_removes(pmpkg_t *pkg);
pmdb_t *alpm_pkg_get_db(pmpkg_t *pkg);
void *alpm_pkg_changelog_open(pmpkg_t *pkg);
size_t alpm_pkg_changelog_read(void *ptr, size_t size,
const pmpkg_t *pkg, const void *fp);
/*int alpm_pkg_changelog_feof(const pmpkg_t *pkg, void *fp);*/
int alpm_pkg_changelog_close(const pmpkg_t *pkg, void *fp);
-unsigned short alpm_pkg_has_scriptlet(pmpkg_t *pkg);
-unsigned short alpm_pkg_has_force(pmpkg_t *pkg);
+int alpm_pkg_has_scriptlet(pmpkg_t *pkg);
+int alpm_pkg_has_force(pmpkg_t *pkg);
off_t alpm_pkg_download_size(pmpkg_t *newpkg);
@@ -262,34 +261,27 @@ pmpkg_t *alpm_sync_newversion(pmpkg_t *pkg, alpm_list_t *dbs_sync);
* Transactions
*/
-/* Types */
-typedef enum _pmtranstype_t {
- PM_TRANS_TYPE_UPGRADE = 1,
- PM_TRANS_TYPE_REMOVE,
- PM_TRANS_TYPE_REMOVEUPGRADE,
- PM_TRANS_TYPE_SYNC
-} pmtranstype_t;
/* Flags */
typedef enum _pmtransflag_t {
- PM_TRANS_FLAG_NODEPS = 0x01,
- PM_TRANS_FLAG_FORCE = 0x02,
- PM_TRANS_FLAG_NOSAVE = 0x04,
- /* 0x08 flag can go here */
- PM_TRANS_FLAG_CASCADE = 0x10,
- PM_TRANS_FLAG_RECURSE = 0x20,
- PM_TRANS_FLAG_DBONLY = 0x40,
- /* 0x80 flag can go here */
- PM_TRANS_FLAG_ALLDEPS = 0x100,
- PM_TRANS_FLAG_DOWNLOADONLY = 0x200,
- PM_TRANS_FLAG_NOSCRIPTLET = 0x400,
- PM_TRANS_FLAG_NOCONFLICTS = 0x800,
- /* 0x1000 flag can go here */
- PM_TRANS_FLAG_NEEDED = 0x2000,
- PM_TRANS_FLAG_ALLEXPLICIT = 0x4000,
- PM_TRANS_FLAG_UNNEEDED = 0x8000,
- PM_TRANS_FLAG_RECURSEALL = 0x10000,
- PM_TRANS_FLAG_NOLOCK = 0x20000
+ PM_TRANS_FLAG_NODEPS = 1,
+ PM_TRANS_FLAG_FORCE = (1 << 1),
+ PM_TRANS_FLAG_NOSAVE = (1 << 2),
+ /* (1 << 3) flag can go here */
+ PM_TRANS_FLAG_CASCADE = (1 << 4),
+ PM_TRANS_FLAG_RECURSE = (1 << 5),
+ PM_TRANS_FLAG_DBONLY = (1 << 6),
+ /* (1 << 7) flag can go here */
+ PM_TRANS_FLAG_ALLDEPS = (1 << 8),
+ PM_TRANS_FLAG_DOWNLOADONLY = (1 << 9),
+ PM_TRANS_FLAG_NOSCRIPTLET = (1 << 10),
+ PM_TRANS_FLAG_NOCONFLICTS = (1 << 11),
+ /* (1 << 12) flag can go here */
+ PM_TRANS_FLAG_NEEDED = (1 << 13),
+ PM_TRANS_FLAG_ALLEXPLICIT = (1 << 14),
+ PM_TRANS_FLAG_UNNEEDED = (1 << 15),
+ PM_TRANS_FLAG_RECURSEALL = (1 << 16),
+ PM_TRANS_FLAG_NOLOCK = (1 << 17)
} pmtransflag_t;
/**
@@ -376,12 +368,12 @@ typedef enum _pmtransevt_t {
/* Transaction Conversations (ie, questions) */
typedef enum _pmtransconv_t {
- PM_TRANS_CONV_INSTALL_IGNOREPKG = 0x01,
- PM_TRANS_CONV_REPLACE_PKG = 0x02,
- PM_TRANS_CONV_CONFLICT_PKG = 0x04,
- PM_TRANS_CONV_CORRUPTED_PKG = 0x08,
- PM_TRANS_CONV_LOCAL_NEWER = 0x10,
- PM_TRANS_CONV_REMOVE_PKGS = 0x20,
+ PM_TRANS_CONV_INSTALL_IGNOREPKG = 1,
+ PM_TRANS_CONV_REPLACE_PKG = (1 << 1),
+ PM_TRANS_CONV_CONFLICT_PKG = (1 << 2),
+ PM_TRANS_CONV_CORRUPTED_PKG = (1 << 3),
+ PM_TRANS_CONV_LOCAL_NEWER = (1 << 4),
+ PM_TRANS_CONV_REMOVE_PKGS = (1 << 5),
} pmtransconv_t;
/* Transaction Progress */
@@ -402,19 +394,23 @@ typedef void (*alpm_trans_cb_conv)(pmtransconv_t, void *, void *,
/* Transaction Progress callback */
typedef void (*alpm_trans_cb_progress)(pmtransprog_t, const char *, int, int, int);
-pmtranstype_t alpm_trans_get_type();
-unsigned int alpm_trans_get_flags();
-alpm_list_t * alpm_trans_get_pkgs();
-int alpm_trans_init(pmtranstype_t type, pmtransflag_t flags,
+int alpm_trans_get_flags();
+alpm_list_t * alpm_trans_get_add();
+alpm_list_t * alpm_trans_get_remove();
+int alpm_trans_init(pmtransflag_t flags,
alpm_trans_cb_event cb_event, alpm_trans_cb_conv conv,
alpm_trans_cb_progress cb_progress);
-int alpm_trans_sysupgrade(int enable_downgrade);
-int alpm_trans_addtarget(char *target);
int alpm_trans_prepare(alpm_list_t **data);
int alpm_trans_commit(alpm_list_t **data);
int alpm_trans_interrupt(void);
int alpm_trans_release(void);
+int alpm_sync_sysupgrade(int enable_downgrade);
+int alpm_sync_target(char *target);
+int alpm_sync_dbtarget(char *db, char *target);
+int alpm_add_target(char *target);
+int alpm_remove_target(char *target);
+
/*
* Dependencies and conflicts
*/
@@ -441,6 +437,7 @@ alpm_list_t *alpm_checkconflicts(alpm_list_t *pkglist);
const char *alpm_conflict_get_package1(pmconflict_t *conflict);
const char *alpm_conflict_get_package2(pmconflict_t *conflict);
+const char *alpm_conflict_get_reason(pmconflict_t *conflict);
pmdepmod_t alpm_dep_get_mod(const pmdepend_t *dep);
const char *alpm_dep_get_name(const pmdepend_t *dep);
@@ -509,6 +506,7 @@ enum _pmerrno_t {
PM_ERR_PKG_OPEN,
PM_ERR_PKG_CANT_REMOVE,
PM_ERR_PKG_INVALID_NAME,
+ PM_ERR_PKG_INVALID_ARCH,
PM_ERR_PKG_REPO_NOT_FOUND,
/* Deltas */
PM_ERR_DLT_INVALID,
diff --git a/lib/libalpm/alpm_list.c b/lib/libalpm/alpm_list.c
index 127f72ac..a395540e 100644
--- a/lib/libalpm/alpm_list.c
+++ b/lib/libalpm/alpm_list.c
@@ -616,7 +616,7 @@ static int ptr_cmp(const void *p, const void *q)
/**
* @brief Find an item in a list.
*
- * Search for the item whos data matches that of the `needle`.
+ * Search for the item whose data matches that of the `needle`.
*
* @param needle the data to search for (== comparison)
* @param haystack the list
@@ -644,11 +644,65 @@ char SYMEXPORT *alpm_list_find_str(const alpm_list_t *haystack,
}
/**
- * @brief Find the items in list `lhs` that are not present in list `rhs`.
+ * @brief Find the differences between list `left` and list `right`
+ *
+ * The two lists must be sorted. Items only in list `left` are added to the
+ * `onlyleft` list. Items only in list `right` are added to the `onlyright`
+ * list.
*
- * Entries are not duplicated. Operation is O(m*n). The first list is stepped
- * through one node at a time, and for each node in the first list, each node
- * in the second list is compared to it.
+ * @param left the first list
+ * @param right the second list
+ * @param fn the comparison function
+ * @param onlyleft pointer to the first result list
+ * @param onlyright pointer to the second result list
+ *
+ */
+void SYMEXPORT alpm_list_diff_sorted(alpm_list_t *left,
+ alpm_list_t *right, alpm_list_fn_cmp fn,
+ alpm_list_t **onlyleft, alpm_list_t **onlyright)
+{
+ alpm_list_t *l = left;
+ alpm_list_t *r = right;
+
+ if(!onlyleft && !onlyright) {
+ return;
+ }
+
+ while (l != NULL && r != NULL) {
+ int cmp = fn(l->data, r->data);
+ if(cmp < 0) {
+ if(onlyleft) {
+ *onlyleft = alpm_list_add(*onlyleft, l->data);
+ }
+ l = l->next;
+ }
+ else if(cmp > 0) {
+ if(onlyright) {
+ *onlyright = alpm_list_add(*onlyright, r->data);
+ }
+ r = r->next;
+ } else {
+ l = l->next;
+ r = r->next;
+ }
+ }
+ while (l != NULL) {
+ if(onlyleft) {
+ *onlyleft = alpm_list_add(*onlyleft, l->data);
+ }
+ l = l->next;
+ }
+ while (r != NULL) {
+ if(onlyright) {
+ *onlyright = alpm_list_add(*onlyright, r->data);
+ }
+ r = r->next;
+ }
+}
+
+
+/**
+ * @brief Find the items in list `lhs` that are not present in list `rhs`.
*
* @param lhs the first list
* @param rhs the second list
@@ -659,21 +713,18 @@ char SYMEXPORT *alpm_list_find_str(const alpm_list_t *haystack,
alpm_list_t SYMEXPORT *alpm_list_diff(const alpm_list_t *lhs,
const alpm_list_t *rhs, alpm_list_fn_cmp fn)
{
- const alpm_list_t *i, *j;
+ alpm_list_t *left, *right;
alpm_list_t *ret = NULL;
- for(i = lhs; i; i = i->next) {
- int found = 0;
- for(j = rhs; j; j = j->next) {
- if(fn(i->data, j->data) == 0) {
- found = 1;
- break;
- }
- }
- if(!found) {
- ret = alpm_list_add(ret, i->data);
- }
- }
+ left = alpm_list_copy(lhs);
+ left = alpm_list_msort(left, alpm_list_count(left), fn);
+ right = alpm_list_copy(rhs);
+ right = alpm_list_msort(right, alpm_list_count(right), fn);
+
+ alpm_list_diff_sorted(left, right, fn, &ret, NULL);
+
+ alpm_list_free(left);
+ alpm_list_free(right);
return(ret);
}
diff --git a/lib/libalpm/alpm_list.h b/lib/libalpm/alpm_list.h
index f079ecfd..48e91173 100644
--- a/lib/libalpm/alpm_list.h
+++ b/lib/libalpm/alpm_list.h
@@ -78,6 +78,8 @@ void *alpm_list_find(const alpm_list_t *haystack, const void *needle, alpm_list_
void *alpm_list_find_ptr(const alpm_list_t *haystack, const void *needle);
char *alpm_list_find_str(const alpm_list_t *haystack, const char *needle);
alpm_list_t *alpm_list_diff(const alpm_list_t *lhs, const alpm_list_t *rhs, alpm_list_fn_cmp fn);
+void alpm_list_diff_sorted(alpm_list_t *left, alpm_list_t *right,
+ alpm_list_fn_cmp fn, alpm_list_t **onlyleft, alpm_list_t **onlyright);
#ifdef __cplusplus
}
diff --git a/lib/libalpm/backup.c b/lib/libalpm/backup.c
index e628131f..a0c6b7fc 100644
--- a/lib/libalpm/backup.c
+++ b/lib/libalpm/backup.c
@@ -33,7 +33,7 @@
#include "util.h"
/* split a backup string "file\thash" into two strings : file and hash */
-int _alpm_backup_split(const char *string, char **file, char **hash)
+static int backup_split(const char *string, char **file, char **hash)
{
char *str = strdup(string);
char *ptr;
@@ -65,14 +65,14 @@ int _alpm_backup_split(const char *string, char **file, char **hash)
char *_alpm_backup_file(const char *string)
{
char *file = NULL;
- _alpm_backup_split(string, &file, NULL);
+ backup_split(string, &file, NULL);
return(file);
}
char *_alpm_backup_hash(const char *string)
{
char *hash = NULL;
- _alpm_backup_split(string, NULL, &hash);
+ backup_split(string, NULL, &hash);
return(hash);
}
@@ -95,7 +95,7 @@ char *_alpm_needbackup(const char *file, const alpm_list_t *backup)
char *hash = NULL;
/* no hash found */
- if(!_alpm_backup_split((char *)lp->data, &filename, &hash)) {
+ if(!backup_split((char *)lp->data, &filename, &hash)) {
FREE(filename);
continue;
}
diff --git a/lib/libalpm/be_files.c b/lib/libalpm/be_files.c
index bfe10867..f624d7cf 100644
--- a/lib/libalpm/be_files.c
+++ b/lib/libalpm/be_files.c
@@ -47,76 +47,10 @@
#include "dload.h"
-/*
- * Return the last update time as number of seconds from the epoch.
- * Returns 0 if the value is unknown or can't be read.
- */
-static time_t getlastupdate(const pmdb_t *db)
-{
- FILE *fp;
- char *file;
- time_t ret = 0;
-
- ALPM_LOG_FUNC;
-
- if(db == NULL) {
- return(ret);
- }
-
- /* db->path + '.lastupdate' + NULL */
- MALLOC(file, strlen(db->path) + 12, RET_ERR(PM_ERR_MEMORY, ret));
- sprintf(file, "%s.lastupdate", db->path);
-
- /* get the last update time, if it's there */
- if((fp = fopen(file, "r")) == NULL) {
- free(file);
- return(ret);
- } else {
- char line[64];
- if(fgets(line, sizeof(line), fp)) {
- ret = atol(line);
- }
- }
- fclose(fp);
- free(file);
- return(ret);
-}
-
-/*
- * writes the dbpath/.lastupdate file with the value in time
- */
-static int setlastupdate(const pmdb_t *db, time_t time)
-{
- FILE *fp;
- char *file;
- int ret = 0;
-
- ALPM_LOG_FUNC;
-
- if(db == NULL || time == 0) {
- return(-1);
- }
-
- /* db->path + '.lastupdate' + NULL */
- MALLOC(file, strlen(db->path) + 12, RET_ERR(PM_ERR_MEMORY, ret));
- sprintf(file, "%s.lastupdate", db->path);
-
- if((fp = fopen(file, "w")) == NULL) {
- free(file);
- return(-1);
- }
- if(fprintf(fp, "%ju", (uintmax_t)time) <= 0) {
- ret = -1;
- }
- fclose(fp);
- free(file);
- return(ret);
-}
-
static int checkdbdir(pmdb_t *db)
{
struct stat buf;
- char *path = db->path;
+ const char *path = _alpm_db_path(db);
if(stat(path, &buf) != 0) {
_alpm_log(PM_LOG_DEBUG, "database dir '%s' does not exist, creating it\n",
@@ -148,7 +82,7 @@ static int checkdbdir(pmdb_t *db)
* pmdb_t *db;
* int result;
* db = alpm_list_getdata(alpm_option_get_syncdbs());
- * if(alpm_trans_init(PM_TRANS_TYPE_SYNC, 0, NULL, NULL, NULL) == 0) {
+ * if(alpm_trans_init(0, NULL, NULL, NULL) == 0) {
* result = alpm_db_update(0, db);
* alpm_trans_release();
*
@@ -174,7 +108,6 @@ static int checkdbdir(pmdb_t *db)
int SYMEXPORT alpm_db_update(int force, pmdb_t *db)
{
char *dbfile, *dbfilepath;
- time_t newmtime = 0, lastupdate = 0;
const char *dbpath;
size_t len;
@@ -191,33 +124,22 @@ int SYMEXPORT alpm_db_update(int force, pmdb_t *db)
*/
ASSERT(handle->trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
ASSERT(handle->trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1));
- ASSERT(handle->trans->type == PM_TRANS_TYPE_SYNC, RET_ERR(PM_ERR_TRANS_TYPE, -1));
if(!alpm_list_find_ptr(handle->dbs_sync, db)) {
RET_ERR(PM_ERR_DB_NOT_FOUND, -1);
}
- if(!force) {
- /* get the lastupdate time */
- lastupdate = getlastupdate(db);
- if(lastupdate == 0) {
- _alpm_log(PM_LOG_DEBUG, "failed to get lastupdate time for %s\n",
- db->treename);
- }
- }
-
len = strlen(db->treename) + strlen(DBEXT) + 1;
MALLOC(dbfile, len, RET_ERR(PM_ERR_MEMORY, -1));
sprintf(dbfile, "%s" DBEXT, db->treename);
dbpath = alpm_option_get_dbpath();
- ret = _alpm_download_single_file(dbfile, db->servers, dbpath,
- lastupdate, &newmtime);
+ ret = _alpm_download_single_file(dbfile, db->servers, dbpath, force);
free(dbfile);
if(ret == 1) {
- /* mtimes match, do nothing */
+ /* files match, do nothing */
pm_errno = 0;
return(1);
} else if(ret == -1) {
@@ -225,12 +147,16 @@ int SYMEXPORT alpm_db_update(int force, pmdb_t *db)
_alpm_log(PM_LOG_DEBUG, "failed to sync db: %s\n", alpm_strerrorlast());
return(-1);
} else {
+ const char *syncdbpath = _alpm_db_path(db);
/* remove the old dir */
- if(_alpm_rmrf(db->path) != 0) {
+ if(_alpm_rmrf(syncdbpath) != 0) {
_alpm_log(PM_LOG_ERROR, _("could not remove database %s\n"), db->treename);
RET_ERR(PM_ERR_DB_REMOVE, -1);
+ } else {
+ _alpm_log(PM_LOG_DEBUG, "database dir %s removed\n", _alpm_db_path(db));
}
+
/* Cache needs to be rebuilt */
_alpm_db_free_pkgcache(db);
@@ -241,20 +167,12 @@ int SYMEXPORT alpm_db_update(int force, pmdb_t *db)
/* uncompress the sync database */
checkdbdir(db);
- ret = _alpm_unpack(dbfilepath, db->path, NULL);
+ ret = _alpm_unpack(dbfilepath, syncdbpath, NULL, 0);
if(ret) {
free(dbfilepath);
RET_ERR(PM_ERR_SYSTEM, -1);
}
- unlink(dbfilepath);
free(dbfilepath);
-
- /* if we have a new mtime, set the DB last update value */
- if(newmtime) {
- _alpm_log(PM_LOG_DEBUG, "sync: new mtime for %s: %ju\n",
- db->treename, (uintmax_t)newmtime);
- setlastupdate(db, newmtime);
- }
}
return(0);
@@ -306,13 +224,15 @@ int _alpm_db_populate(pmdb_t *db)
struct dirent *ent = NULL;
struct stat sbuf;
char path[PATH_MAX];
+ const char *dbpath;
DIR *dbdir;
ALPM_LOG_FUNC;
ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
- dbdir = opendir(db->path);
+ dbpath = _alpm_db_path(db);
+ dbdir = opendir(dbpath);
if(dbdir == NULL) {
return(0);
}
@@ -324,7 +244,7 @@ int _alpm_db_populate(pmdb_t *db)
continue;
}
/* stat the entry, make sure it's a directory */
- snprintf(path, PATH_MAX, "%s%s", db->path, name);
+ snprintf(path, PATH_MAX, "%s%s", dbpath, name);
if(stat(path, &sbuf) != 0 || !S_ISDIR(sbuf.st_mode)) {
continue;
}
@@ -342,6 +262,13 @@ int _alpm_db_populate(pmdb_t *db)
continue;
}
+ /* duplicated database entries are not allowed */
+ if(_alpm_pkg_find(db->pkgcache, pkg->name)) {
+ _alpm_log(PM_LOG_ERROR, _("duplicated database entry '%s'\n"), pkg->name);
+ _alpm_pkg_free(pkg);
+ continue;
+ }
+
/* explicitly read with only 'BASE' data, accessors will handle the rest */
if(_alpm_db_read(db, pkg, INFRQ_BASE) == -1) {
_alpm_log(PM_LOG_ERROR, _("corrupted database entry '%s'\n"), name);
@@ -367,10 +294,12 @@ static char *get_pkgpath(pmdb_t *db, pmpkg_t *info)
{
size_t len;
char *pkgpath;
+ const char *dbpath;
- len = strlen(db->path) + strlen(info->name) + strlen(info->version) + 3;
+ dbpath = _alpm_db_path(db);
+ len = strlen(dbpath) + strlen(info->name) + strlen(info->version) + 3;
MALLOC(pkgpath, len, RET_ERR(PM_ERR_MEMORY, NULL));
- sprintf(pkgpath, "%s%s-%s/", db->path, info->name, info->version);
+ sprintf(pkgpath, "%s%s-%s/", dbpath, info->name, info->version);
return(pkgpath);
}
@@ -379,6 +308,7 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)
FILE *fp = NULL;
char path[PATH_MAX];
char line[513];
+ int sline = sizeof(line)-1;
char *pkgpath = NULL;
ALPM_LOG_FUNC;
@@ -410,7 +340,7 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)
info->name, inforeq);
/* clear out 'line', to be certain - and to make valgrind happy */
- memset(line, 0, 513);
+ memset(line, 0, sline+1);
pkgpath = get_pkgpath(db, info);
@@ -434,7 +364,7 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)
}
_alpm_strtrim(line);
if(strcmp(line, "%NAME%") == 0) {
- if(fgets(line, 512, fp) == NULL) {
+ if(fgets(line, sline, fp) == NULL) {
goto error;
}
if(strcmp(_alpm_strtrim(line), info->name) != 0) {
@@ -442,7 +372,7 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)
"mismatch on package %s\n"), db->treename, info->name);
}
} else if(strcmp(line, "%VERSION%") == 0) {
- if(fgets(line, 512, fp) == NULL) {
+ if(fgets(line, sline, fp) == NULL) {
goto error;
}
if(strcmp(_alpm_strtrim(line), info->version) != 0) {
@@ -450,44 +380,44 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)
"mismatch on package %s\n"), db->treename, info->name);
}
} else if(strcmp(line, "%FILENAME%") == 0) {
- if(fgets(line, 512, fp) == NULL) {
+ if(fgets(line, sline, fp) == NULL) {
goto error;
}
STRDUP(info->filename, _alpm_strtrim(line), goto error);
} else if(strcmp(line, "%DESC%") == 0) {
- if(fgets(line, 512, fp) == NULL) {
+ if(fgets(line, sline, fp) == NULL) {
goto error;
}
STRDUP(info->desc, _alpm_strtrim(line), goto error);
} else if(strcmp(line, "%GROUPS%") == 0) {
- while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {
+ while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) {
char *linedup;
STRDUP(linedup, _alpm_strtrim(line), goto error);
info->groups = alpm_list_add(info->groups, linedup);
}
} else if(strcmp(line, "%URL%") == 0) {
- if(fgets(line, 512, fp) == NULL) {
+ if(fgets(line, sline, fp) == NULL) {
goto error;
}
STRDUP(info->url, _alpm_strtrim(line), goto error);
} else if(strcmp(line, "%LICENSE%") == 0) {
- while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {
+ while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) {
char *linedup;
STRDUP(linedup, _alpm_strtrim(line), goto error);
info->licenses = alpm_list_add(info->licenses, linedup);
}
} else if(strcmp(line, "%ARCH%") == 0) {
- if(fgets(line, 512, fp) == NULL) {
+ if(fgets(line, sline, fp) == NULL) {
goto error;
}
STRDUP(info->arch, _alpm_strtrim(line), goto error);
} else if(strcmp(line, "%BUILDDATE%") == 0) {
- if(fgets(line, 512, fp) == NULL) {
+ if(fgets(line, sline, fp) == NULL) {
goto error;
}
_alpm_strtrim(line);
- char first = tolower(line[0]);
+ char first = tolower((unsigned char)line[0]);
if(first > 'a' && first < 'z') {
struct tm tmp_tm = {0}; /* initialize to null in case of failure */
setlocale(LC_TIME, "C");
@@ -498,12 +428,12 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)
info->builddate = atol(line);
}
} else if(strcmp(line, "%INSTALLDATE%") == 0) {
- if(fgets(line, 512, fp) == NULL) {
+ if(fgets(line, sline, fp) == NULL) {
goto error;
}
_alpm_strtrim(line);
- char first = tolower(line[0]);
+ char first = tolower((unsigned char)line[0]);
if(first > 'a' && first < 'z') {
struct tm tmp_tm = {0}; /* initialize to null in case of failure */
setlocale(LC_TIME, "C");
@@ -514,12 +444,12 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)
info->installdate = atol(line);
}
} else if(strcmp(line, "%PACKAGER%") == 0) {
- if(fgets(line, 512, fp) == NULL) {
+ if(fgets(line, sline, fp) == NULL) {
goto error;
}
STRDUP(info->packager, _alpm_strtrim(line), goto error);
} else if(strcmp(line, "%REASON%") == 0) {
- if(fgets(line, 512, fp) == NULL) {
+ if(fgets(line, sline, fp) == NULL) {
goto error;
}
info->reason = (pmpkgreason_t)atol(_alpm_strtrim(line));
@@ -529,7 +459,7 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)
* is currently only used in sync databases, and SIZE is
* only used in local databases.
*/
- if(fgets(line, 512, fp) == NULL) {
+ if(fgets(line, sline, fp) == NULL) {
goto error;
}
info->size = atol(_alpm_strtrim(line));
@@ -540,19 +470,19 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)
} else if(strcmp(line, "%ISIZE%") == 0) {
/* ISIZE (installed size) tag only appears in sync repositories,
* not the local one. */
- if(fgets(line, 512, fp) == NULL) {
+ if(fgets(line, sline, fp) == NULL) {
goto error;
}
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(line, 512, fp) == NULL) {
+ if(fgets(line, sline, fp) == NULL) {
goto error;
}
STRDUP(info->md5sum, _alpm_strtrim(line), goto error);
} else if(strcmp(line, "%REPLACES%") == 0) {
- while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {
+ while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) {
char *linedup;
STRDUP(linedup, _alpm_strtrim(line), goto error);
info->replaces = alpm_list_add(info->replaces, linedup);
@@ -575,13 +505,13 @@ 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%") == 0) {
- while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {
+ while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) {
char *linedup;
STRDUP(linedup, _alpm_strtrim(line), goto error);
info->files = alpm_list_add(info->files, linedup);
}
} else if(strcmp(line, "%BACKUP%") == 0) {
- while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {
+ while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) {
char *linedup;
STRDUP(linedup, _alpm_strtrim(line), goto error);
info->backup = alpm_list_add(info->backup, linedup);
@@ -603,24 +533,24 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)
fgets(line, 255, fp);
_alpm_strtrim(line);
if(strcmp(line, "%DEPENDS%") == 0) {
- while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {
+ while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) {
pmdepend_t *dep = _alpm_splitdep(_alpm_strtrim(line));
info->depends = alpm_list_add(info->depends, dep);
}
} else if(strcmp(line, "%OPTDEPENDS%") == 0) {
- while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {
+ while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) {
char *linedup;
STRDUP(linedup, _alpm_strtrim(line), goto error);
info->optdepends = alpm_list_add(info->optdepends, linedup);
}
} else if(strcmp(line, "%CONFLICTS%") == 0) {
- while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {
+ while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) {
char *linedup;
STRDUP(linedup, _alpm_strtrim(line), goto error);
info->conflicts = alpm_list_add(info->conflicts, linedup);
}
} else if(strcmp(line, "%PROVIDES%") == 0) {
- while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {
+ while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) {
char *linedup;
STRDUP(linedup, _alpm_strtrim(line), goto error);
info->provides = alpm_list_add(info->provides, linedup);
@@ -639,7 +569,7 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)
fgets(line, 255, fp);
_alpm_strtrim(line);
if(strcmp(line, "%DELTAS%") == 0) {
- while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {
+ while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) {
pmdelta_t *delta = _alpm_delta_parse(line);
if(delta) {
info->deltas = alpm_list_add(info->deltas, delta);
diff --git a/lib/libalpm/be_package.c b/lib/libalpm/be_package.c
index 9c7c1617..c1a43438 100644
--- a/lib/libalpm/be_package.c
+++ b/lib/libalpm/be_package.c
@@ -82,7 +82,7 @@ static int parse_descfile(struct archive *a, pmpkg_t *newpkg)
} else if(!strcmp(key, "license")) {
newpkg->licenses = alpm_list_add(newpkg->licenses, strdup(ptr));
} else if(!strcmp(key, "builddate")) {
- char first = tolower(ptr[0]);
+ char first = tolower((unsigned char)ptr[0]);
if(first > 'a' && first < 'z') {
struct tm tmp_tm = {0}; /* initialize to null in case of failure */
setlocale(LC_TIME, "C");
@@ -132,7 +132,7 @@ static int parse_descfile(struct archive *a, pmpkg_t *newpkg)
* through the full archive
* @return An information filled pmpkg_t struct
*/
-static pmpkg_t *pkg_load(const char *pkgfile, unsigned short full)
+static pmpkg_t *pkg_load(const char *pkgfile, int full)
{
int ret = ARCHIVE_OK;
int config = 0;
@@ -269,8 +269,7 @@ error:
* @param pkg address of the package pointer
* @return 0 on success, -1 on error (pm_errno is set accordingly)
*/
-int SYMEXPORT alpm_pkg_load(const char *filename, unsigned short full,
- pmpkg_t **pkg)
+int SYMEXPORT alpm_pkg_load(const char *filename, int full, pmpkg_t **pkg)
{
ALPM_LOG_FUNC;
diff --git a/lib/libalpm/conflict.c b/lib/libalpm/conflict.c
index 07ef73cf..e934c01e 100644
--- a/lib/libalpm/conflict.c
+++ b/lib/libalpm/conflict.c
@@ -41,7 +41,7 @@
#include "cache.h"
#include "deps.h"
-pmconflict_t *_alpm_conflict_new(const char *package1, const char *package2)
+pmconflict_t *_alpm_conflict_new(const char *package1, const char *package2, const char *reason)
{
pmconflict_t *conflict;
@@ -51,6 +51,7 @@ pmconflict_t *_alpm_conflict_new(const char *package1, const char *package2)
STRDUP(conflict->package1, package1, RET_ERR(PM_ERR_MEMORY, NULL));
STRDUP(conflict->package2, package2, RET_ERR(PM_ERR_MEMORY, NULL));
+ STRDUP(conflict->reason, reason, RET_ERR(PM_ERR_MEMORY, NULL));
return(conflict);
}
@@ -59,6 +60,7 @@ void _alpm_conflict_free(pmconflict_t *conflict)
{
FREE(conflict->package2);
FREE(conflict->package1);
+ FREE(conflict->reason);
FREE(conflict);
}
@@ -69,6 +71,7 @@ pmconflict_t *_alpm_conflict_dup(const pmconflict_t *conflict)
STRDUP(newconflict->package1, conflict->package1, RET_ERR(PM_ERR_MEMORY, NULL));
STRDUP(newconflict->package2, conflict->package2, RET_ERR(PM_ERR_MEMORY, NULL));
+ STRDUP(newconflict->reason, conflict->reason, RET_ERR(PM_ERR_MEMORY, NULL));
return(newconflict);
}
@@ -122,9 +125,9 @@ static int does_conflict(pmpkg_t *pkg1, const char *conflict, pmpkg_t *pkg2)
* @param pkg2 package causing conflict
*/
static void add_conflict(alpm_list_t **baddeps, const char *pkg1,
- const char *pkg2)
+ const char *pkg2, const char *reason)
{
- pmconflict_t *conflict = _alpm_conflict_new(pkg1, pkg2);
+ pmconflict_t *conflict = _alpm_conflict_new(pkg1, pkg2, reason);
if(conflict && !_alpm_conflict_isin(conflict, *baddeps)) {
*baddeps = alpm_list_add(*baddeps, conflict);
} else {
@@ -168,9 +171,9 @@ static void check_conflict(alpm_list_t *list1, alpm_list_t *list2,
if(does_conflict(pkg1, conflict, pkg2)) {
if(order >= 0) {
- add_conflict(baddeps, pkg1name, pkg2name);
+ add_conflict(baddeps, pkg1name, pkg2name, conflict);
} else {
- add_conflict(baddeps, pkg2name, pkg1name);
+ add_conflict(baddeps, pkg2name, pkg1name, conflict);
}
}
}
@@ -513,7 +516,7 @@ alpm_list_t *_alpm_db_find_fileconflicts(pmdb_t *db, pmtrans_t *trans,
/* skip removal of file, but not add. this will prevent a second
* package from removing the file when it was already installed
* by its new owner (whether the file is in backup array or not */
- trans->skip_remove = alpm_list_add(trans->skip_remove, strdup(path));
+ trans->skip_remove = alpm_list_add(trans->skip_remove, strdup(filestr));
_alpm_log(PM_LOG_DEBUG, "file changed packages, adding to remove skiplist: %s\n", filestr);
resolved_conflict = 1;
}
@@ -578,6 +581,17 @@ const char SYMEXPORT *alpm_conflict_get_package2(pmconflict_t *conflict)
return conflict->package2;
}
+const char SYMEXPORT *alpm_conflict_get_reason(pmconflict_t *conflict)
+{
+ ALPM_LOG_FUNC;
+
+ /* Sanity checks */
+ ASSERT(handle != NULL, return(NULL));
+ ASSERT(conflict != NULL, return(NULL));
+
+ return conflict->reason;
+}
+
const char SYMEXPORT *alpm_fileconflict_get_target(pmfileconflict_t *conflict)
{
ALPM_LOG_FUNC;
diff --git a/lib/libalpm/conflict.h b/lib/libalpm/conflict.h
index 149c728e..73a6e959 100644
--- a/lib/libalpm/conflict.h
+++ b/lib/libalpm/conflict.h
@@ -27,6 +27,7 @@
struct __pmconflict_t {
char *package1;
char *package2;
+ char *reason;
};
struct __pmfileconflict_t {
@@ -36,7 +37,7 @@ struct __pmfileconflict_t {
char *ctarget;
};
-pmconflict_t *_alpm_conflict_new(const char *package1, const char *package2);
+pmconflict_t *_alpm_conflict_new(const char *package1, const char *package2, const char *reason);
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);
diff --git a/lib/libalpm/db.c b/lib/libalpm/db.c
index 62c2e0a3..dca5452a 100644
--- a/lib/libalpm/db.c
+++ b/lib/libalpm/db.c
@@ -323,18 +323,15 @@ alpm_list_t SYMEXPORT *alpm_db_search(pmdb_t *db, const alpm_list_t* needles)
/** @} */
-pmdb_t *_alpm_db_new(const char *dbpath, const char *treename)
+static pmdb_t *_alpm_db_new(const char *treename, int is_local)
{
pmdb_t *db;
- const size_t pathsize = strlen(dbpath) + strlen(treename) + 2;
ALPM_LOG_FUNC;
CALLOC(db, 1, sizeof(pmdb_t), RET_ERR(PM_ERR_MEMORY, NULL));
- CALLOC(db->path, 1, pathsize, RET_ERR(PM_ERR_MEMORY, NULL));
-
- sprintf(db->path, "%s%s/", dbpath, treename);
STRDUP(db->treename, treename, RET_ERR(PM_ERR_MEMORY, NULL));
+ db->is_local = is_local;
return(db);
}
@@ -347,13 +344,44 @@ void _alpm_db_free(pmdb_t *db)
_alpm_db_free_pkgcache(db);
/* cleanup server list */
FREELIST(db->servers);
- FREE(db->path);
+ FREE(db->_path);
FREE(db->treename);
FREE(db);
return;
}
+const char *_alpm_db_path(pmdb_t *db)
+{
+ if(!db) {
+ return(NULL);
+ }
+ if(!db->_path) {
+ const char *dbpath;
+ size_t pathsize;
+
+ dbpath = alpm_option_get_dbpath();
+ if(!dbpath) {
+ _alpm_log(PM_LOG_ERROR, _("database path is undefined\n"));
+ RET_ERR(PM_ERR_DB_OPEN, NULL);
+ }
+
+ if(db->is_local) {
+ pathsize = strlen(dbpath) + strlen(db->treename) + 2;
+ CALLOC(db->_path, 1, pathsize, RET_ERR(PM_ERR_MEMORY, NULL));
+ sprintf(db->_path, "%s%s/", dbpath, db->treename);
+ } else {
+ pathsize = strlen(dbpath) + 5 + strlen(db->treename) + 2;
+ CALLOC(db->_path, 1, pathsize, RET_ERR(PM_ERR_MEMORY, NULL));
+ /* all sync DBs now reside in the sync/ subdir of the dbpath */
+ sprintf(db->_path, "%ssync/%s/", dbpath, db->treename);
+ }
+ _alpm_log(PM_LOG_DEBUG, "database path for tree %s set to %s\n",
+ db->treename, db->_path);
+ }
+ return(db->_path);
+}
+
int _alpm_db_cmp(const void *d1, const void *d2)
{
pmdb_t *db1 = (pmdb_t *)d1;
@@ -440,7 +468,6 @@ alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles)
pmdb_t *_alpm_db_register_local(void)
{
pmdb_t *db;
- const char *dbpath;
ALPM_LOG_FUNC;
@@ -451,13 +478,7 @@ pmdb_t *_alpm_db_register_local(void)
_alpm_log(PM_LOG_DEBUG, "registering local database\n");
- dbpath = alpm_option_get_dbpath();
- if(!dbpath) {
- _alpm_log(PM_LOG_ERROR, _("database path is undefined\n"));
- RET_ERR(PM_ERR_DB_OPEN, NULL);
- }
-
- db = _alpm_db_new(dbpath, "local");
+ db = _alpm_db_new("local", 1);
if(db == NULL) {
RET_ERR(PM_ERR_DB_CREATE, NULL);
}
@@ -469,8 +490,6 @@ pmdb_t *_alpm_db_register_local(void)
pmdb_t *_alpm_db_register_sync(const char *treename)
{
pmdb_t *db;
- const char *dbpath;
- char path[PATH_MAX];
alpm_list_t *i;
ALPM_LOG_FUNC;
@@ -485,15 +504,7 @@ pmdb_t *_alpm_db_register_sync(const char *treename)
_alpm_log(PM_LOG_DEBUG, "registering sync database '%s'\n", treename);
- dbpath = alpm_option_get_dbpath();
- if(!dbpath) {
- _alpm_log(PM_LOG_ERROR, _("database path is undefined\n"));
- RET_ERR(PM_ERR_DB_OPEN, NULL);
- }
- /* all sync DBs now reside in the sync/ subdir of the dbpath */
- snprintf(path, PATH_MAX, "%ssync/", dbpath);
-
- db = _alpm_db_new(path, treename);
+ db = _alpm_db_new(treename, 0);
if(db == NULL) {
RET_ERR(PM_ERR_DB_CREATE, NULL);
}
diff --git a/lib/libalpm/db.h b/lib/libalpm/db.h
index 950ace22..a540d02d 100644
--- a/lib/libalpm/db.h
+++ b/lib/libalpm/db.h
@@ -28,30 +28,32 @@
/* Database entries */
typedef enum _pmdbinfrq_t {
- INFRQ_BASE = 0x01,
- INFRQ_DESC = 0x02,
- INFRQ_DEPENDS = 0x04,
- INFRQ_FILES = 0x08,
- INFRQ_SCRIPTLET = 0x10,
- INFRQ_DELTAS = 0x20,
+ INFRQ_BASE = 1,
+ INFRQ_DESC = (1 << 1),
+ INFRQ_DEPENDS = (1 << 2),
+ INFRQ_FILES = (1 << 3),
+ INFRQ_SCRIPTLET = (1 << 4),
+ INFRQ_DELTAS = (1 << 5),
/* ALL should be sum of all above */
INFRQ_ALL = 0x3F
} pmdbinfrq_t;
/* Database */
struct __pmdb_t {
- char *path;
char *treename;
- unsigned short pkgcache_loaded;
+ /* do not access directly, use _alpm_db_path(db) for lazy access */
+ char *_path;
+ int pkgcache_loaded;
+ int grpcache_loaded;
+ int is_local;
alpm_list_t *pkgcache;
- unsigned short grpcache_loaded;
alpm_list_t *grpcache;
alpm_list_t *servers;
};
/* db.c, database general calls */
-pmdb_t *_alpm_db_new(const char *dbpath, const char *treename);
void _alpm_db_free(pmdb_t *db);
+const char *_alpm_db_path(pmdb_t *db);
int _alpm_db_cmp(const void *d1, const void *d2);
alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles);
pmdb_t *_alpm_db_register_local(void);
diff --git a/lib/libalpm/delta.c b/lib/libalpm/delta.c
index 599a1b76..523968ec 100644
--- a/lib/libalpm/delta.c
+++ b/lib/libalpm/delta.c
@@ -71,34 +71,16 @@ off_t SYMEXPORT alpm_delta_get_size(pmdelta_t *delta)
/** @} */
-static alpm_list_t *delta_graph_init(alpm_list_t *deltas)
+static alpm_list_t *graph_init(alpm_list_t *deltas)
{
alpm_list_t *i, *j;
alpm_list_t *vertices = NULL;
/* create the vertices */
for(i = deltas; i; i = i->next) {
- char *fpath, *md5sum;
pmgraph_t *v = _alpm_graph_new();
pmdelta_t *vdelta = i->data;
vdelta->download_size = vdelta->delta_size;
v->weight = LONG_MAX;
-
- /* determine whether the delta file already exists */
- fpath = _alpm_filecache_find(vdelta->delta);
- md5sum = alpm_compute_md5sum(fpath);
- if(fpath && md5sum && strcmp(md5sum, vdelta->delta_md5) == 0) {
- vdelta->download_size = 0;
- }
- FREE(fpath);
- FREE(md5sum);
-
- /* determine whether a base 'from' file exists */
- fpath = _alpm_filecache_find(vdelta->from);
- if(fpath) {
- v->weight = vdelta->download_size;
- }
- FREE(fpath);
-
v->data = vdelta;
vertices = alpm_list_add(vertices, v);
}
@@ -128,8 +110,36 @@ static alpm_list_t *delta_graph_init(alpm_list_t *deltas)
return(vertices);
}
-static off_t delta_vert(alpm_list_t *vertices,
- const char *to, alpm_list_t **path) {
+static void graph_init_size(alpm_list_t *vertices)
+{
+ alpm_list_t *i;
+
+ for(i = vertices; i; i = i->next) {
+ char *fpath, *md5sum;
+ pmgraph_t *v = i->data;
+ pmdelta_t *vdelta = v->data;
+
+ /* determine whether the delta file already exists */
+ fpath = _alpm_filecache_find(vdelta->delta);
+ md5sum = alpm_compute_md5sum(fpath);
+ if(fpath && md5sum && strcmp(md5sum, vdelta->delta_md5) == 0) {
+ vdelta->download_size = 0;
+ }
+ FREE(fpath);
+ FREE(md5sum);
+
+ /* determine whether a base 'from' file exists */
+ fpath = _alpm_filecache_find(vdelta->from);
+ if(fpath) {
+ v->weight = vdelta->download_size;
+ }
+ FREE(fpath);
+ }
+}
+
+
+static void dijkstra(alpm_list_t *vertices)
+{
alpm_list_t *i;
pmgraph_t *v;
while(1) {
@@ -165,9 +175,14 @@ static off_t delta_vert(alpm_list_t *vertices,
}
}
+}
- v = NULL;
+static off_t shortest_path(alpm_list_t *vertices, const char *to, alpm_list_t **path)
+{
+ alpm_list_t *i;
+ pmgraph_t *v = NULL;
off_t bestsize = 0;
+ alpm_list_t *rpath = NULL;
for(i = vertices; i; i = i->next) {
pmgraph_t *v_i = i->data;
@@ -181,7 +196,6 @@ static off_t delta_vert(alpm_list_t *vertices,
}
}
- alpm_list_t *rpath = NULL;
while(v != NULL) {
pmdelta_t *vdelta = v->data;
rpath = alpm_list_add(rpath, vdelta);
@@ -219,9 +233,10 @@ off_t _alpm_shortest_delta_path(alpm_list_t *deltas,
_alpm_log(PM_LOG_DEBUG, "started delta shortest-path search for '%s'\n", to);
- vertices = delta_graph_init(deltas);
-
- bestsize = delta_vert(vertices, to, &bestpath);
+ vertices = graph_init(deltas);
+ graph_init_size(vertices);
+ dijkstra(vertices);
+ bestsize = shortest_path(vertices, to, &bestpath);
_alpm_log(PM_LOG_DEBUG, "delta shortest-path search complete : '%jd'\n", (intmax_t)bestsize);
diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c
index 02a4c7b6..46699ac6 100644
--- a/lib/libalpm/deps.c
+++ b/lib/libalpm/deps.c
@@ -605,7 +605,7 @@ int _alpm_resolvedeps(pmdb_t *local, alpm_list_t *dbs_sync, pmpkg_t *pkg,
ALPM_LOG_FUNC;
- if(local == NULL || dbs_sync == NULL) {
+ if(local == NULL) {
return(-1);
}
diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c
index 10be5e9d..6bf9b4db 100644
--- a/lib/libalpm/dload.c
+++ b/lib/libalpm/dload.c
@@ -25,6 +25,9 @@
#include <errno.h>
#include <string.h>
#include <unistd.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
#include <signal.h>
#include <limits.h>
/* the following two are needed on BSD for libfetch */
@@ -59,7 +62,7 @@ static char *get_filename(const char *url) {
static char *get_destfile(const char *path, const char *filename) {
char *destfile;
/* len = localpath len + filename len + null */
- int len = strlen(path) + strlen(filename) + 1;
+ size_t len = strlen(path) + strlen(filename) + 1;
CALLOC(destfile, len, sizeof(char), RET_ERR(PM_ERR_MEMORY, NULL));
snprintf(destfile, len, "%s%s", path, filename);
@@ -69,37 +72,13 @@ static char *get_destfile(const char *path, const char *filename) {
static char *get_tempfile(const char *path, const char *filename) {
char *tempfile;
/* len = localpath len + filename len + '.part' len + null */
- int len = strlen(path) + strlen(filename) + 6;
+ size_t len = strlen(path) + strlen(filename) + 6;
CALLOC(tempfile, len, sizeof(char), RET_ERR(PM_ERR_MEMORY, NULL));
snprintf(tempfile, len, "%s%s.part", path, filename);
return(tempfile);
}
-/* Build a 'struct url' from an url. */
-static struct url *url_for_string(const char *url)
-{
- struct url *ret = NULL;
- ret = fetchParseURL(url);
- if(!ret) {
- _alpm_log(PM_LOG_ERROR, _("url '%s' is invalid\n"), url);
- RET_ERR(PM_ERR_SERVER_BAD_URL, NULL);
- }
-
- /* if no URL scheme specified, assume HTTP */
- if(strlen(ret->scheme) == 0) {
- _alpm_log(PM_LOG_WARNING, _("url scheme not specified, assuming HTTP\n"));
- strcpy(ret->scheme, SCHEME_HTTP);
- }
- /* add a user & password for anonymous FTP */
- if(strcmp(ret->scheme,SCHEME_FTP) == 0 && strlen(ret->user) == 0) {
- strcpy(ret->user, "anonymous");
- strcpy(ret->pwd, "libalpm@guest");
- }
-
- return(ret);
-}
-
static const char *gethost(struct url *fileurl)
{
const char *host = _("disk");
@@ -109,75 +88,126 @@ static const char *gethost(struct url *fileurl)
return(host);
}
+int dload_interrupted;
+static RETSIGTYPE inthandler(int signum)
+{
+ dload_interrupted = 1;
+}
+
+#define check_stop() if(dload_interrupted) { ret = -1; goto cleanup; }
+enum sighandlers { OLD = 0, NEW = 1 };
+
static int download_internal(const char *url, const char *localpath,
- time_t mtimeold, time_t *mtimenew) {
- fetchIO *dlf = NULL;
+ int force) {
FILE *localf = NULL;
- struct url_stat ust;
struct stat st;
- int chk_resume = 0, ret = 0;
- size_t dl_thisfile = 0;
+ int ret = 0;
+ off_t dl_thisfile = 0;
ssize_t nread = 0;
char *tempfile, *destfile, *filename;
- struct sigaction new_action, old_action;
- struct url *fileurl = url_for_string(url);
- char buffer[PM_DLBUF_LEN];
+ struct sigaction sig_pipe[2], sig_int[2];
- if(!fileurl) {
- return(-1);
- }
+ off_t local_size = 0;
+ time_t local_time = 0;
+
+ struct url *fileurl;
+ struct url_stat ust;
+ fetchIO *dlf = NULL;
+
+ char buffer[PM_DLBUF_LEN];
filename = get_filename(url);
if(!filename) {
- return(-1);
+ _alpm_log(PM_LOG_ERROR, _("url '%s' is invalid\n"), url);
+ RET_ERR(PM_ERR_SERVER_BAD_URL, -1);
}
- destfile = get_destfile(localpath, filename);
- tempfile = get_tempfile(localpath, filename);
- if(mtimeold) {
- fileurl->last_modified = mtimeold;
+ fileurl = fetchParseURL(url);
+ if(!fileurl) {
+ _alpm_log(PM_LOG_ERROR, _("url '%s' is invalid\n"), url);
+ RET_ERR(PM_ERR_LIBFETCH, -1);
}
- /* pass the raw filename for passing to the callback function */
- _alpm_log(PM_LOG_DEBUG, "using '%s' for download progress\n", filename);
+ destfile = get_destfile(localpath, filename);
+ tempfile = get_tempfile(localpath, filename);
if(stat(tempfile, &st) == 0 && st.st_size > 0) {
- _alpm_log(PM_LOG_DEBUG, "existing file found, using it\n");
- fileurl->offset = (off_t)st.st_size;
+ _alpm_log(PM_LOG_DEBUG, "tempfile found, attempting continuation\n");
+ local_time = fileurl->last_modified = st.st_mtime;
+ local_size = fileurl->offset = (off_t)st.st_size;
dl_thisfile = st.st_size;
localf = fopen(tempfile, "ab");
- chk_resume = 1;
+ } else if(!force && stat(destfile, &st) == 0 && st.st_size > 0) {
+ _alpm_log(PM_LOG_DEBUG, "destfile found, using mtime only\n");
+ local_time = fileurl->last_modified = st.st_mtime;
+ local_size = /* no fu->off here */ (off_t)st.st_size;
} else {
- fileurl->offset = (off_t)0;
- dl_thisfile = 0;
+ _alpm_log(PM_LOG_DEBUG, "no file found matching criteria, starting from scratch\n");
}
+ /* pass the raw filename for passing to the callback function */
+ _alpm_log(PM_LOG_DEBUG, "using '%s' for download progress\n", filename);
+
/* print proxy info for debug purposes */
_alpm_log(PM_LOG_DEBUG, "HTTP_PROXY: %s\n", getenv("HTTP_PROXY"));
_alpm_log(PM_LOG_DEBUG, "http_proxy: %s\n", getenv("http_proxy"));
_alpm_log(PM_LOG_DEBUG, "FTP_PROXY: %s\n", getenv("FTP_PROXY"));
_alpm_log(PM_LOG_DEBUG, "ftp_proxy: %s\n", getenv("ftp_proxy"));
- /* libfetch does not reset the error code */
- fetchLastErrCode = 0;
-
/* 10s timeout */
fetchTimeout = 10;
/* ignore any SIGPIPE signals- these may occur if our FTP socket dies or
* something along those lines. Store the old signal handler first. */
- new_action.sa_handler = SIG_IGN;
- sigemptyset(&new_action.sa_mask);
- sigaction(SIGPIPE, NULL, &old_action);
- sigaction(SIGPIPE, &new_action, NULL);
-
- dlf = fetchXGet(fileurl, &ust, (handle->nopassiveftp ? "i" : "pi"));
-
- if(fetchLastErrCode == FETCH_UNCHANGED) {
- _alpm_log(PM_LOG_DEBUG, "mtimes are identical, skipping %s\n", filename);
+ sig_pipe[NEW].sa_handler = SIG_IGN;
+ sigemptyset(&sig_pipe[NEW].sa_mask);
+ sig_pipe[NEW].sa_flags = 0;
+ sigaction(SIGPIPE, NULL, &sig_pipe[OLD]);
+ sigaction(SIGPIPE, &sig_pipe[NEW], NULL);
+
+ dload_interrupted = 0;
+ sig_int[NEW].sa_handler = &inthandler;
+ sigemptyset(&sig_int[NEW].sa_mask);
+ sig_int[NEW].sa_flags = 0;
+ sigaction(SIGINT, NULL, &sig_int[OLD]);
+ sigaction(SIGINT, &sig_int[NEW], NULL);
+
+ /* NOTE: libfetch does not reset the error code, be sure to do it before
+ * calls into the library */
+
+ /* find out the remote size *and* mtime in one go. there is a lot of
+ * trouble in trying to do both size and "if-modified-since" logic in a
+ * non-stat request, so avoid it. */
+ fetchLastErrCode = 0;
+ if(fetchStat(fileurl, &ust, "") == -1) {
+ pm_errno = PM_ERR_LIBFETCH;
+ _alpm_log(PM_LOG_ERROR, _("failed retrieving file '%s' from %s : %s\n"),
+ filename, gethost(fileurl), fetchLastErrString);
+ ret = -1;
+ goto cleanup;
+ }
+ check_stop();
+
+ _alpm_log(PM_LOG_DEBUG, "ust.mtime: %ld local_time: %ld compare: %ld\n",
+ ust.mtime, local_time, local_time - ust.mtime);
+ _alpm_log(PM_LOG_DEBUG, "ust.size: %"PRId64" local_size: %"PRId64" compare: %"PRId64"\n",
+ ust.size, local_size, local_size - ust.size);
+ if(!force && ust.mtime && ust.mtime == local_time
+ && ust.size && ust.size == local_size) {
+ /* the remote time and size values agreed with what we have, so move on
+ * because there is nothing more to do. */
+ _alpm_log(PM_LOG_DEBUG, "files are identical, skipping %s\n", filename);
ret = 1;
goto cleanup;
}
+ if(!ust.mtime || ust.mtime != local_time) {
+ _alpm_log(PM_LOG_DEBUG, "mtimes were different or unavailable, downloading %s from beginning\n", filename);
+ fileurl->offset = 0;
+ }
+
+ fetchLastErrCode = 0;
+ dlf = fetchGet(fileurl, "");
+ check_stop();
if(fetchLastErrCode != 0 || dlf == NULL) {
pm_errno = PM_ERR_LIBFETCH;
@@ -189,17 +219,14 @@ static int download_internal(const char *url, const char *localpath,
_alpm_log(PM_LOG_DEBUG, "connected to %s successfully\n", fileurl->host);
}
- if(ust.mtime && mtimenew) {
- *mtimenew = ust.mtime;
+ if(localf && fileurl->offset == 0) {
+ _alpm_log(PM_LOG_WARNING, _("resuming download of %s not possible; starting over\n"), filename);
+ fclose(localf);
+ localf = NULL;
+ } else if(fileurl->offset) {
+ _alpm_log(PM_LOG_DEBUG, "resuming download at position %"PRId64"\n", fileurl->offset);
}
- if(chk_resume && fileurl->offset == 0) {
- _alpm_log(PM_LOG_WARNING, _("cannot resume download, starting over\n"));
- if(localf != NULL) {
- fclose(localf);
- localf = NULL;
- }
- }
if(localf == NULL) {
_alpm_rmrf(tempfile);
@@ -207,7 +234,9 @@ static int download_internal(const char *url, const char *localpath,
dl_thisfile = 0;
localf = fopen(tempfile, "wb");
if(localf == NULL) { /* still null? */
- _alpm_log(PM_LOG_ERROR, _("cannot write to file '%s'\n"), tempfile);
+ pm_errno = PM_ERR_RETRIEVE;
+ _alpm_log(PM_LOG_ERROR, _("error writing to file '%s': %s\n"),
+ tempfile, strerror(errno));
ret = -1;
goto cleanup;
}
@@ -219,15 +248,15 @@ static int download_internal(const char *url, const char *localpath,
}
while((nread = fetchIO_read(dlf, buffer, PM_DLBUF_LEN)) > 0) {
+ check_stop();
size_t nwritten = 0;
- while(nwritten < nread) {
- nwritten += fwrite(buffer, 1, (nread - nwritten), localf);
- if(ferror(localf)) {
- _alpm_log(PM_LOG_ERROR, _("error writing to file '%s': %s\n"),
- destfile, strerror(errno));
- ret = -1;
- goto cleanup;
- }
+ nwritten = fwrite(buffer, 1, nread, localf);
+ if((nwritten != nread) || ferror(localf)) {
+ pm_errno = PM_ERR_RETRIEVE;
+ _alpm_log(PM_LOG_ERROR, _("error writing to file '%s': %s\n"),
+ tempfile, strerror(errno));
+ ret = -1;
+ goto cleanup;
}
dl_thisfile += nread;
@@ -262,36 +291,60 @@ static int download_internal(const char *url, const char *localpath,
fetchIO_close(dlf);
dlf = NULL;
+ /* set the times on the file to the same as that of the remote file */
+ if(ust.mtime) {
+ struct timeval tv[2];
+ memset(&tv, 0, sizeof(tv));
+ tv[0].tv_sec = ust.atime;
+ tv[1].tv_sec = ust.mtime;
+ utimes(tempfile, tv);
+ }
rename(tempfile, destfile);
ret = 0;
cleanup:
- /* restore any existing SIGPIPE signal handler */
- sigaction(SIGPIPE, &old_action, NULL);
-
FREE(tempfile);
FREE(destfile);
if(localf != NULL) {
+ /* if we still had a local file open, we got interrupted. set the mtimes on
+ * the file accordingly. */
+ fflush(localf);
+ if(ust.mtime) {
+ struct timeval tv[2];
+ memset(&tv, 0, sizeof(tv));
+ tv[0].tv_sec = ust.atime;
+ tv[1].tv_sec = ust.mtime;
+ futimes(fileno(localf), tv);
+ }
fclose(localf);
}
if(dlf != NULL) {
fetchIO_close(dlf);
}
fetchFreeURL(fileurl);
+
+ /* restore the old signal handlers */
+ sigaction(SIGINT, &sig_int[OLD], NULL);
+ sigaction(SIGPIPE, &sig_pipe[OLD], NULL);
+ /* if we were interrupted, trip the old handler */
+ if(dload_interrupted) {
+ raise(SIGINT);
+ }
+
return(ret);
}
#endif
static int download(const char *url, const char *localpath,
- time_t mtimeold, time_t *mtimenew) {
+ int force) {
if(handle->fetchcb == NULL) {
#if defined(INTERNAL_DOWNLOAD)
- return(download_internal(url, localpath, mtimeold, mtimenew));
+ return(download_internal(url, localpath, force));
#else
RET_ERR(PM_ERR_EXTERNAL_DOWNLOAD, -1);
#endif
} else {
- int ret = handle->fetchcb(url, localpath, mtimeold, mtimenew);
+ int ret = handle->fetchcb(url, localpath, force);
if(ret == -1) {
RET_ERR(PM_ERR_EXTERNAL_DOWNLOAD, -1);
}
@@ -301,19 +354,15 @@ static int download(const char *url, const char *localpath,
/*
* Download a single file
- * - if mtimeold is non-NULL, then only download the file if it's different
- * than mtimeold.
- * - if *mtimenew is non-NULL, it will be filled with the mtime of the remote
- * file.
* - servers must be a list of urls WITHOUT trailing slashes.
*
* RETURN: 0 for successful download
- * 1 if the mtimes are identical
+ * 1 if the files are identical
* -1 on error
*/
int _alpm_download_single_file(const char *filename,
alpm_list_t *servers, const char *localpath,
- time_t mtimeold, time_t *mtimenew)
+ int force)
{
alpm_list_t *i;
int ret = -1;
@@ -323,14 +372,14 @@ int _alpm_download_single_file(const char *filename,
for(i = servers; i; i = i->next) {
const char *server = i->data;
char *fileurl = NULL;
- int len;
+ size_t len;
/* print server + filename into a buffer */
len = strlen(server) + strlen(filename) + 2;
CALLOC(fileurl, len, sizeof(char), RET_ERR(PM_ERR_MEMORY, -1));
snprintf(fileurl, len, "%s/%s", server, filename);
- ret = download(fileurl, localpath, mtimeold, mtimenew);
+ ret = download(fileurl, localpath, force);
FREE(fileurl);
if(ret != -1) {
break;
@@ -349,7 +398,7 @@ int _alpm_download_files(alpm_list_t *files,
for(lp = files; lp; lp = lp->next) {
char *filename = lp->data;
if(_alpm_download_single_file(filename, servers,
- localpath, 0, NULL) == -1) {
+ localpath, 0) == -1) {
ret++;
}
}
@@ -376,7 +425,7 @@ char SYMEXPORT *alpm_fetch_pkgurl(const char *url)
cachedir = _alpm_filecache_setup();
/* download the file */
- ret = download(url, cachedir, 0, NULL);
+ ret = download(url, cachedir, 0);
if(ret == -1) {
_alpm_log(PM_LOG_WARNING, _("failed to download %s\n"), url);
return(NULL);
diff --git a/lib/libalpm/dload.h b/lib/libalpm/dload.h
index 64b57d27..ee800244 100644
--- a/lib/libalpm/dload.h
+++ b/lib/libalpm/dload.h
@@ -25,11 +25,11 @@
#include <time.h>
-#define PM_DLBUF_LEN (1024 * 10)
+#define PM_DLBUF_LEN (1024 * 16)
int _alpm_download_single_file(const char *filename,
alpm_list_t *servers, const char *localpath,
- time_t mtimeold, time_t *mtimenew);
+ int force);
int _alpm_download_files(alpm_list_t *files,
alpm_list_t *servers, const char *localpath);
diff --git a/lib/libalpm/error.c b/lib/libalpm/error.c
index 81aaa8b1..ae19786e 100644
--- a/lib/libalpm/error.c
+++ b/lib/libalpm/error.c
@@ -117,8 +117,10 @@ const char SYMEXPORT *alpm_strerror(int err)
return _("cannot remove all files for package");
case PM_ERR_PKG_INVALID_NAME:
return _("package filename is not valid");
+ case PM_ERR_PKG_INVALID_ARCH:
+ return _("package architecture is not valid");
case PM_ERR_PKG_REPO_NOT_FOUND:
- return _("no such repository");
+ return _("could not find repository for target");
/* Deltas */
case PM_ERR_DLT_INVALID:
return _("invalid or corrupted delta");
diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c
index d1a35ad9..5cbf363a 100644
--- a/lib/libalpm/handle.c
+++ b/lib/libalpm/handle.c
@@ -79,6 +79,7 @@ void _alpm_handle_free(pmhandle_t *handle)
FREELIST(handle->cachedirs);
FREE(handle->logfile);
FREE(handle->lockfile);
+ FREE(handle->arch);
FREELIST(handle->dbs_sync);
FREELIST(handle->noupgrade);
FREELIST(handle->noextract);
@@ -168,7 +169,7 @@ const char SYMEXPORT *alpm_option_get_lockfile()
return handle->lockfile;
}
-unsigned short SYMEXPORT alpm_option_get_usesyslog()
+int SYMEXPORT alpm_option_get_usesyslog()
{
if (handle == NULL) {
pm_errno = PM_ERR_HANDLE_NULL;
@@ -213,13 +214,22 @@ alpm_list_t SYMEXPORT *alpm_option_get_ignoregrps()
return handle->ignoregrp;
}
-unsigned short SYMEXPORT alpm_option_get_nopassiveftp()
+const char SYMEXPORT *alpm_option_get_arch()
+{
+ if (handle == NULL) {
+ pm_errno = PM_ERR_HANDLE_NULL;
+ return NULL;
+ }
+ return handle->arch;
+}
+
+int SYMEXPORT alpm_option_get_usedelta()
{
if (handle == NULL) {
pm_errno = PM_ERR_HANDLE_NULL;
return -1;
}
- return handle->nopassiveftp;
+ return handle->usedelta;
}
pmdb_t SYMEXPORT *alpm_option_get_localdb()
@@ -436,7 +446,7 @@ int SYMEXPORT alpm_option_set_logfile(const char *logfile)
return(0);
}
-void SYMEXPORT alpm_option_set_usesyslog(unsigned short usesyslog)
+void SYMEXPORT alpm_option_set_usesyslog(int usesyslog)
{
handle->usesyslog = usesyslog;
}
@@ -529,12 +539,13 @@ int SYMEXPORT alpm_option_remove_ignoregrp(const char *grp)
return(0);
}
-void SYMEXPORT alpm_option_set_nopassiveftp(unsigned short nopasv)
+void SYMEXPORT alpm_option_set_arch(const char *arch)
{
- handle->nopassiveftp = nopasv;
+ if(handle->arch) FREE(handle->arch);
+ if(arch) handle->arch = strdup(arch);
}
-void SYMEXPORT alpm_option_set_usedelta(unsigned short usedelta)
+void SYMEXPORT alpm_option_set_usedelta(int usedelta)
{
handle->usedelta = usedelta;
}
diff --git a/lib/libalpm/handle.h b/lib/libalpm/handle.h
index c7c262cf..a87d0fb2 100644
--- a/lib/libalpm/handle.h
+++ b/lib/libalpm/handle.h
@@ -57,9 +57,9 @@ typedef struct _pmhandle_t {
alpm_list_t *ignoregrp; /* List of groups to ignore */
/* options */
- unsigned short usesyslog; /* Use syslog instead of logfile? */ /* TODO move to frontend */
- unsigned short nopassiveftp; /* Don't use PASV ftp connections */
- unsigned short usedelta; /* Download deltas if possible */
+ int usesyslog; /* Use syslog instead of logfile? */ /* TODO move to frontend */
+ char *arch; /* Architecture of packages we should allow */
+ int usedelta; /* Download deltas if possible */
} pmhandle_t;
/* global handle variable */
diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c
index 002b1c89..4ff04dab 100644
--- a/lib/libalpm/package.c
+++ b/lib/libalpm/package.c
@@ -295,7 +295,7 @@ alpm_list_t SYMEXPORT *alpm_pkg_get_groups(pmpkg_t *pkg)
return pkg->groups;
}
-unsigned short SYMEXPORT alpm_pkg_has_force(pmpkg_t *pkg)
+int SYMEXPORT alpm_pkg_has_force(pmpkg_t *pkg)
{
ALPM_LOG_FUNC;
@@ -423,13 +423,6 @@ alpm_list_t SYMEXPORT *alpm_pkg_get_backup(pmpkg_t *pkg)
return pkg->backup;
}
-alpm_list_t SYMEXPORT *alpm_pkg_get_removes(pmpkg_t *pkg)
-{
- ASSERT(pkg != NULL, return(NULL));
-
- return(pkg->removes);
-}
-
pmdb_t SYMEXPORT *alpm_pkg_get_db(pmpkg_t *pkg)
{
/* Sanity checks */
@@ -548,7 +541,7 @@ int SYMEXPORT alpm_pkg_changelog_close(const pmpkg_t *pkg, void *fp)
return(ret);
}
-unsigned short SYMEXPORT alpm_pkg_has_scriptlet(pmpkg_t *pkg)
+int SYMEXPORT alpm_pkg_has_scriptlet(pmpkg_t *pkg)
{
ALPM_LOG_FUNC;
@@ -580,7 +573,7 @@ alpm_list_t SYMEXPORT *alpm_pkg_compute_requiredby(pmpkg_t *pkg)
}
pmpkg_t *cachepkg = i->data;
if(_alpm_dep_edge(cachepkg, pkg)) {
- const char *cachepkgname = alpm_pkg_get_name(cachepkg);
+ const char *cachepkgname = cachepkg->name;
reqs = alpm_list_add(reqs, strdup(cachepkgname));
}
}
@@ -858,7 +851,11 @@ void _alpm_pkg_free(pmpkg_t *pkg)
FREE(pkg);
}
-/* Free transaction specific fields */
+/* This function should be used when removing a target from upgrade/sync target list
+ * Case 1: If pkg is a loaded package file (PKG_FROM_FILE), it will be freed.
+ * Case 2: If pkg is a pkgcache entry (PKG_FROM_CACHE), it won't be freed,
+ * only the transaction specific fields of pkg will be freed.
+ */
void _alpm_pkg_free_trans(pmpkg_t *pkg)
{
ALPM_LOG_FUNC;
@@ -867,6 +864,11 @@ void _alpm_pkg_free_trans(pmpkg_t *pkg)
return;
}
+ if(pkg->origin == PKG_FROM_FILE) {
+ _alpm_pkg_free(pkg);
+ return;
+ }
+
alpm_list_free(pkg->removes);
pkg->removes = NULL;
}
@@ -894,7 +896,7 @@ int _alpm_pkg_cmp(const void *p1, const void *p2)
{
pmpkg_t *pkg1 = (pmpkg_t *)p1;
pmpkg_t *pkg2 = (pmpkg_t *)p2;
- return(strcmp(alpm_pkg_get_name(pkg1), alpm_pkg_get_name(pkg2)));
+ return(strcmp(pkg1->name, pkg2->name));
}
/* Test for existence of a package in a alpm_list_t*
@@ -913,7 +915,7 @@ pmpkg_t *_alpm_pkg_find(alpm_list_t *haystack, const char *needle)
for(lp = haystack; lp; lp = lp->next) {
pmpkg_t *info = lp->data;
- if(info && strcmp(alpm_pkg_get_name(info), needle) == 0) {
+ if(info && strcmp(info->name, needle) == 0) {
return(info);
}
}
diff --git a/lib/libalpm/package.h b/lib/libalpm/package.h
index aea3f394..b003b410 100644
--- a/lib/libalpm/package.h
+++ b/lib/libalpm/package.h
@@ -49,8 +49,8 @@ struct __pmpkg_t {
off_t size;
off_t isize;
off_t download_size;
- unsigned short scriptlet;
- unsigned short force;
+ int scriptlet;
+ int force;
pmpkgreason_t reason;
alpm_list_t *licenses;
alpm_list_t *replaces;
diff --git a/lib/libalpm/po/LINGUAS b/lib/libalpm/po/LINGUAS
index 5f661697..60193275 100644
--- a/lib/libalpm/po/LINGUAS
+++ b/lib/libalpm/po/LINGUAS
@@ -1,4 +1,5 @@
# Set of available languages.
+ca
cs
de
el
diff --git a/lib/libalpm/po/ca.po b/lib/libalpm/po/ca.po
new file mode 100644
index 00000000..05ee007a
--- /dev/null
+++ b/lib/libalpm/po/ca.po
@@ -0,0 +1,569 @@
+# Translation of libpalm.po to Catalan
+# Copyright (C) YEAR Pacman Development Team <pacman-dev@archlinux.org>
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Manuel Tortosa <manutortosa@gmail.com>, 2009.
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: pacman-dev@archlinux.org\n"
+"POT-Creation-Date: 2009-10-04 16:48+0200\n"
+"PO-Revision-Date: 2009-11-15 23:05+0100\n"
+"Last-Translator: Manuel Tortosa <manutortosa@gmail.com>\n"
+"Language-Team: Catalan <kde-i18n-ca@kde.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Lokalize 1.0\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+#, c-format
+msgid "replacing older version %s-%s by %s in target list\n"
+msgstr ""
+"s'està reemplaçant l'antiga versió %s-%s per %s en la llista "
+"d'objectius\n"
+
+#, c-format
+msgid "skipping %s-%s because newer version %s is in target list\n"
+msgstr ""
+"s'ometrà %s-%s perquè la versió més nova %s és en la llista "
+"d'objectius\n"
+
+#, c-format
+msgid "conflicting packages were found in target list\n"
+msgstr "s'han trobat paquets conflictius en la llista d'objectius\n"
+
+#, c-format
+msgid "you cannot install two conflicting packages at the same time\n"
+msgstr "no podeu instal·lar dos paquets amb conflictes alhora\n"
+
+#, c-format
+msgid "replacing packages with -U is not supported yet\n"
+msgstr "no està implementat reemplaçar paquets amb -U\n"
+
+#, c-format
+msgid "you can replace packages manually using -Rd and -U\n"
+msgstr "podeu reemplaçar paquets manualment usant -Rd i -U\n"
+
+#, c-format
+msgid ""
+"directory permissions differ on %s\n"
+"filesystem: %o package: %o\n"
+msgstr ""
+"els permisos del directori difereixen en %s\n"
+"sistema de fitxers: %o paquet: %o\n"
+
+#, c-format
+msgid "extract: not overwriting dir with file %s\n"
+msgstr "extracció: no se sobreescriurà el directori amb el fitxer %s\n"
+
+#, c-format
+msgid "extract: symlink %s does not point to dir\n"
+msgstr "extracció: l'enllaç simbòlic %s no apunta al directori\n"
+
+#, c-format
+msgid "could not extract %s (%s)\n"
+msgstr "no es pot extreure %s (%s)\n"
+
+#, c-format
+msgid "could not rename %s to %s (%s)\n"
+msgstr "no es pot reanomenar %s a %s (%s)\n"
+
+#, c-format
+msgid "%s saved as %s\n"
+msgstr "%s desat com %s\n"
+
+#, c-format
+msgid "could not install %s as %s (%s)\n"
+msgstr "no es pot instal·lar %s com %s (%s)\n"
+
+#, c-format
+msgid "%s installed as %s\n"
+msgstr "%s instal·lat com %s\n"
+
+#, c-format
+msgid "extracting %s as %s.pacnew\n"
+msgstr "s'està extraient %s com %s.pacnew\n"
+
+#, c-format
+msgid "could not get current working directory\n"
+msgstr "no es pot obtenir el directori de treball actual\n"
+
+#, c-format
+msgid "problem occurred while upgrading %s\n"
+msgstr "ha ocorregut un problema en actualitzar %s\n"
+
+#, c-format
+msgid "problem occurred while installing %s\n"
+msgstr "ha ocorregut un problema en instal·lar %s\n"
+
+#, c-format
+msgid "could not update database entry %s-%s\n"
+msgstr ""
+"no s'ha pogut actualitzar l'entrada de la base de dades %s-%s\n"
+
+#, c-format
+msgid "could not add entry '%s' in cache\n"
+msgstr "no s'ha pogut afegir l'entrada '%s' en la memòria cau\n"
+
+#, c-format
+msgid "removing invalid database: %s\n"
+msgstr "s'està eliminant la base de dades invàlida: %s\n"
+
+#, c-format
+msgid "could not remove database %s\n"
+msgstr "no s'ha pogut eliminar la base de dades %s\n"
+
+#, c-format
+msgid "invalid name for database entry '%s'\n"
+msgstr "nom invàlid per l'entrada de la base de dades '%s'\n"
+
+#, c-format
+msgid "corrupted database entry '%s'\n"
+msgstr "entrada de la base de dades corrupta '%s'\n"
+
+#, c-format
+msgid "could not open file %s: %s\n"
+msgstr "no es pot obrir el fitxer %s: %s\n"
+
+#, c-format
+msgid "%s database is inconsistent: name mismatch on package %s\n"
+msgstr ""
+"la base de dades %s és inconsistent: nom erroni en el paquet %s\n"
+
+#, c-format
+msgid "%s database is inconsistent: version mismatch on package %s\n"
+msgstr ""
+"la base de dades %s és inconsistent: versió errònia en el paquet %s\n"
+
+#, c-format
+msgid "could not create directory %s: %s\n"
+msgstr "no s'ha pogut crear el directori %s: %s\n"
+
+#, c-format
+msgid "could not parse package description file in %s\n"
+msgstr ""
+"no s'ha pogut analitzar el fitxers de descripció de paquet en %s\n"
+
+#, c-format
+msgid "missing package name in %s\n"
+msgstr "falta nom de paquet en %s\n"
+
+#, c-format
+msgid "missing package version in %s\n"
+msgstr "falta versió de paquet en %s\n"
+
+#, c-format
+msgid "error while reading package %s: %s\n"
+msgstr "error en llegir paquet %s: %s\n"
+
+#, c-format
+msgid "missing package metadata in %s\n"
+msgstr "falten les metadades del paquet en %s\n"
+
+#, c-format
+msgid "attempt to re-register the 'local' DB\n"
+msgstr "intent de re-registre de la BD 'local'\n"
+
+#, c-format
+msgid "database path is undefined\n"
+msgstr "no s'ha definit la ruta de la base de dades\n"
+
+#, c-format
+msgid "dependency cycle detected:\n"
+msgstr "s'ha detectat una dependència cíclica:\n"
+
+#, c-format
+msgid "%s will be removed after its %s dependency\n"
+msgstr "%s serà eliminat després de la seva dependència %s\n"
+
+#, c-format
+msgid "%s will be installed before its %s dependency\n"
+msgstr "%s serà instal·lar abans de la seva dependència %s\n"
+
+#, c-format
+msgid "ignoring package %s-%s\n"
+msgstr "s'està ignorant paquet %s-%s\n"
+
+#, c-format
+msgid "provider package was selected (%s provides %s)\n"
+msgstr "s'ha seleccionat un paquet proveïdor (%s proveeix %s)\n"
+
+#, c-format
+msgid "cannot resolve \"%s\", a dependency of \"%s\"\n"
+msgstr "no es pot resoldre \"%s\", una dependència de \"%s\"\n"
+
+#, c-format
+msgid "url '%s' is invalid\n"
+msgstr "l'url '%s' és invàlid\n"
+
+#, c-format
+msgid "url scheme not specified, assuming HTTP\n"
+msgstr "no s'ha especificat l'esquema url, s'està assumint HTTP\n"
+
+#, c-format
+msgid "disk"
+msgstr "disc"
+
+#, c-format
+msgid "failed retrieving file '%s' from %s : %s\n"
+msgstr "ha fallat en recuperar el fitxer '%s' des de %s : %s\n"
+
+#, c-format
+msgid "cannot resume download, starting over\n"
+msgstr "no es pot la reprendre la baixada, s'està iniciant de nou\n"
+
+#, c-format
+msgid "cannot write to file '%s'\n"
+msgstr "no s'ha pogut escriure al fitxer '%s'\n"
+
+#, c-format
+msgid "error writing to file '%s': %s\n"
+msgstr "error en escriure al fitxer '%s': %s\n"
+
+#, c-format
+msgid "failed retrieving file '%s' from %s\n"
+msgstr "ha fallat en recuperar el fitxer '%s' de %s\n"
+
+#, c-format
+msgid "%s appears to be truncated: %jd/%jd bytes\n"
+msgstr "%s sembla estar truncat: %jd/%jd bytes\n"
+
+#, c-format
+msgid "failed to download %s\n"
+msgstr "ha fallat en baixar %s\n"
+
+#, c-format
+msgid "out of memory!"
+msgstr "memòria esgotada!"
+
+#, c-format
+msgid "unexpected system error"
+msgstr "error inesperat del sistema"
+
+#, c-format
+msgid "insufficient privileges"
+msgstr "privilegis insuficients"
+
+#, c-format
+msgid "could not find or read file"
+msgstr "no es pot trobar o llegir fitxer"
+
+#, c-format
+msgid "could not find or read directory"
+msgstr "no es pot trobar o llegir directori"
+
+#, c-format
+msgid "wrong or NULL argument passed"
+msgstr "s'ha passat un argument erroni o NULL"
+
+#, c-format
+msgid "library not initialized"
+msgstr "llibreria no inicialitzada"
+
+#, c-format
+msgid "library already initialized"
+msgstr "la llibreria ja s'ha inicialitzat"
+
+#, c-format
+msgid "unable to lock database"
+msgstr "no s'ha pogut bloquejar la base de dades"
+
+#, c-format
+msgid "could not open database"
+msgstr "no s'ha pogut obrir la base de dades"
+
+#, c-format
+msgid "could not create database"
+msgstr "no s'ha pogut crear la base de dades"
+
+#, c-format
+msgid "database not initialized"
+msgstr "base de dades no inicialitzada"
+
+#, c-format
+msgid "database already registered"
+msgstr "la base de dades ja s'ha registrat"
+
+#, c-format
+msgid "could not find database"
+msgstr "no s'ha pogut trobar la base de dades"
+
+#, c-format
+msgid "could not update database"
+msgstr "no s'ha pogut actualitzar la base de dades"
+
+#, c-format
+msgid "could not remove database entry"
+msgstr "no s'ha pogut suprimir l'entrada de la base de dades"
+
+#, c-format
+msgid "invalid url for server"
+msgstr "url del servidor invàlid"
+
+#, c-format
+msgid "no servers configured for repository"
+msgstr "no s'ha configurat cap servidor pel repositori"
+
+#, c-format
+msgid "transaction already initialized"
+msgstr "ja s'ha inicialitzat la transacció"
+
+#, c-format
+msgid "transaction not initialized"
+msgstr "no s'ha inicialitzat la transacció"
+
+#, c-format
+msgid "duplicate target"
+msgstr "objectiu duplicat"
+
+#, c-format
+msgid "transaction not prepared"
+msgstr "transacció no preparada"
+
+#, c-format
+msgid "transaction aborted"
+msgstr "transacció cancel·lada"
+
+#, c-format
+msgid "operation not compatible with the transaction type"
+msgstr "l'operació no és compatible amb el tipus de transacció"
+
+#, c-format
+msgid "transaction commit attempt when database is not locked"
+msgstr ""
+"intent de publicació de la transacció amb la base de dades no "
+"bloquejada"
+
+#, c-format
+msgid "could not find or read package"
+msgstr "no s'ha pogut trobar o llegir el paquet"
+
+#, c-format
+msgid "operation cancelled due to ignorepkg"
+msgstr "operació cancel·lada degut a ignorepkg"
+
+#, c-format
+msgid "invalid or corrupted package"
+msgstr "paquet invàlid o corrupte"
+
+#, c-format
+msgid "cannot open package file"
+msgstr "no s'ha pogut obrir el fitxer de paquet"
+
+#, c-format
+msgid "cannot remove all files for package"
+msgstr "no s'han pogut eliminar tots els fitxers del paquet"
+
+#, c-format
+msgid "package filename is not valid"
+msgstr "el nom de fitxer del paquet no és vàlid"
+
+#, c-format
+msgid "no such repository"
+msgstr "no existeix aquest repositori"
+
+#, c-format
+msgid "invalid or corrupted delta"
+msgstr "delta invàlid o corrupte"
+
+#, c-format
+msgid "delta patch failed"
+msgstr "ha fallat el pedaç delta"
+
+#, c-format
+msgid "could not satisfy dependencies"
+msgstr "no s'han pogut satisfer les dependències"
+
+#, c-format
+msgid "conflicting dependencies"
+msgstr "dependències conflictives"
+
+#, c-format
+msgid "conflicting files"
+msgstr "fitxers conflictius"
+
+#, c-format
+msgid "failed to retrieve some files"
+msgstr "ha fallat en recuperar alguns fitxers"
+
+#, c-format
+msgid "invalid regular expression"
+msgstr "expressió regular invàlida"
+
+#, c-format
+msgid "libarchive error"
+msgstr "error de libarchive"
+
+#, c-format
+msgid "download library error"
+msgstr "error de la llibreria de baixades"
+
+#, c-format
+msgid "error invoking external downloader"
+msgstr "error en invocar el baixador extern"
+
+#, c-format
+msgid "unexpected error"
+msgstr "error inesperat"
+
+#, c-format
+msgid "could not find %s in database -- skipping\n"
+msgstr "no s'ha pogut trobar %s en la base de dades -- s'està ometent\n"
+
+#, c-format
+msgid "removing %s from target list\n"
+msgstr "s'està eliminant %s de la llista d'objectius\n"
+
+#, c-format
+msgid "cannot remove file '%s': %s\n"
+msgstr "no s'ha pogut eliminar el fitxer '%s': %s\n"
+
+#, c-format
+msgid "could not remove database entry %s-%s\n"
+msgstr "no s'ha pogut eliminar la entrada de la base de dades %s-%s\n"
+
+#, c-format
+msgid "could not remove entry '%s' from cache\n"
+msgstr "no s'ha pogut eliminar l'entrada '%s' de la memòria cau\n"
+
+#, c-format
+msgid "%s: ignoring package upgrade (%s => %s)\n"
+msgstr "%s: s'ha ignorat l'actualització del paquet (%s => %s)\n"
+
+#, c-format
+msgid "%s: ignoring package downgrade (%s => %s)\n"
+msgstr "%s: s'ha ignorat la desactualització del paquet (%s => %s)\n"
+
+#, c-format
+msgid "%s: downgrading from version %s to version %s\n"
+msgstr "%s: desactualitzant de la versió %s a la versió %s\n"
+
+#, c-format
+msgid "%s: local (%s) is newer than %s (%s)\n"
+msgstr "%s: local (%s) és més nou que %s (%s)\n"
+
+#, c-format
+msgid "ignoring package replacement (%s-%s => %s-%s)\n"
+msgstr "s'està ignorant el reemplaçament del paquet (%s-%s => %s-%s)\n"
+
+#, c-format
+msgid "cannot replace %s by %s\n"
+msgstr "no s'ha pogut reemplaçar %s per %s\n"
+
+#, c-format
+msgid "repository '%s' not found\n"
+msgstr "no s'ha trobat el repositori '%s'\n"
+
+#, c-format
+msgid "%s-%s is up to date -- skipping\n"
+msgstr "%s-%s és al dia -- s'ignorarà\n"
+
+#, c-format
+msgid "%s-%s is up to date -- reinstalling\n"
+msgstr "%s-%s és al dia -- es reinstal·larà\n"
+
+#, c-format
+msgid "downgrading package %s (%s => %s)\n"
+msgstr "desactualitzant paquet %s (%s => %s)\n"
+
+#, c-format
+msgid "unresolvable package conflicts detected\n"
+msgstr ""
+"s'ha detectat un paquet amb un conflicte impossible de resoldre\n"
+
+#, c-format
+msgid "removing '%s' from target list because it conflicts with '%s'\n"
+msgstr ""
+"s'està eliminant '%s' de la llista d'objectius perquè té conflictes "
+"amb '%s'\n"
+
+#, c-format
+msgid "failed to retrieve some files from %s\n"
+msgstr "ha fallat en recuperar alguns fitxers de %s\n"
+
+#, c-format
+msgid "could not create removal transaction\n"
+msgstr "no s'ha pogut crear la transacció d'eliminació\n"
+
+#, c-format
+msgid "could not create transaction\n"
+msgstr "no s'ha pogut crear la transacció\n"
+
+#, c-format
+msgid "could not initialize the removal transaction\n"
+msgstr "no s'ha pogut inicialitzar la transacció d'eliminació\n"
+
+#, c-format
+msgid "could not initialize transaction\n"
+msgstr "no s'ha pogut inicialitzar la transacció\n"
+
+#, c-format
+msgid "could not prepare removal transaction\n"
+msgstr "no s'ha pogut preparar la transacció d'eliminació\n"
+
+#, c-format
+msgid "could not commit removal transaction\n"
+msgstr "no s'ha pogut publicar la transacció d'eliminació\n"
+
+#, c-format
+msgid "could not commit transaction\n"
+msgstr "no s'ha pogut publicar la transacció\n"
+
+#, c-format
+msgid "could not remove lock file %s\n"
+msgstr "no s'ha pogut eliminar el fitxer de bloqueig %s\n"
+
+#, c-format
+msgid "could not create temp directory\n"
+msgstr "no s'ha pogut crear el directori temporal\n"
+
+#, c-format
+msgid "could not copy tempfile to %s (%s)\n"
+msgstr "no s'ha pogut copiar el fitxer temporal a %s (%s)\n"
+
+#, c-format
+msgid "could not remove tmpdir %s\n"
+msgstr "no s'ha pogut eliminar el directori temporal %s\n"
+
+#, c-format
+msgid "could not open %s: %s\n"
+msgstr "no s'ha pogut obrir %s: %s\n"
+
+#, c-format
+msgid "could not change directory to %s (%s)\n"
+msgstr "no s'ha pogut canviar el directori a %s (%s)\n"
+
+#, c-format
+msgid "could not fork a new process (%s)\n"
+msgstr "no s'ha pogut bifurcar a un nou procés (%s)\n"
+
+#, c-format
+msgid "could not change the root directory (%s)\n"
+msgstr "no s'ha pogut canviar el directori arrel (%s)\n"
+
+#, c-format
+msgid "could not change directory to / (%s)\n"
+msgstr "no s'ha pogut canviar el directori a / (%s)\n"
+
+#, c-format
+msgid "call to popen failed (%s)\n"
+msgstr "ha fallat la crida a popen (%s)\n"
+
+#, c-format
+msgid "call to waitpid failed (%s)\n"
+msgstr "ha fallat la crida a waitpid (%s)\n"
+
+#, c-format
+msgid "command failed to execute correctly\n"
+msgstr "l'ordre a fallat a executar-se correctament\n"
+
+#, c-format
+msgid "no %s cache exists, creating...\n"
+msgstr "no existeix memòria cau %s, s'està creant...\n"
+
+#, c-format
+msgid "couldn't create package cache, using /tmp instead\n"
+msgstr "no s'ha pogut crear la memòria cau del paquet, s'usarà /tmp\n"
+
+
diff --git a/lib/libalpm/remove.c b/lib/libalpm/remove.c
index 1e8f9156..80eec67f 100644
--- a/lib/libalpm/remove.c
+++ b/lib/libalpm/remove.c
@@ -47,35 +47,45 @@
#include "handle.h"
#include "alpm.h"
-int _alpm_remove_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name)
+int SYMEXPORT alpm_remove_target(char *target)
{
pmpkg_t *info;
- const char *targ;
+ pmtrans_t *trans;
+ pmdb_t *db_local;
+ alpm_list_t *p;
ALPM_LOG_FUNC;
- ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
+ /* Sanity checks */
+ ASSERT(target != NULL && strlen(target) != 0, RET_ERR(PM_ERR_WRONG_ARGS, -1));
+ ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1));
+ trans = handle->trans;
+ db_local = handle->db_local;
ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
- ASSERT(name != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1));
+ ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1));
+ ASSERT(db_local != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
- targ = strchr(name, '/');
- if(targ && strncmp(name, "local", 5) == 0) {
- targ++;
- } else {
- targ = name;
- }
- if(_alpm_pkg_find(trans->packages, targ)) {
+ if(_alpm_pkg_find(trans->remove, target)) {
RET_ERR(PM_ERR_TRANS_DUP_TARGET, -1);
}
- if((info = _alpm_db_get_pkgfromcache(db, targ)) == NULL) {
- _alpm_log(PM_LOG_DEBUG, "could not find %s in database\n", targ);
- RET_ERR(PM_ERR_PKG_NOT_FOUND, -1);
+ if((info = _alpm_db_get_pkgfromcache(db_local, target)) != NULL) {
+ _alpm_log(PM_LOG_DEBUG, "adding %s in the target list\n", info->name);
+ trans->remove = alpm_list_add(trans->remove, _alpm_pkg_dup(info));
+ return(0);
}
- _alpm_log(PM_LOG_DEBUG, "adding %s in target list\n", info->name);
- trans->packages = alpm_list_add(trans->packages, _alpm_pkg_dup(info));
+ _alpm_log(PM_LOG_DEBUG, "could not find %s in database\n", target);
+ pmgrp_t *grp = alpm_db_readgrp(db_local, target);
+ if(grp == NULL) {
+ RET_ERR(PM_ERR_PKG_NOT_FOUND, -1);
+ }
+ for(p = alpm_grp_get_pkgs(grp); p; p = alpm_list_next(p)) {
+ pmpkg_t *pkg = alpm_list_getdata(p);
+ _alpm_log(PM_LOG_DEBUG, "adding %s in the target list\n", pkg->name);
+ trans->remove = alpm_list_add(trans->remove, _alpm_pkg_dup(pkg));
+ }
return(0);
}
@@ -91,10 +101,10 @@ static void remove_prepare_cascade(pmtrans_t *trans, pmdb_t *db,
pmdepmissing_t *miss = (pmdepmissing_t *)i->data;
pmpkg_t *info = _alpm_db_get_pkgfromcache(db, miss->target);
if(info) {
- if(!_alpm_pkg_find(trans->packages, alpm_pkg_get_name(info))) {
+ if(!_alpm_pkg_find(trans->remove, alpm_pkg_get_name(info))) {
_alpm_log(PM_LOG_DEBUG, "pulling %s in target list\n",
alpm_pkg_get_name(info));
- trans->packages = alpm_list_add(trans->packages, _alpm_pkg_dup(info));
+ trans->remove = alpm_list_add(trans->remove, _alpm_pkg_dup(info));
}
} else {
_alpm_log(PM_LOG_ERROR, _("could not find %s in database -- skipping\n"),
@@ -103,7 +113,7 @@ static void remove_prepare_cascade(pmtrans_t *trans, pmdb_t *db,
}
alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_depmiss_free);
alpm_list_free(lp);
- lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, trans->packages, NULL);
+ lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, trans->remove, NULL);
}
}
@@ -118,11 +128,11 @@ static void remove_prepare_keep_needed(pmtrans_t *trans, pmdb_t *db,
for(i = lp; i; i = i->next) {
pmdepmissing_t *miss = (pmdepmissing_t *)i->data;
void *vpkg;
- pmpkg_t *pkg = _alpm_pkg_find(trans->packages, miss->causingpkg);
+ pmpkg_t *pkg = _alpm_pkg_find(trans->remove, miss->causingpkg);
if(pkg == NULL) {
continue;
}
- trans->packages = alpm_list_remove(trans->packages, pkg, _alpm_pkg_cmp,
+ trans->remove = alpm_list_remove(trans->remove, pkg, _alpm_pkg_cmp,
&vpkg);
pkg = vpkg;
if(pkg) {
@@ -133,7 +143,7 @@ static void remove_prepare_keep_needed(pmtrans_t *trans, pmdb_t *db,
}
alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_depmiss_free);
alpm_list_free(lp);
- lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, trans->packages, NULL);
+ lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, trans->remove, NULL);
}
}
@@ -146,21 +156,16 @@ int _alpm_remove_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data)
ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
- /* skip all checks if we are doing this removal as part of an upgrade */
- if(trans->type == PM_TRANS_TYPE_REMOVEUPGRADE) {
- return(0);
- }
-
if((trans->flags & PM_TRANS_FLAG_RECURSE) && !(trans->flags & PM_TRANS_FLAG_CASCADE)) {
_alpm_log(PM_LOG_DEBUG, "finding removable dependencies\n");
- _alpm_recursedeps(db, trans->packages, trans->flags & PM_TRANS_FLAG_RECURSEALL);
+ _alpm_recursedeps(db, trans->remove, trans->flags & PM_TRANS_FLAG_RECURSEALL);
}
if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) {
EVENT(trans, PM_TRANS_EVT_CHECKDEPS_START, NULL, NULL);
_alpm_log(PM_LOG_DEBUG, "looking for unsatisfied dependencies\n");
- lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, trans->packages, NULL);
+ lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, trans->remove, NULL);
if(lp != NULL) {
if(trans->flags & PM_TRANS_FLAG_CASCADE) {
@@ -183,15 +188,15 @@ int _alpm_remove_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, 1);
+ lp = _alpm_sortbydeps(trans->remove, 1);
/* free the old alltargs */
- alpm_list_free(trans->packages);
- trans->packages = lp;
+ alpm_list_free(trans->remove);
+ trans->remove = lp;
/* -Rcs == -Rc then -Rs */
if((trans->flags & PM_TRANS_FLAG_CASCADE) && (trans->flags & PM_TRANS_FLAG_RECURSE)) {
_alpm_log(PM_LOG_DEBUG, "finding removable dependencies\n");
- _alpm_recursedeps(db, trans->packages, trans->flags & PM_TRANS_FLAG_RECURSEALL);
+ _alpm_recursedeps(db, trans->remove, trans->flags & PM_TRANS_FLAG_RECURSEALL);
}
if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) {
@@ -201,13 +206,13 @@ int _alpm_remove_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data)
return(0);
}
-static int can_remove_file(pmtrans_t *trans, const char *path)
+static int can_remove_file(const char *path, alpm_list_t *skip)
{
char file[PATH_MAX+1];
snprintf(file, PATH_MAX, "%s%s", handle->root, path);
- if(alpm_list_find_str(trans->skip_remove, file)) {
+ if(alpm_list_find_str(skip, file)) {
/* return success because we will never actually remove this file */
return(1);
}
@@ -228,7 +233,7 @@ static int can_remove_file(pmtrans_t *trans, const char *path)
/* Helper function for iterating through a package's file and deleting them
* Used by _alpm_remove_commit. */
-static void unlink_file(pmpkg_t *info, char *filename, pmtrans_t *trans)
+static void unlink_file(pmpkg_t *info, char *filename, alpm_list_t *skip_remove, int nosave)
{
struct stat buf;
char file[PATH_MAX+1];
@@ -237,13 +242,13 @@ static void unlink_file(pmpkg_t *info, char *filename, pmtrans_t *trans)
snprintf(file, PATH_MAX, "%s%s", handle->root, filename);
- if(trans->type == PM_TRANS_TYPE_REMOVEUPGRADE) {
- /* check noupgrade */
- if(alpm_list_find_str(handle->noupgrade, filename)) {
- _alpm_log(PM_LOG_DEBUG, "Skipping removal of '%s' due to NoUpgrade\n",
- file);
- return;
- }
+ /* check the remove skip list before removing the file.
+ * see the big comment block in db_find_fileconflicts() for an
+ * explanation. */
+ if(alpm_list_find_str(skip_remove, filename)) {
+ _alpm_log(PM_LOG_DEBUG, "%s is in skip_remove, skipping removal\n",
+ file);
+ return;
}
/* we want to do a lstat here, and not a _alpm_lstat.
@@ -263,19 +268,10 @@ static void unlink_file(pmpkg_t *info, char *filename, pmtrans_t *trans)
_alpm_log(PM_LOG_DEBUG, "removing directory %s\n", file);
}
} else {
- /* check the remove skip list before removing the file.
- * see the big comment block in db_find_fileconflicts() for an
- * explanation. */
- if(alpm_list_find_str(trans->skip_remove, file)) {
- _alpm_log(PM_LOG_DEBUG, "%s is in trans->skip_remove, skipping removal\n",
- file);
- return;
- }
-
/* if the file needs backup and has been modified, back it up to .pacsave */
char *pkghash = _alpm_needbackup(filename, alpm_pkg_get_backup(info));
if(pkghash) {
- if(trans->flags & PM_TRANS_FLAG_NOSAVE) {
+ if(nosave) {
_alpm_log(PM_LOG_DEBUG, "transaction is set to NOSAVE, not backing up '%s'\n", file);
FREE(pkghash);
} else {
@@ -303,7 +299,69 @@ static void unlink_file(pmpkg_t *info, char *filename, pmtrans_t *trans)
}
}
-int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db)
+int _alpm_upgraderemove_package(pmpkg_t *oldpkg, pmpkg_t *newpkg, pmtrans_t *trans)
+{
+ alpm_list_t *skip_remove, *b;
+ alpm_list_t *newfiles, *lp;
+ alpm_list_t *files = alpm_pkg_get_files(oldpkg);
+ const char *pkgname = alpm_pkg_get_name(oldpkg);
+
+ ALPM_LOG_FUNC;
+
+ _alpm_log(PM_LOG_DEBUG, "removing old package first (%s-%s)\n",
+ oldpkg->name, oldpkg->version);
+
+ /* copy the remove skiplist over */
+ skip_remove =
+ alpm_list_join(alpm_list_strdup(trans->skip_remove),alpm_list_strdup(handle->noupgrade));
+ /* Add files in the NEW backup array to the skip_remove array
+ * so this removal operation doesn't kill them */
+ /* old package backup list */
+ alpm_list_t *filelist = alpm_pkg_get_files(newpkg);
+ for(b = alpm_pkg_get_backup(newpkg); b; b = b->next) {
+ char *backup = _alpm_backup_file(b->data);
+ /* safety check (fix the upgrade026 pactest) */
+ if(!alpm_list_find_str(filelist, backup)) {
+ FREE(backup);
+ continue;
+ }
+ _alpm_log(PM_LOG_DEBUG, "adding %s to the skip_remove array\n", backup);
+ skip_remove = alpm_list_add(skip_remove, backup);
+ }
+
+ for(lp = files; lp; lp = lp->next) {
+ if(!can_remove_file(lp->data, skip_remove)) {
+ _alpm_log(PM_LOG_DEBUG, "not removing package '%s', can't remove all files\n",
+ pkgname);
+ RET_ERR(PM_ERR_PKG_CANT_REMOVE, -1);
+ }
+ }
+
+ /* iterate through the list backwards, unlinking files */
+ newfiles = alpm_list_reverse(files);
+ for(lp = newfiles; lp; lp = alpm_list_next(lp)) {
+ unlink_file(oldpkg, lp->data, skip_remove, 0);
+ }
+ alpm_list_free(newfiles);
+ FREELIST(skip_remove);
+
+ /* remove the package from the database */
+ _alpm_log(PM_LOG_DEBUG, "updating database\n");
+ _alpm_log(PM_LOG_DEBUG, "removing database entry '%s'\n", pkgname);
+ if(_alpm_db_remove(handle->db_local, oldpkg) == -1) {
+ _alpm_log(PM_LOG_ERROR, _("could not remove database entry %s-%s\n"),
+ pkgname, alpm_pkg_get_version(oldpkg));
+ }
+ /* remove the package from the cache */
+ if(_alpm_db_remove_pkgfromcache(handle->db_local, oldpkg) == -1) {
+ _alpm_log(PM_LOG_ERROR, _("could not remove entry '%s' from cache\n"),
+ pkgname);
+ }
+
+ return(0);
+}
+
+int _alpm_remove_packages(pmtrans_t *trans, pmdb_t *db)
{
pmpkg_t *info;
alpm_list_t *targ, *lp;
@@ -314,14 +372,14 @@ int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db)
ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
- pkg_count = alpm_list_count(trans->packages);
+ pkg_count = alpm_list_count(trans->remove);
- for(targ = trans->packages; targ; targ = targ->next) {
+ for(targ = trans->remove; targ; targ = targ->next) {
int position = 0;
char scriptlet[PATH_MAX];
- alpm_list_t *files;
info = (pmpkg_t*)targ->data;
const char *pkgname = NULL;
+ int targcount = alpm_list_count(targ);
if(handle->trans->state == STATE_INTERRUPTED) {
return(0);
@@ -329,26 +387,23 @@ int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db)
/* get the name now so we can use it after package is removed */
pkgname = alpm_pkg_get_name(info);
- snprintf(scriptlet, PATH_MAX, "%s%s-%s/install", db->path,
- pkgname, alpm_pkg_get_version(info));
-
- if(trans->type != PM_TRANS_TYPE_REMOVEUPGRADE) {
- EVENT(trans, PM_TRANS_EVT_REMOVE_START, info, NULL);
- _alpm_log(PM_LOG_DEBUG, "removing package %s-%s\n",
- pkgname, alpm_pkg_get_version(info));
-
- /* run the pre-remove scriptlet if it exists */
- if(alpm_pkg_has_scriptlet(info) && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) {
- _alpm_runscriptlet(handle->root, scriptlet, "pre_remove",
- alpm_pkg_get_version(info), NULL, trans);
- }
- }
+ snprintf(scriptlet, PATH_MAX, "%s%s-%s/install",
+ _alpm_db_path(db), pkgname, alpm_pkg_get_version(info));
- files = alpm_pkg_get_files(info);
+ EVENT(trans, PM_TRANS_EVT_REMOVE_START, info, NULL);
+ _alpm_log(PM_LOG_DEBUG, "removing package %s-%s\n",
+ pkgname, alpm_pkg_get_version(info));
+
+ /* run the pre-remove scriptlet if it exists */
+ if(alpm_pkg_has_scriptlet(info) && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) {
+ _alpm_runscriptlet(handle->root, scriptlet, "pre_remove",
+ alpm_pkg_get_version(info), NULL, trans);
+ }
if(!(trans->flags & PM_TRANS_FLAG_DBONLY)) {
+ alpm_list_t *files = alpm_pkg_get_files(info);
for(lp = files; lp; lp = lp->next) {
- if(!can_remove_file(trans, lp->data)) {
+ if(!can_remove_file(lp->data, NULL)) {
_alpm_log(PM_LOG_DEBUG, "not removing package '%s', can't remove all files\n",
pkgname);
RET_ERR(PM_ERR_PKG_CANT_REMOVE, -1);
@@ -356,20 +411,20 @@ int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db)
}
int filenum = alpm_list_count(files);
- double percent = 0.0;
alpm_list_t *newfiles;
_alpm_log(PM_LOG_DEBUG, "removing %d files\n", filenum);
/* iterate through the list backwards, unlinking files */
newfiles = alpm_list_reverse(files);
for(lp = newfiles; lp; lp = alpm_list_next(lp)) {
- unlink_file(info, lp->data, trans);
+ double percent;
+ unlink_file(info, lp->data, NULL, trans->flags & PM_TRANS_FLAG_NOSAVE);
/* update progress bar after each file */
percent = (double)position / (double)filenum;
PROGRESS(trans, PM_TRANS_PROGRESS_REMOVE_START, info->name,
(double)(percent * 100), pkg_count,
- (pkg_count - alpm_list_count(targ) + 1));
+ (pkg_count - targcount + 1));
position++;
}
alpm_list_free(newfiles);
@@ -377,14 +432,12 @@ int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db)
/* set progress to 100% after we finish unlinking files */
PROGRESS(trans, PM_TRANS_PROGRESS_REMOVE_START, pkgname, 100,
- pkg_count, (pkg_count - alpm_list_count(targ) + 1));
+ pkg_count, (pkg_count - targcount + 1));
- if(trans->type != PM_TRANS_TYPE_REMOVEUPGRADE) {
- /* run the post-remove script if it exists */
- if(alpm_pkg_has_scriptlet(info) && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) {
- _alpm_runscriptlet(handle->root, scriptlet, "post_remove",
- alpm_pkg_get_version(info), NULL, trans);
- }
+ /* run the post-remove script if it exists */
+ if(alpm_pkg_has_scriptlet(info) && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) {
+ _alpm_runscriptlet(handle->root, scriptlet, "post_remove",
+ alpm_pkg_get_version(info), NULL, trans);
}
/* remove the package from the database */
@@ -400,16 +453,11 @@ int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db)
pkgname);
}
- /* call a done event if this isn't an upgrade */
- if(trans->type != PM_TRANS_TYPE_REMOVEUPGRADE) {
- EVENT(trans, PM_TRANS_EVT_REMOVE_DONE, info, NULL);
- }
+ EVENT(trans, PM_TRANS_EVT_REMOVE_DONE, info, NULL);
}
/* run ldconfig if it exists */
- if(trans->type != PM_TRANS_TYPE_REMOVEUPGRADE) {
- _alpm_ldconfig(handle->root);
- }
+ _alpm_ldconfig(handle->root);
return(0);
}
diff --git a/lib/libalpm/remove.h b/lib/libalpm/remove.h
index 716fbf72..fbbaa169 100644
--- a/lib/libalpm/remove.h
+++ b/lib/libalpm/remove.h
@@ -24,9 +24,10 @@
#include "alpm_list.h"
#include "trans.h"
-int _alpm_remove_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name);
int _alpm_remove_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data);
-int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db);
+int _alpm_remove_packages(pmtrans_t *trans, pmdb_t *db);
+
+int _alpm_upgraderemove_package(pmpkg_t *oldpkg, pmpkg_t *newpkg, pmtrans_t *trans);
#endif /* _ALPM_REMOVE_H */
diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c
index 47639248..2cdcd47b 100644
--- a/lib/libalpm/sync.c
+++ b/lib/libalpm/sync.c
@@ -43,11 +43,13 @@
#include "deps.h"
#include "conflict.h"
#include "trans.h"
+#include "add.h"
#include "util.h"
#include "handle.h"
#include "alpm.h"
#include "dload.h"
#include "delta.h"
+#include "remove.h"
/** Check for new version of pkg in sync repos
* (only the first occurrence is considered in sync)
@@ -80,17 +82,30 @@ pmpkg_t SYMEXPORT *alpm_sync_newversion(pmpkg_t *pkg, alpm_list_t *dbs_sync)
return(NULL);
}
-int _alpm_sync_sysupgrade(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, int enable_downgrade)
+/** Search for packages to upgrade and add them to the transaction.
+ * @return 0 on success, -1 on error (pm_errno is set accordingly)
+ */
+int SYMEXPORT alpm_sync_sysupgrade(int enable_downgrade)
{
alpm_list_t *i, *j, *k;
+ pmtrans_t *trans;
+ pmdb_t *db_local;
+ alpm_list_t *dbs_sync;
ALPM_LOG_FUNC;
+ ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1));
+ trans = handle->trans;
+ db_local = handle->db_local;
+ dbs_sync = handle->dbs_sync;
+ ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
+ ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1));
+
_alpm_log(PM_LOG_DEBUG, "checking for package upgrades\n");
for(i = _alpm_db_get_pkgcache(db_local); i; i = i->next) {
pmpkg_t *lpkg = i->data;
- if(_alpm_pkg_find(trans->packages, lpkg->name)) {
+ if(_alpm_pkg_find(trans->add, lpkg->name)) {
_alpm_log(PM_LOG_DEBUG, "%s is already in the target list -- skipping\n", lpkg->name);
continue;
}
@@ -113,7 +128,7 @@ int _alpm_sync_sysupgrade(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_s
} else {
_alpm_log(PM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n",
spkg->name, spkg->version);
- trans->packages = alpm_list_add(trans->packages, spkg);
+ trans->add = alpm_list_add(trans->add, spkg);
}
} else if(cmp < 0) {
if(enable_downgrade) {
@@ -124,7 +139,7 @@ int _alpm_sync_sysupgrade(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_s
} else {
_alpm_log(PM_LOG_WARNING, _("%s: downgrading from version %s to version %s\n"),
lpkg->name, lpkg->version, spkg->version);
- trans->packages = alpm_list_add(trans->packages, spkg);
+ trans->add = alpm_list_add(trans->add, spkg);
}
} else {
_alpm_log(PM_LOG_WARNING, _("%s: local (%s) is newer than %s (%s)\n"),
@@ -152,7 +167,7 @@ int _alpm_sync_sysupgrade(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_s
}
/* If spkg is already in the target list, we append lpkg to spkg's removes list */
- pmpkg_t *tpkg = _alpm_pkg_find(trans->packages, spkg->name);
+ pmpkg_t *tpkg = _alpm_pkg_find(trans->add, spkg->name);
if(tpkg) {
/* sanity check, multiple repos can contain spkg->name */
if(tpkg->origin_data.db != sdb) {
@@ -173,7 +188,7 @@ int _alpm_sync_sysupgrade(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_s
spkg->removes = alpm_list_add(NULL, lpkg);
_alpm_log(PM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n",
spkg->name, spkg->version);
- trans->packages = alpm_list_add(trans->packages, spkg);
+ trans->add = alpm_list_add(trans->add, spkg);
}
}
}
@@ -187,57 +202,18 @@ int _alpm_sync_sysupgrade(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_s
return(0);
}
-int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, char *name)
+int _alpm_sync_pkg(pmpkg_t *spkg)
{
- char *targline;
- char *targ;
- alpm_list_t *j;
- pmpkg_t *local, *spkg;
- pmdepend_t *dep; /* provisions and dependencies are also allowed */
+ pmtrans_t *trans;
+ pmdb_t *db_local;
+ pmpkg_t *local;
ALPM_LOG_FUNC;
- 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));
- targ = strchr(targline, '/');
- if(targ) {
- /* we are looking for a package in a specific database */
- alpm_list_t *dbs = NULL;
- *targ = '\0';
- targ++;
- _alpm_log(PM_LOG_DEBUG, "searching for target '%s' in repo '%s'\n", targ, targline);
- for(j = dbs_sync; j; j = j->next) {
- pmdb_t *db = j->data;
- if(strcmp(db->treename, targline) == 0) {
- dbs = alpm_list_add(NULL, db);
- break;
- }
- }
- if(dbs == NULL) {
- _alpm_log(PM_LOG_ERROR, _("repository '%s' not found\n"), targline);
- FREE(targline);
- RET_ERR(PM_ERR_PKG_REPO_NOT_FOUND, -1);
- }
- dep = _alpm_splitdep(targ);
- spkg = _alpm_resolvedep(dep, dbs, NULL, 1);
- _alpm_dep_free(dep);
- alpm_list_free(dbs);
- } else {
- dep = _alpm_splitdep(targline);
- spkg = _alpm_resolvedep(dep, dbs_sync, NULL, 1);
- _alpm_dep_free(dep);
- }
- FREE(targline);
-
- if(spkg == NULL) {
- /* pm_errno is set by _alpm_resolvedep */
- return(-1);
- }
+ trans = handle->trans;
+ db_local = handle->db_local;
- if(_alpm_pkg_find(trans->packages, alpm_pkg_get_name(spkg))) {
+ if(_alpm_pkg_find(trans->add, alpm_pkg_get_name(spkg))) {
RET_ERR(PM_ERR_TRANS_DUP_TARGET, -1);
}
@@ -267,11 +243,108 @@ int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sy
spkg->reason = PM_PKG_REASON_EXPLICIT;
_alpm_log(PM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n",
alpm_pkg_get_name(spkg), alpm_pkg_get_version(spkg));
- trans->packages = alpm_list_add(trans->packages, spkg);
+ trans->add = alpm_list_add(trans->add, spkg);
+
+ return(0);
+}
+
+int _alpm_sync_target(alpm_list_t *dbs_sync, char *target)
+{
+ alpm_list_t *i, *j;
+ pmpkg_t *spkg;
+ pmdepend_t *dep; /* provisions and dependencies are also allowed */
+ pmgrp_t *grp;
+ int found = 0;
+
+ ALPM_LOG_FUNC;
+
+ /* Sanity checks */
+ ASSERT(target != NULL && strlen(target) != 0, RET_ERR(PM_ERR_WRONG_ARGS, -1));
+ ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1));
+
+ dep = _alpm_splitdep(target);
+ spkg = _alpm_resolvedep(dep, dbs_sync, NULL, 1);
+ _alpm_dep_free(dep);
+
+ if(spkg != NULL) {
+ return(_alpm_sync_pkg(spkg));
+ }
+
+ _alpm_log(PM_LOG_DEBUG, "%s package not found, searching for group...\n", target);
+ for(i = dbs_sync; i; i = i->next) {
+ pmdb_t *db = i->data;
+ grp = alpm_db_readgrp(db, target);
+ if(grp) {
+ found = 1;
+ for(j = alpm_grp_get_pkgs(grp); j; j = j->next) {
+ pmpkg_t *pkg = j->data;
+ if(_alpm_sync_pkg(pkg) == -1) {
+ if(pm_errno == PM_ERR_TRANS_DUP_TARGET || pm_errno == PM_ERR_PKG_IGNORED) {
+ /* just skip duplicate or ignored targets */
+ continue;
+ } else {
+ return(-1);
+ }
+ }
+ }
+ }
+ }
+
+ if(!found) {
+ RET_ERR(PM_ERR_PKG_NOT_FOUND, -1);
+ }
return(0);
}
+/** Add a sync target to the transaction.
+ * @param target the name of the sync target to add
+ * @return 0 on success, -1 on error (pm_errno is set accordingly)
+ */
+int SYMEXPORT alpm_sync_dbtarget(char *dbname, char *target)
+{
+ alpm_list_t *i;
+ alpm_list_t *dbs_sync;
+
+ ALPM_LOG_FUNC;
+
+ /* Sanity checks */
+ ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1));
+ dbs_sync = handle->dbs_sync;
+
+ /* we are looking for a package in a specific database */
+ alpm_list_t *dbs = NULL;
+ _alpm_log(PM_LOG_DEBUG, "searching for target '%s' in repo '%s'\n", target, dbname);
+ for(i = dbs_sync; i; i = i->next) {
+ pmdb_t *db = i->data;
+ if(strcmp(db->treename, dbname) == 0) {
+ dbs = alpm_list_add(NULL, db);
+ break;
+ }
+ }
+ if(dbs == NULL) {
+ RET_ERR(PM_ERR_PKG_REPO_NOT_FOUND, -1);
+ }
+ return(_alpm_sync_target(dbs, target));
+}
+
+/** Add a sync target to the transaction.
+ * @param target the name of the sync target to add
+ * @return 0 on success, -1 on error (pm_errno is set accordingly)
+ */
+int SYMEXPORT alpm_sync_target(char *target)
+{
+ alpm_list_t *dbs_sync;
+
+ ALPM_LOG_FUNC;
+
+ /* Sanity checks */
+ ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1));
+ dbs_sync = handle->dbs_sync;
+
+ return(_alpm_sync_target(dbs_sync,target));
+}
+
/** Compute the size of the files that will be downloaded to install a
* package.
* @param newpkg the new package to upgrade to
@@ -282,6 +355,11 @@ static int compute_download_size(pmpkg_t *newpkg)
char *fpath;
off_t size = 0;
+ if(newpkg->origin == PKG_FROM_FILE) {
+ newpkg->download_size = 0;
+ return(0);
+ }
+
fname = alpm_pkg_get_filename(newpkg);
ASSERT(fname != NULL, RET_ERR(PM_ERR_PKG_INVALID_NAME, -1));
fpath = _alpm_filecache_find(fname);
@@ -321,10 +399,9 @@ static int compute_download_size(pmpkg_t *newpkg)
int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, alpm_list_t **data)
{
alpm_list_t *deps = NULL;
- alpm_list_t *preferred = NULL;
alpm_list_t *unresolvable = NULL;
- alpm_list_t *remove = NULL; /* allow checkdeps usage with trans->packages */
alpm_list_t *i, *j;
+ alpm_list_t *remove = NULL;
int ret = 0;
ALPM_LOG_FUNC;
@@ -344,32 +421,29 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
EVENT(trans, PM_TRANS_EVT_RESOLVEDEPS_START, NULL, NULL);
_alpm_log(PM_LOG_DEBUG, "resolving target's dependencies\n");
- /* build remove list and preferred list for resolvedeps */
- for(i = trans->packages; i; i = i->next) {
+ /* build remove list for resolvedeps */
+ for(i = trans->add; i; i = i->next) {
pmpkg_t *spkg = i->data;
for(j = spkg->removes; j; j = j->next) {
remove = alpm_list_add(remove, j->data);
}
- preferred = alpm_list_add(preferred, spkg);
}
/* Resolve packages in the transaction one at a time, in addtion
building up a list of packages which could not be resolved. */
- for(i = trans->packages; i; i = i->next) {
+ for(i = trans->add; i; i = i->next) {
pmpkg_t *pkg = i->data;
- if(_alpm_resolvedeps(db_local, dbs_sync, pkg, preferred,
+ if(_alpm_resolvedeps(db_local, dbs_sync, pkg, trans->add,
&resolved, remove, data) == -1) {
unresolvable = alpm_list_add(unresolvable, pkg);
}
/* Else, [resolved] now additionally contains [pkg] and all of its
dependencies not already on the list */
}
- alpm_list_free(preferred);
/* If there were unresolvable top-level packages, prompt the user to
see if they'd like to ignore them rather than failing the sync */
if(unresolvable != NULL) {
- unresolvable = alpm_list_remove_dupes(unresolvable);
int remove_unresolvable = 0;
QUESTION(handle->trans, PM_TRANS_CONV_REMOVE_PKGS, unresolvable,
NULL, NULL, &remove_unresolvable);
@@ -392,21 +466,21 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
}
}
- /* Unresolvable packages will be removed from the target list, so
- we free the transaction specific fields */
- alpm_list_free_inner(unresolvable, (alpm_list_fn_free)_alpm_pkg_free_trans);
-
/* Set DEPEND reason for pulled packages */
for(i = resolved; i; i = i->next) {
pmpkg_t *pkg = i->data;
- if(!_alpm_pkg_find(trans->packages, pkg->name)) {
+ if(!_alpm_pkg_find(trans->add, pkg->name)) {
pkg->reason = PM_PKG_REASON_DEPEND;
}
}
+ /* Unresolvable packages will be removed from the target list, so
+ we free the transaction specific fields */
+ alpm_list_free_inner(unresolvable, (alpm_list_fn_free)_alpm_pkg_free_trans);
+
/* re-order w.r.t. dependencies */
- alpm_list_free(trans->packages);
- trans->packages = _alpm_sortbydeps(resolved, 0);
+ alpm_list_free(trans->add);
+ trans->add = _alpm_sortbydeps(resolved, 0);
alpm_list_free(resolved);
EVENT(trans, PM_TRANS_EVT_RESOLVEDEPS_DONE, NULL, NULL);
@@ -420,15 +494,15 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
/* 1. check for conflicts in the target list */
_alpm_log(PM_LOG_DEBUG, "check targets vs targets\n");
- deps = _alpm_innerconflicts(trans->packages);
+ deps = _alpm_innerconflicts(trans->add);
for(i = deps; i; i = i->next) {
pmconflict_t *conflict = i->data;
pmpkg_t *rsync, *sync, *sync1, *sync2;
/* have we already removed one of the conflicting targets? */
- sync1 = _alpm_pkg_find(trans->packages, conflict->package1);
- sync2 = _alpm_pkg_find(trans->packages, conflict->package2);
+ sync1 = _alpm_pkg_find(trans->add, conflict->package1);
+ sync2 = _alpm_pkg_find(trans->add, conflict->package2);
if(!sync1 || !sync2) {
continue;
}
@@ -468,8 +542,8 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
_alpm_log(PM_LOG_WARNING,
_("removing '%s' from target list because it conflicts with '%s'\n"),
rsync->name, sync->name);
+ trans->add = alpm_list_remove(trans->add, rsync, _alpm_pkg_cmp, NULL);
_alpm_pkg_free_trans(rsync); /* rsync is not transaction target anymore */
- trans->packages = alpm_list_remove(trans->packages, rsync, _alpm_pkg_cmp, NULL);
continue;
}
@@ -479,7 +553,7 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
/* 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, trans->packages);
+ deps = _alpm_outerconflicts(db_local, trans->add);
for(i = deps; i; i = i->next) {
pmconflict_t *conflict = i->data;
@@ -487,7 +561,7 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
/* 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) {
+ for(j = trans->add; j && !found; j = j->next) {
pmpkg_t *spkg = j->data;
if(_alpm_pkg_find(spkg->removes, conflict->package2)) {
found = 1;
@@ -500,11 +574,11 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
_alpm_log(PM_LOG_DEBUG, "package '%s' conflicts with '%s'\n",
conflict->package1, conflict->package2);
- pmpkg_t *sync = _alpm_pkg_find(trans->packages, conflict->package1);
+ pmpkg_t *sync = _alpm_pkg_find(trans->add, 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);
+ conflict->package2, conflict->reason, &doremove);
if(doremove) {
/* append to the removes list */
_alpm_log(PM_LOG_DEBUG, "electing '%s' for removal\n", conflict->package2);
@@ -529,19 +603,17 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
alpm_list_free(deps);
}
- if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) {
- /* rebuild remove list */
- alpm_list_free(remove);
- remove = NULL;
- for(i = trans->packages; i; i = i->next) {
- pmpkg_t *spkg = i->data;
- for(j = spkg->removes; j; j = j->next) {
- remove = alpm_list_add(remove, j->data);
- }
+ /* Build trans->remove list */
+ for(i = trans->add; i; i = i->next) {
+ pmpkg_t *spkg = i->data;
+ for(j = spkg->removes; j; j = j->next) {
+ trans->remove = alpm_list_add(trans->remove, _alpm_pkg_dup(j->data));
}
+ }
+ if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) {
_alpm_log(PM_LOG_DEBUG, "checking dependencies\n");
- deps = alpm_checkdeps(_alpm_db_get_pkgcache(db_local), 1, remove, trans->packages);
+ deps = alpm_checkdeps(_alpm_db_get_pkgcache(db_local), 1, trans->remove, trans->add);
if(deps) {
pm_errno = PM_ERR_UNSATISFIED_DEPS;
ret = -1;
@@ -554,7 +626,7 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
goto cleanup;
}
}
- for(i = trans->packages; i; i = i->next) {
+ for(i = trans->add; i; i = i->next) {
/* update download size field */
pmpkg_t *spkg = i->data;
if(compute_download_size(spkg) != 0) {
@@ -564,8 +636,8 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
}
cleanup:
- alpm_list_free(remove);
alpm_list_free(unresolvable);
+ alpm_list_free(remove);
return(ret);
}
@@ -601,7 +673,7 @@ static int apply_deltas(pmtrans_t *trans)
int ret = 0;
const char *cachedir = _alpm_filecache_setup();
- for(i = trans->packages; i; i = i->next) {
+ for(i = trans->add; i; i = i->next) {
pmpkg_t *spkg = i->data;
alpm_list_t *delta_path = spkg->delta_path;
alpm_list_t *dlts = NULL;
@@ -614,7 +686,7 @@ static int apply_deltas(pmtrans_t *trans)
pmdelta_t *d = dlts->data;
char *delta, *from, *to;
char command[PATH_MAX];
- int len = 0;
+ size_t len = 0;
delta = _alpm_filecache_find(d->delta);
/* the initial package might be in a different cachedir */
@@ -711,7 +783,6 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
{
alpm_list_t *i, *j, *files = NULL;
alpm_list_t *deltas = NULL;
- pmtrans_t *tr_remove = NULL, *tr_upgrade = NULL;
int replaces = 0;
int errors = 0;
const char *cachedir = NULL;
@@ -730,7 +801,7 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
if(handle->totaldlcb) {
off_t total_size = (off_t)0;
/* sum up the download size for each package and store total */
- for(i = trans->packages; i; i = i->next) {
+ for(i = trans->add; i; i = i->next) {
pmpkg_t *spkg = i->data;
total_size += spkg->download_size;
}
@@ -741,11 +812,10 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
for(i = handle->dbs_sync; i; i = i->next) {
pmdb_t *current = i->data;
- for(j = trans->packages; j; j = j->next) {
+ for(j = trans->add; j; j = j->next) {
pmpkg_t *spkg = j->data;
- pmdb_t *dbs = spkg->origin_data.db;
- if(current == dbs) {
+ if(spkg->origin == PKG_FROM_CACHE && current == spkg->origin_data.db) {
const char *fname = NULL;
fname = alpm_pkg_get_filename(spkg);
@@ -835,15 +905,36 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
EVENT(trans, PM_TRANS_EVT_INTEGRITY_START, NULL, NULL);
errors = 0;
- for(i = trans->packages; i; i = i->next) {
+ for(i = trans->add; i; i = i->next) {
pmpkg_t *spkg = i->data;
+ if(spkg->origin == PKG_FROM_FILE) {
+ continue; /* pkg_load() has been already called, this package is valid */
+ }
+
const char *filename = alpm_pkg_get_filename(spkg);
const char *md5sum = alpm_pkg_get_md5sum(spkg);
if(test_md5sum(trans, filename, md5sum) != 0) {
errors++;
*data = alpm_list_add(*data, strdup(filename));
+ continue;
+ }
+ /* load the package file and replace pkgcache entry with it in the target list */
+ /* TODO: alpm_pkg_get_db() will not work on this target anymore */
+ _alpm_log(PM_LOG_DEBUG, "replacing pkgcache entry with package file for target %s\n", spkg->name);
+ char *filepath = _alpm_filecache_find(filename);
+ pmpkg_t *pkgfile;
+ if(alpm_pkg_load(filepath, 1, &pkgfile) != 0) {
+ _alpm_pkg_free(pkgfile);
+ errors++;
+ *data = alpm_list_add(*data, strdup(filename));
+ FREE(filepath);
+ continue;
}
+ FREE(filepath);
+ pkgfile->reason = spkg->reason; /* copy over install reason */
+ i->data = pkgfile;
+ _alpm_pkg_free_trans(spkg); /* spkg has been removed from the target list */
}
if(errors) {
pm_errno = PM_ERR_PKG_INVALID;
@@ -856,71 +947,15 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
trans->state = STATE_COMMITING;
- /* Create remove and upgrade transactions */
- tr_remove = _alpm_trans_new();
- if(tr_remove == NULL) {
- _alpm_log(PM_LOG_ERROR, _("could not create removal transaction\n"));
- goto error;
- }
- tr_upgrade = _alpm_trans_new();
- if(tr_upgrade == NULL) {
- _alpm_log(PM_LOG_ERROR, _("could not create transaction\n"));
- goto error;
- }
-
- if(_alpm_trans_init(tr_remove, PM_TRANS_TYPE_REMOVE, PM_TRANS_FLAG_NODEPS, NULL, NULL, NULL) == -1) {
- _alpm_log(PM_LOG_ERROR, _("could not initialize the removal transaction\n"));
- goto error;
- }
- if(_alpm_trans_init(tr_upgrade, PM_TRANS_TYPE_UPGRADE, trans->flags, trans->cb_event, trans->cb_conv, trans->cb_progress) == -1) {
- _alpm_log(PM_LOG_ERROR, _("could not initialize transaction\n"));
- goto error;
- }
-
- /* adding targets */
- for(i = trans->packages; i; i = i->next) {
- pmpkg_t *spkg = i->data;
- alpm_list_t *j;
- /* remove transaction */
- for(j = spkg->removes; j; j = j->next) {
- pmpkg_t *pkg = j->data;
- if(!_alpm_pkg_find(tr_remove->packages, pkg->name)) {
- if(_alpm_trans_addtarget(tr_remove, pkg->name) == -1) {
- goto error;
- }
- replaces++;
- }
- }
- /* upgrade transaction */
- const char *fname;
- char *fpath;
-
- fname = alpm_pkg_get_filename(spkg);
- if(fname == NULL) {
- goto error;
- }
- /* Loop through the cache dirs until we find a matching file */
- fpath = _alpm_filecache_find(fname);
-
- if(_alpm_trans_addtarget(tr_upgrade, fpath) == -1) {
- FREE(fpath);
- goto error;
- }
- FREE(fpath);
-
- /* using alpm_list_last() is ok because addtarget() adds the new target at the
- * end of the tr->packages list */
- pmpkg_t *ipkg = alpm_list_last(tr_upgrade->packages)->data;
- ipkg->reason = spkg->reason;
- }
+ replaces = alpm_list_count(trans->remove);
/* fileconflict check */
if(!(trans->flags & PM_TRANS_FLAG_FORCE)) {
EVENT(trans, PM_TRANS_EVT_FILECONFLICTS_START, NULL, NULL);
_alpm_log(PM_LOG_DEBUG, "looking for file conflicts\n");
- alpm_list_t *conflict = _alpm_db_find_fileconflicts(db_local, tr_upgrade,
- tr_upgrade->packages, tr_remove->packages);
+ alpm_list_t *conflict = _alpm_db_find_fileconflicts(db_local, trans,
+ trans->add, trans->remove);
if(conflict) {
pm_errno = PM_ERR_FILE_CONFLICTS;
if(data) {
@@ -938,14 +973,8 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
/* remove conflicting and to-be-replaced packages */
if(replaces) {
_alpm_log(PM_LOG_DEBUG, "removing conflicting and to-be-replaced packages\n");
- if(_alpm_trans_prepare(tr_remove, data) == -1) {
- _alpm_log(PM_LOG_ERROR, _("could not prepare removal transaction\n"));
- goto error;
- }
/* we want the frontend to be aware of commit details */
- tr_remove->cb_event = trans->cb_event;
- tr_remove->cb_progress = trans->cb_progress;
- if(_alpm_trans_commit(tr_remove, NULL) == -1) {
+ if(_alpm_remove_packages(trans, handle->db_local) == -1) {
_alpm_log(PM_LOG_ERROR, _("could not commit removal transaction\n"));
goto error;
}
@@ -953,8 +982,7 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
/* install targets */
_alpm_log(PM_LOG_DEBUG, "installing packages\n");
- /* add_prepare is not needed */
- if(_alpm_trans_commit(tr_upgrade, NULL) == -1) {
+ if(_alpm_upgrade_packages(trans, handle->db_local) == -1) {
_alpm_log(PM_LOG_ERROR, _("could not commit transaction\n"));
goto error;
}
@@ -963,8 +991,6 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
error:
FREELIST(files);
alpm_list_free(deltas);
- _alpm_trans_free(tr_remove);
- _alpm_trans_free(tr_upgrade);
return(ret);
}
diff --git a/lib/libalpm/sync.h b/lib/libalpm/sync.h
index c2905a45..b432b69e 100644
--- a/lib/libalpm/sync.h
+++ b/lib/libalpm/sync.h
@@ -24,9 +24,6 @@
#include "alpm.h"
-int _alpm_sync_sysupgrade(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, int enable_downgrade);
-
-int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, char *name);
int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, alpm_list_t **data);
int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data);
diff --git a/lib/libalpm/trans.c b/lib/libalpm/trans.c
index 6e847e64..4879d236 100644
--- a/lib/libalpm/trans.c
+++ b/lib/libalpm/trans.c
@@ -52,17 +52,18 @@
*/
/** Initialize the transaction.
- * @param type type of the transaction
* @param flags flags of the transaction (like nodeps, etc)
* @param event event callback function pointer
* @param conv question callback function pointer
* @param progress progress callback function pointer
* @return 0 on success, -1 on error (pm_errno is set accordingly)
*/
-int SYMEXPORT alpm_trans_init(pmtranstype_t type, pmtransflag_t flags,
+int SYMEXPORT alpm_trans_init(pmtransflag_t flags,
alpm_trans_cb_event event, alpm_trans_cb_conv conv,
alpm_trans_cb_progress progress)
{
+ pmtrans_t *trans;
+
ALPM_LOG_FUNC;
/* Sanity checks */
@@ -78,38 +79,53 @@ int SYMEXPORT alpm_trans_init(pmtranstype_t type, pmtransflag_t flags,
}
}
- handle->trans = _alpm_trans_new();
- if(handle->trans == NULL) {
+ trans = _alpm_trans_new();
+ if(trans == NULL) {
RET_ERR(PM_ERR_MEMORY, -1);
}
- return(_alpm_trans_init(handle->trans, type, flags, event, conv, progress));
-}
-
-/** Search for packages to upgrade and add them to the transaction.
- * @return 0 on success, -1 on error (pm_errno is set accordingly)
- */
-int SYMEXPORT alpm_trans_sysupgrade(int enable_downgrade)
-{
- pmtrans_t *trans;
+ trans->flags = flags;
+ trans->cb_event = event;
+ trans->cb_conv = conv;
+ trans->cb_progress = progress;
+ trans->state = STATE_INITIALIZED;
- ALPM_LOG_FUNC;
+ handle->trans = trans;
- ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1));
+ return(0);
+}
- trans = handle->trans;
- ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
- ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1));
- ASSERT(trans->type == PM_TRANS_TYPE_SYNC, RET_ERR(PM_ERR_TRANS_TYPE, -1));
+static alpm_list_t *check_arch(alpm_list_t *pkgs)
+{
+ alpm_list_t *i;
+ alpm_list_t *invalid = NULL;
- return(_alpm_sync_sysupgrade(trans, handle->db_local, handle->dbs_sync, enable_downgrade));
+ const char *arch = alpm_option_get_arch();
+ if(!arch) {
+ return(NULL);
+ }
+ for(i = pkgs; i; i = i->next) {
+ pmpkg_t *pkg = i->data;
+ const char *pkgarch = alpm_pkg_get_arch(pkg);
+ if(strcmp(pkgarch,arch) && strcmp(pkgarch,"any")) {
+ char *string;
+ const char *pkgname = alpm_pkg_get_name(pkg);
+ const char *pkgver = alpm_pkg_get_version(pkg);
+ size_t len = strlen(pkgname) + strlen(pkgver) + strlen(pkgarch) + 3;
+ MALLOC(string, len, RET_ERR(PM_ERR_MEMORY, invalid));
+ sprintf(string, "%s-%s-%s", pkgname, pkgver, pkgarch);
+ invalid = alpm_list_add(invalid, string);
+ }
+ }
+ return(invalid);
}
-/** Add a target to the transaction.
- * @param target the name of the target to add
+/** Prepare a transaction.
+ * @param data the address of an alpm_list where detailed description
+ * of an error can be dumped (ie. list of conflicting files)
* @return 0 on success, -1 on error (pm_errno is set accordingly)
*/
-int SYMEXPORT alpm_trans_addtarget(char *target)
+int SYMEXPORT alpm_trans_prepare(alpm_list_t **data)
{
pmtrans_t *trans;
@@ -117,32 +133,41 @@ int SYMEXPORT alpm_trans_addtarget(char *target)
/* Sanity checks */
ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1));
- ASSERT(target != NULL && strlen(target) != 0, RET_ERR(PM_ERR_WRONG_ARGS, -1));
+ ASSERT(data != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1));
trans = handle->trans;
+
ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1));
- return(_alpm_trans_addtarget(trans, target));
-}
+ /* If there's nothing to do, return without complaining */
+ if(trans->add == NULL && trans->remove == NULL) {
+ return(0);
+ }
-/** Prepare a transaction.
- * @param data the address of an alpm_list where detailed description
- * of an error can be dumped (ie. list of conflicting files)
- * @return 0 on success, -1 on error (pm_errno is set accordingly)
- */
-int SYMEXPORT alpm_trans_prepare(alpm_list_t **data)
-{
- ALPM_LOG_FUNC;
+ alpm_list_t *invalid = check_arch(trans->add);
+ if(invalid) {
+ if(data) {
+ *data = invalid;
+ }
+ RET_ERR(PM_ERR_PKG_INVALID_ARCH, -1);
+ }
- /* Sanity checks */
- ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1));
- ASSERT(data != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1));
+ if(trans->add == NULL) {
+ if(_alpm_remove_prepare(trans, handle->db_local, data) == -1) {
+ /* pm_errno is set by _alpm_remove_prepare() */
+ return(-1);
+ }
+ } else {
+ if(_alpm_sync_prepare(trans, handle->db_local, handle->dbs_sync, data) == -1) {
+ /* pm_errno is set by _alpm_sync_prepare() */
+ return(-1);
+ }
+ }
- ASSERT(handle->trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
- ASSERT(handle->trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1));
+ trans->state = STATE_PREPARED;
- return(_alpm_trans_prepare(handle->trans, data));
+ return(0);
}
/** Commit a transaction.
@@ -152,17 +177,42 @@ int SYMEXPORT alpm_trans_prepare(alpm_list_t **data)
*/
int SYMEXPORT alpm_trans_commit(alpm_list_t **data)
{
+ pmtrans_t *trans;
+
ALPM_LOG_FUNC;
/* Sanity checks */
ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1));
- ASSERT(handle->trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
- ASSERT(handle->trans->state == STATE_PREPARED, RET_ERR(PM_ERR_TRANS_NOT_PREPARED, -1));
+ trans = handle->trans;
+
+ ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
+ ASSERT(trans->state == STATE_PREPARED, RET_ERR(PM_ERR_TRANS_NOT_PREPARED, -1));
+
+ ASSERT(!(trans->flags & PM_TRANS_FLAG_NOLOCK), RET_ERR(PM_ERR_TRANS_NOT_LOCKED, -1));
+
+ /* If there's nothing to do, return without complaining */
+ if(trans->add == NULL && trans->remove == NULL) {
+ return(0);
+ }
+
+ trans->state = STATE_COMMITING;
- ASSERT(!(handle->trans->flags & PM_TRANS_FLAG_NOLOCK), RET_ERR(PM_ERR_TRANS_NOT_LOCKED, -1));
+ if(trans->add == NULL) {
+ if(_alpm_remove_packages(trans, handle->db_local) == -1) {
+ /* pm_errno is set by _alpm_remove_commit() */
+ return(-1);
+ }
+ } else {
+ if(_alpm_sync_commit(trans, handle->db_local, data) == -1) {
+ /* pm_errno is set by _alpm_sync_commit() */
+ return(-1);
+ }
+ }
- return(_alpm_trans_commit(handle->trans, data));
+ trans->state = STATE_COMMITED;
+
+ return(0);
}
/** Interrupt a transaction.
@@ -203,7 +253,7 @@ int SYMEXPORT alpm_trans_release()
ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
ASSERT(trans->state != STATE_IDLE, RET_ERR(PM_ERR_TRANS_NULL, -1));
- unsigned int nolock_flag = trans->flags & PM_TRANS_FLAG_NOLOCK;
+ int nolock_flag = trans->flags & PM_TRANS_FLAG_NOLOCK;
_alpm_trans_free(trans);
handle->trans = NULL;
@@ -211,7 +261,10 @@ int SYMEXPORT alpm_trans_release()
/* unlock db */
if(!nolock_flag) {
if(handle->lckfd != -1) {
- while(close(handle->lckfd) == -1 && errno == EINTR);
+ int fd;
+ do {
+ fd = close(handle->lckfd);
+ } while(fd == -1 && errno == EINTR);
handle->lckfd = -1;
}
if(_alpm_lckrm()) {
@@ -247,12 +300,10 @@ void _alpm_trans_free(pmtrans_t *trans)
return;
}
- if(trans->type == PM_TRANS_TYPE_SYNC) {
- alpm_list_free_inner(trans->packages, (alpm_list_fn_free)_alpm_pkg_free_trans);
- } else {
- alpm_list_free_inner(trans->packages, (alpm_list_fn_free)_alpm_pkg_free);
- }
- alpm_list_free(trans->packages);
+ alpm_list_free_inner(trans->add, (alpm_list_fn_free)_alpm_pkg_free_trans);
+ alpm_list_free(trans->add);
+ alpm_list_free_inner(trans->remove, (alpm_list_fn_free)_alpm_pkg_free);
+ alpm_list_free(trans->remove);
FREELIST(trans->skip_add);
FREELIST(trans->skip_remove);
@@ -260,150 +311,6 @@ void _alpm_trans_free(pmtrans_t *trans)
FREE(trans);
}
-int _alpm_trans_init(pmtrans_t *trans, pmtranstype_t type, pmtransflag_t flags,
- alpm_trans_cb_event event, alpm_trans_cb_conv conv,
- alpm_trans_cb_progress progress)
-{
- ALPM_LOG_FUNC;
-
- /* Sanity checks */
- ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
-
- trans->type = type;
- trans->flags = flags;
- trans->cb_event = event;
- trans->cb_conv = conv;
- trans->cb_progress = progress;
- trans->state = STATE_INITIALIZED;
-
- return(0);
-}
-
-/** Add a target to the transaction.
- * @param trans the current transaction
- * @param target the name of the target to add
- * @return 0 on success, -1 on error (pm_errno is set accordingly)
- */
-int _alpm_trans_addtarget(pmtrans_t *trans, char *target)
-{
- ALPM_LOG_FUNC;
-
- /* Sanity checks */
- ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
- ASSERT(target != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1));
-
- switch(trans->type) {
- case PM_TRANS_TYPE_UPGRADE:
- if(_alpm_add_loadtarget(trans, handle->db_local, target) == -1) {
- /* pm_errno is set by _alpm_add_loadtarget() */
- return(-1);
- }
- break;
- case PM_TRANS_TYPE_REMOVE:
- case PM_TRANS_TYPE_REMOVEUPGRADE:
- if(_alpm_remove_loadtarget(trans, handle->db_local, target) == -1) {
- /* pm_errno is set by _alpm_remove_loadtarget() */
- return(-1);
- }
- break;
- case PM_TRANS_TYPE_SYNC:
- if(_alpm_sync_addtarget(trans, handle->db_local, handle->dbs_sync, target) == -1) {
- /* pm_errno is set by _alpm_sync_loadtarget() */
- return(-1);
- }
- break;
- }
-
- return(0);
-}
-
-int _alpm_trans_prepare(pmtrans_t *trans, alpm_list_t **data)
-{
- if(data) {
- *data = NULL;
- }
-
- ALPM_LOG_FUNC;
-
- /* Sanity checks */
- ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
-
- /* If there's nothing to do, return without complaining */
- if(trans->packages == NULL) {
- return(0);
- }
-
- switch(trans->type) {
- case PM_TRANS_TYPE_UPGRADE:
- if(_alpm_add_prepare(trans, handle->db_local, data) == -1) {
- /* pm_errno is set by _alpm_add_prepare() */
- return(-1);
- }
- break;
- case PM_TRANS_TYPE_REMOVE:
- case PM_TRANS_TYPE_REMOVEUPGRADE:
- if(_alpm_remove_prepare(trans, handle->db_local, data) == -1) {
- /* pm_errno is set by _alpm_remove_prepare() */
- return(-1);
- }
- break;
- case PM_TRANS_TYPE_SYNC:
- if(_alpm_sync_prepare(trans, handle->db_local, handle->dbs_sync, data) == -1) {
- /* pm_errno is set by _alpm_sync_prepare() */
- return(-1);
- }
- break;
- }
-
- trans->state = STATE_PREPARED;
-
- return(0);
-}
-
-int _alpm_trans_commit(pmtrans_t *trans, alpm_list_t **data)
-{
- ALPM_LOG_FUNC;
-
- if(data!=NULL)
- *data = NULL;
-
- /* Sanity checks */
- ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
-
- /* If there's nothing to do, return without complaining */
- if(trans->packages == NULL) {
- return(0);
- }
-
- trans->state = STATE_COMMITING;
-
- switch(trans->type) {
- case PM_TRANS_TYPE_UPGRADE:
- if(_alpm_add_commit(trans, handle->db_local) == -1) {
- /* pm_errno is set by _alpm_add_commit() */
- return(-1);
- }
- break;
- case PM_TRANS_TYPE_REMOVE:
- case PM_TRANS_TYPE_REMOVEUPGRADE:
- if(_alpm_remove_commit(trans, handle->db_local) == -1) {
- /* pm_errno is set by _alpm_remove_commit() */
- return(-1);
- }
- break;
- case PM_TRANS_TYPE_SYNC:
- if(_alpm_sync_commit(trans, handle->db_local, data) == -1) {
- /* pm_errno is set by _alpm_sync_commit() */
- return(-1);
- }
- break;
- }
-
- trans->state = STATE_COMMITED;
-
- return(0);
-}
-
/* A cheap grep for text files, returns 1 if a substring
* was found in the text file fn, 0 if it wasn't
*/
@@ -416,7 +323,8 @@ static int grep(const char *fn, const char *needle)
}
while(!feof(fp)) {
char line[1024];
- fgets(line, 1024, fp);
+ int sline = sizeof(line)-1;
+ fgets(line, sline, fp);
if(feof(fp)) {
continue;
}
@@ -464,7 +372,7 @@ int _alpm_runscriptlet(const char *root, const char *installfn,
/* either extract or copy the scriptlet */
snprintf(scriptfn, PATH_MAX, "%s/.INSTALL", tmpdir);
if(!strcmp(script, "pre_upgrade") || !strcmp(script, "pre_install")) {
- if(_alpm_unpack(installfn, tmpdir, ".INSTALL")) {
+ if(_alpm_unpack_single(installfn, tmpdir, ".INSTALL")) {
retval = 1;
}
} else {
@@ -503,30 +411,30 @@ cleanup:
return(retval);
}
-pmtranstype_t SYMEXPORT alpm_trans_get_type()
+int SYMEXPORT alpm_trans_get_flags()
{
/* Sanity checks */
ASSERT(handle != NULL, return(-1));
ASSERT(handle->trans != NULL, return(-1));
- return handle->trans->type;
+ return handle->trans->flags;
}
-unsigned int SYMEXPORT alpm_trans_get_flags()
+alpm_list_t SYMEXPORT * alpm_trans_get_add()
{
/* Sanity checks */
- ASSERT(handle != NULL, return(-1));
- ASSERT(handle->trans != NULL, return(-1));
+ ASSERT(handle != NULL, return(NULL));
+ ASSERT(handle->trans != NULL, return(NULL));
- return handle->trans->flags;
+ return handle->trans->add;
}
-alpm_list_t SYMEXPORT * alpm_trans_get_pkgs()
+alpm_list_t SYMEXPORT * alpm_trans_get_remove()
{
/* Sanity checks */
ASSERT(handle != NULL, return(NULL));
ASSERT(handle->trans != NULL, return(NULL));
- return handle->trans->packages;
+ return handle->trans->remove;
}
/* vim: set ts=2 sw=2 noet: */
diff --git a/lib/libalpm/trans.h b/lib/libalpm/trans.h
index 0537bc72..ca1e141a 100644
--- a/lib/libalpm/trans.h
+++ b/lib/libalpm/trans.h
@@ -37,10 +37,10 @@ typedef enum _pmtransstate_t {
/* Transaction */
struct __pmtrans_t {
- pmtranstype_t type;
pmtransflag_t flags;
pmtransstate_t state;
- alpm_list_t *packages; /* list of (pmpkg_t *) */
+ alpm_list_t *add; /* list of (pmpkg_t *) */
+ alpm_list_t *remove; /* list of (pmpkg_t *) */
alpm_list_t *skip_add; /* list of (char *) */
alpm_list_t *skip_remove; /* list of (char *) */
alpm_trans_cb_event cb_event;
@@ -69,12 +69,9 @@ do { \
pmtrans_t *_alpm_trans_new(void);
void _alpm_trans_free(pmtrans_t *trans);
-int _alpm_trans_init(pmtrans_t *trans, pmtranstype_t type, pmtransflag_t flags,
+int _alpm_trans_init(pmtrans_t *trans, pmtransflag_t flags,
alpm_trans_cb_event event, alpm_trans_cb_conv conv,
alpm_trans_cb_progress progress);
-int _alpm_trans_addtarget(pmtrans_t *trans, char *target);
-int _alpm_trans_prepare(pmtrans_t *trans, alpm_list_t **data);
-int _alpm_trans_commit(pmtrans_t *trans, alpm_list_t **data);
int _alpm_runscriptlet(const char *root, const char *installfn,
const char *script, const char *ver,
const char *oldver, pmtrans_t *trans);
diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c
index 2b006e21..27e861e4 100644
--- a/lib/libalpm/util.c
+++ b/lib/libalpm/util.c
@@ -175,7 +175,7 @@ char *_alpm_strtrim(char *str)
return(str);
}
- while(isspace((int)*pch)) {
+ while(isspace((unsigned char)*pch)) {
pch++;
}
if(pch != str) {
@@ -188,7 +188,7 @@ char *_alpm_strtrim(char *str)
}
pch = (str + (strlen(str) - 1));
- while(isspace((int)*pch)) {
+ while(isspace((unsigned char)*pch)) {
pch--;
}
*++pch = '\0';
@@ -196,57 +196,11 @@ char *_alpm_strtrim(char *str)
return(str);
}
-/* Helper function for _alpm_strreplace */
-static void _strnadd(char **str, const char *append, unsigned int count)
-{
- if(*str) {
- *str = realloc(*str, strlen(*str) + count + 1);
- } else {
- *str = calloc(count + 1, sizeof(char));
- }
-
- strncat(*str, append, count);
-}
-
-/* Replace all occurances of 'needle' with 'replace' in 'str', returning
- * a new string (must be free'd) */
-char *_alpm_strreplace(const char *str, const char *needle, const char *replace)
-{
- const char *p, *q;
- p = q = str;
-
- char *newstr = NULL;
- unsigned int needlesz = strlen(needle),
- replacesz = strlen(replace);
-
- while (1) {
- q = strstr(p, needle);
- if(!q) { /* not found */
- if(*p) {
- /* add the rest of 'p' */
- _strnadd(&newstr, p, strlen(p));
- }
- break;
- } else { /* found match */
- if(q > p){
- /* add chars between this occurance and last occurance, if any */
- _strnadd(&newstr, p, q - p);
- }
- _strnadd(&newstr, replace, replacesz);
- p = q + needlesz;
- }
- }
-
- return newstr;
-}
-
-
/* Create a lock file */
int _alpm_lckmk()
{
int fd;
- pid_t pid;
- char *dir, *ptr, *spid = NULL;
+ char *dir, *ptr;
const char *file = alpm_option_get_lockfile();
/* create the dir of the lockfile first */
@@ -258,16 +212,15 @@ int _alpm_lckmk()
_alpm_makepath(dir);
FREE(dir);
- while((fd = open(file, O_WRONLY | O_CREAT | O_EXCL, 0000)) == -1
- && errno == EINTR);
+ do {
+ fd = open(file, O_WRONLY | O_CREAT | O_EXCL, 0000);
+ } while (fd == -1 && errno == EINTR);
if(fd > 0) {
- pid = getpid();
- size_t len = snprintf(spid, 0, "%ld\n", (long)pid) + 1;
- spid = malloc(len);
- snprintf(spid, len, "%ld\n", (long)pid);
- while(write(fd, (void *)spid, len) == -1 && errno == EINTR);
+ FILE *f = fdopen(fd, "w");
+ fprintf(f, "%ld\n", (long)getpid());
+ fflush(f);
fsync(fd);
- free(spid);
+ fclose(f);
return(fd);
}
return(-1);
@@ -286,14 +239,38 @@ int _alpm_lckrm()
/* Compression functions */
/**
- * @brief Unpack a specific file or all files in an archive.
+ * @brief Unpack a specific file in an archive.
*
* @param archive the archive to unpack
* @param prefix where to extract the files
- * @param fn a file within the archive to unpack or NULL for all
+ * @param fn a file within the archive to unpack
* @return 0 on success, 1 on failure
*/
-int _alpm_unpack(const char *archive, const char *prefix, const char *fn)
+int _alpm_unpack_single(const char *archive, const char *prefix, const char *fn)
+{
+ alpm_list_t *list = NULL;
+ int ret = 0;
+ if(fn == NULL) {
+ return(1);
+ }
+ list = alpm_list_add(list, (void *)fn);
+ ret = _alpm_unpack(archive, prefix, list, 1);
+ alpm_list_free(list);
+ return(ret);
+}
+
+/**
+ * @brief Unpack a list of files in an archive.
+ *
+ * @param archive the archive to unpack
+ * @param prefix where to extract the files
+ * @param list a list of files within the archive to unpack or
+ * NULL for all
+ * @param breakfirst break after the first entry found
+ *
+ * @return 0 on success, 1 on failure
+ */
+int _alpm_unpack(const char *archive, const char *prefix, alpm_list_t *list, int breakfirst)
{
int ret = 0;
mode_t oldmask;
@@ -339,21 +316,30 @@ int _alpm_unpack(const char *archive, const char *prefix, const char *fn)
st = archive_entry_stat(entry);
entryname = archive_entry_pathname(entry);
-
+
if(S_ISREG(st->st_mode)) {
archive_entry_set_perm(entry, 0644);
} else if(S_ISDIR(st->st_mode)) {
archive_entry_set_perm(entry, 0755);
}
- /* If a specific file was requested skip entries that don't match. */
- if (fn && strcmp(fn, entryname)) {
- _alpm_log(PM_LOG_DEBUG, "skipping: %s\n", entryname);
- if (archive_read_data_skip(_archive) != ARCHIVE_OK) {
- ret = 1;
- goto cleanup;
+ /* If specific files were requested, skip entries that don't match. */
+ if(list) {
+ char *prefix = strdup(entryname);
+ char *p = strstr(prefix,"/");
+ if(p) {
+ *(p+1) = '\0';
+ }
+ char *found = alpm_list_find_str(list, prefix);
+ free(prefix);
+ if(!found) {
+ _alpm_log(PM_LOG_DEBUG, "skipping: %s\n", entryname);
+ if (archive_read_data_skip(_archive) != ARCHIVE_OK) {
+ ret = 1;
+ goto cleanup;
+ }
+ continue;
}
- continue;
}
/* Extract the archive entry. */
@@ -369,7 +355,7 @@ int _alpm_unpack(const char *archive, const char *prefix, const char *fn)
goto cleanup;
}
- if(fn) {
+ if(breakfirst) {
break;
}
}
@@ -426,8 +412,7 @@ int _alpm_rmrf(const char *path)
return(0);
}
-int _alpm_logaction(unsigned short usesyslog, FILE *f,
- const char *fmt, va_list args)
+int _alpm_logaction(int usesyslog, FILE *f, const char *fmt, va_list args)
{
int ret = 0;
@@ -527,7 +512,9 @@ int _alpm_run_chroot(const char *root, const char *cmd)
/* this code runs for the parent only (wait on the child) */
pid_t retpid;
int status;
- while((retpid = waitpid(pid, &status, 0)) == -1 && errno == EINTR);
+ do {
+ retpid = waitpid(pid, &status, 0);
+ } while(retpid == -1 && errno == EINTR);
if(retpid == -1) {
_alpm_log(PM_LOG_ERROR, _("call to waitpid failed (%s)\n"),
strerror(errno));
diff --git a/lib/libalpm/util.h b/lib/libalpm/util.h
index 4bc8b92f..37893c8b 100644
--- a/lib/libalpm/util.h
+++ b/lib/libalpm/util.h
@@ -26,6 +26,8 @@
#include "config.h"
+#include "alpm_list.h"
+
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
@@ -60,12 +62,12 @@ int _alpm_makepath(const char *path);
int _alpm_makepath_mode(const char *path, mode_t mode);
int _alpm_copyfile(const char *src, const char *dest);
char *_alpm_strtrim(char *str);
-char *_alpm_strreplace(const char *str, const char *needle, const char *replace);
int _alpm_lckmk();
int _alpm_lckrm();
-int _alpm_unpack(const char *archive, const char *prefix, const char *fn);
+int _alpm_unpack_single(const char *archive, const char *prefix, const char *fn);
+int _alpm_unpack(const char *archive, const char *prefix, alpm_list_t *list, int breakfirst);
int _alpm_rmrf(const char *path);
-int _alpm_logaction(unsigned short usesyslog, FILE *f, const char *fmt, va_list args);
+int _alpm_logaction(int usesyslog, FILE *f, const char *fmt, va_list args);
int _alpm_run_chroot(const char *root, const char *cmd);
int _alpm_ldconfig(const char *root);
int _alpm_str_cmp(const void *s1, const void *s2);