diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libalpm/add.c | 229 | ||||
-rw-r--r-- | lib/libalpm/add.h | 4 | ||||
-rw-r--r-- | lib/libalpm/alpm.h | 29 | ||||
-rw-r--r-- | lib/libalpm/be_files.c | 42 | ||||
-rw-r--r-- | lib/libalpm/conflict.c | 26 | ||||
-rw-r--r-- | lib/libalpm/conflict.h | 3 | ||||
-rw-r--r-- | lib/libalpm/db.c | 61 | ||||
-rw-r--r-- | lib/libalpm/db.h | 8 | ||||
-rw-r--r-- | lib/libalpm/delta.c | 67 | ||||
-rw-r--r-- | lib/libalpm/deps.c | 2 | ||||
-rw-r--r-- | lib/libalpm/dload.c | 53 | ||||
-rw-r--r-- | lib/libalpm/error.c | 4 | ||||
-rw-r--r-- | lib/libalpm/handle.c | 12 | ||||
-rw-r--r-- | lib/libalpm/handle.h | 2 | ||||
-rw-r--r-- | lib/libalpm/package.c | 18 | ||||
-rw-r--r-- | lib/libalpm/remove.c | 220 | ||||
-rw-r--r-- | lib/libalpm/remove.h | 5 | ||||
-rw-r--r-- | lib/libalpm/sync.c | 339 | ||||
-rw-r--r-- | lib/libalpm/sync.h | 3 | ||||
-rw-r--r-- | lib/libalpm/trans.c | 308 | ||||
-rw-r--r-- | lib/libalpm/trans.h | 9 | ||||
-rw-r--r-- | lib/libalpm/util.c | 45 | ||||
-rw-r--r-- | lib/libalpm/util.h | 1 |
23 files changed, 648 insertions, 842 deletions
diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c index 1d143c6f..c6751a49 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 @@ -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..e9fadca2 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -151,8 +151,9 @@ 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); +const char *alpm_option_get_arch(); +void alpm_option_set_arch(const char *arch); + void alpm_option_set_usedelta(unsigned short usedelta); pmdb_t *alpm_option_get_localdb(); @@ -224,7 +225,6 @@ 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, @@ -262,13 +262,6 @@ 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 { @@ -402,19 +395,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, +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 +438,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 +507,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/be_files.c b/lib/libalpm/be_files.c index bfe10867..21533ef2 100644 --- a/lib/libalpm/be_files.c +++ b/lib/libalpm/be_files.c @@ -51,10 +51,11 @@ * 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) +static time_t getlastupdate(pmdb_t *db) { FILE *fp; char *file; + const char *dbpath; time_t ret = 0; ALPM_LOG_FUNC; @@ -63,9 +64,10 @@ static time_t getlastupdate(const pmdb_t *db) return(ret); } - /* db->path + '.lastupdate' + NULL */ - MALLOC(file, strlen(db->path) + 12, RET_ERR(PM_ERR_MEMORY, ret)); - sprintf(file, "%s.lastupdate", db->path); + dbpath = _alpm_db_path(db); + /* dbpath + '.lastupdate' + NULL */ + MALLOC(file, strlen(dbpath) + 12, RET_ERR(PM_ERR_MEMORY, ret)); + sprintf(file, "%s.lastupdate", dbpath); /* get the last update time, if it's there */ if((fp = fopen(file, "r")) == NULL) { @@ -85,10 +87,11 @@ static time_t getlastupdate(const pmdb_t *db) /* * writes the dbpath/.lastupdate file with the value in time */ -static int setlastupdate(const pmdb_t *db, time_t time) +static int setlastupdate(pmdb_t *db, time_t time) { FILE *fp; char *file; + const char *dbpath; int ret = 0; ALPM_LOG_FUNC; @@ -97,9 +100,10 @@ static int setlastupdate(const pmdb_t *db, time_t time) return(-1); } - /* db->path + '.lastupdate' + NULL */ - MALLOC(file, strlen(db->path) + 12, RET_ERR(PM_ERR_MEMORY, ret)); - sprintf(file, "%s.lastupdate", db->path); + dbpath = _alpm_db_path(db); + /* dbpath + '.lastupdate' + NULL */ + MALLOC(file, strlen(dbpath) + 12, RET_ERR(PM_ERR_MEMORY, ret)); + sprintf(file, "%s.lastupdate", dbpath); if((fp = fopen(file, "w")) == NULL) { free(file); @@ -116,7 +120,7 @@ static int setlastupdate(const pmdb_t *db, time_t time) 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 +152,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(); * @@ -191,7 +195,6 @@ 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); @@ -225,8 +228,9 @@ 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); } @@ -241,7 +245,7 @@ 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); if(ret) { free(dbfilepath); RET_ERR(PM_ERR_SYSTEM, -1); @@ -306,13 +310,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 +330,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; } @@ -367,10 +373,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); } 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..e57ff935 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, unsigned short 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..29816032 100644 --- a/lib/libalpm/db.h +++ b/lib/libalpm/db.h @@ -40,18 +40,20 @@ typedef enum _pmdbinfrq_t { /* Database */ struct __pmdb_t { - char *path; char *treename; + /* do not access directly, use _alpm_db_path(db) for lazy access */ + char *_path; unsigned short pkgcache_loaded; - alpm_list_t *pkgcache; unsigned short grpcache_loaded; + unsigned short is_local; + alpm_list_t *pkgcache; 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 4695731a..f8fb09fe 100644 --- a/lib/libalpm/dload.c +++ b/lib/libalpm/dload.c @@ -76,30 +76,6 @@ static char *get_tempfile(const char *path, const char *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 int download_internal(const char *url, const char *localpath, time_t mtimeold, time_t *mtimenew) { fetchIO *dlf = NULL; @@ -110,17 +86,20 @@ static int download_internal(const char *url, const char *localpath, size_t dl_thisfile = 0, nread = 0; char *tempfile, *destfile, *filename; struct sigaction new_action, old_action; - struct url *fileurl = url_for_string(url); + struct url *fileurl; char buffer[PM_DLBUF_LEN]; - if(!fileurl) { - return(-1); - } - filename = get_filename(url); if(!filename) { return(-1); } + + fileurl = fetchParseURL(url); + if(!fileurl) { + _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); @@ -161,7 +140,7 @@ static int download_internal(const char *url, const char *localpath, sigaction(SIGPIPE, NULL, &old_action); sigaction(SIGPIPE, &new_action, NULL); - dlf = fetchXGet(fileurl, &ust, (handle->nopassiveftp ? "i" : "pi")); + dlf = fetchXGet(fileurl, &ust, "i"); if(fetchLastErrCode == FETCH_UNCHANGED) { _alpm_log(PM_LOG_DEBUG, "mtimes are identical, skipping %s\n", filename); @@ -214,14 +193,12 @@ static int download_internal(const char *url, const char *localpath, while((nread = fetchIO_read(dlf, buffer, PM_DLBUF_LEN)) > 0) { 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)) { + _alpm_log(PM_LOG_ERROR, _("error writing to file '%s': %s\n"), + destfile, strerror(errno)); + ret = -1; + goto cleanup; } dl_thisfile += nread; 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..012d4121 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); @@ -213,13 +214,13 @@ 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 -1; + return NULL; } - return handle->nopassiveftp; + return handle->arch; } pmdb_t SYMEXPORT *alpm_option_get_localdb() @@ -529,9 +530,10 @@ 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) diff --git a/lib/libalpm/handle.h b/lib/libalpm/handle.h index c7c262cf..a1eb1cde 100644 --- a/lib/libalpm/handle.h +++ b/lib/libalpm/handle.h @@ -58,7 +58,7 @@ typedef struct _pmhandle_t { /* options */ unsigned short usesyslog; /* Use syslog instead of logfile? */ /* TODO move to frontend */ - unsigned short nopassiveftp; /* Don't use PASV ftp connections */ + char *arch; /* Architecture of packages we should allow */ unsigned short usedelta; /* Download deltas if possible */ } pmhandle_t; diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c index 002b1c89..de171661 100644 --- a/lib/libalpm/package.c +++ b/lib/libalpm/package.c @@ -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 */ @@ -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; } diff --git a/lib/libalpm/remove.c b/lib/libalpm/remove.c index 1e8f9156..f31fbfb0 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,12 +372,11 @@ 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; @@ -329,26 +386,24 @@ 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)); + + 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); } - files = alpm_pkg_get_files(info); 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); @@ -363,7 +418,7 @@ int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db) /* 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); + unlink_file(info, lp->data, NULL, trans->flags & PM_TRANS_FLAG_NOSAVE); /* update progress bar after each file */ percent = (double)position / (double)filenum; @@ -379,12 +434,10 @@ int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db) PROGRESS(trans, PM_TRANS_PROGRESS_REMOVE_START, pkgname, 100, pkg_count, (pkg_count - alpm_list_count(targ) + 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..a1a6ea7c 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); @@ -323,8 +401,8 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync 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; @@ -345,7 +423,7 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync _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) { + 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); @@ -355,7 +433,7 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync /* 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, &resolved, remove, data) == -1) { @@ -392,21 +470,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 +498,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 +546,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 +557,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 +565,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 +578,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); @@ -532,16 +610,16 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) { /* rebuild remove list */ alpm_list_free(remove); - remove = NULL; - for(i = trans->packages; i; i = i->next) { + trans->remove = NULL; + 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); + trans->remove = alpm_list_add(trans->remove, _alpm_pkg_dup(j->data)); } } _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 +632,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,7 +642,6 @@ 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); return(ret); @@ -601,7 +678,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; @@ -711,7 +788,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 +806,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 +817,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 +910,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 +952,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 +978,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 +987,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 +996,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..c99f5964 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(!(handle->trans->flags & PM_TRANS_FLAG_NOLOCK), RET_ERR(PM_ERR_TRANS_NOT_LOCKED, -1)); + 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; + + 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. @@ -247,12 +297,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 +308,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 */ @@ -503,30 +407,30 @@ cleanup: return(retval); } -pmtranstype_t SYMEXPORT alpm_trans_get_type() +unsigned 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 082c095b..f78d193a 100644 --- a/lib/libalpm/util.c +++ b/lib/libalpm/util.c @@ -196,51 +196,6 @@ 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() { diff --git a/lib/libalpm/util.h b/lib/libalpm/util.h index 4bc8b92f..ccf169d3 100644 --- a/lib/libalpm/util.h +++ b/lib/libalpm/util.h @@ -60,7 +60,6 @@ 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); |