diff options
Diffstat (limited to 'lib/libalpm')
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); |