diff options
Diffstat (limited to 'lib/libalpm')
| -rw-r--r-- | lib/libalpm/add.c | 231 | ||||
| -rw-r--r-- | lib/libalpm/add.h | 4 | ||||
| -rw-r--r-- | lib/libalpm/alpm.h | 100 | ||||
| -rw-r--r-- | lib/libalpm/alpm_list.c | 85 | ||||
| -rw-r--r-- | lib/libalpm/alpm_list.h | 2 | ||||
| -rw-r--r-- | lib/libalpm/backup.c | 8 | ||||
| -rw-r--r-- | lib/libalpm/be_files.c | 95 | ||||
| -rw-r--r-- | lib/libalpm/be_package.c | 7 | ||||
| -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 | 22 | ||||
| -rw-r--r-- | lib/libalpm/delta.c | 67 | ||||
| -rw-r--r-- | lib/libalpm/deps.c | 2 | ||||
| -rw-r--r-- | lib/libalpm/dload.c | 62 | ||||
| -rw-r--r-- | lib/libalpm/error.c | 4 | ||||
| -rw-r--r-- | lib/libalpm/handle.c | 25 | ||||
| -rw-r--r-- | lib/libalpm/handle.h | 6 | ||||
| -rw-r--r-- | lib/libalpm/package.c | 22 | ||||
| -rw-r--r-- | lib/libalpm/package.h | 4 | ||||
| -rw-r--r-- | lib/libalpm/remove.c | 228 | ||||
| -rw-r--r-- | lib/libalpm/remove.h | 5 | ||||
| -rw-r--r-- | lib/libalpm/sync.c | 360 | ||||
| -rw-r--r-- | lib/libalpm/sync.h | 3 | ||||
| -rw-r--r-- | lib/libalpm/trans.c | 315 | ||||
| -rw-r--r-- | lib/libalpm/trans.h | 9 | ||||
| -rw-r--r-- | lib/libalpm/util.c | 120 | ||||
| -rw-r--r-- | lib/libalpm/util.h | 8 | 
28 files changed, 891 insertions, 993 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..c433b73d 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); @@ -128,8 +128,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 +151,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 +196,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 +226,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 +263,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 +370,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 +396,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 +439,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 +508,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..17bdfdf4 100644 --- a/lib/libalpm/alpm_list.c +++ b/lib/libalpm/alpm_list.c @@ -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..ffbaa8d5 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, 0);  		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);  } @@ -379,6 +387,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 +419,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 +443,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 +451,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 +459,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 +507,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 +523,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 +538,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 +549,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 +584,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 +612,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 +648,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..a4c9f1f4 100644 --- a/lib/libalpm/dload.c +++ b/lib/libalpm/dload.c @@ -59,7 +59,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 +69,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"); @@ -116,21 +92,24 @@ static int download_internal(const char *url, const char *localpath,  	struct url_stat ust;  	struct stat st;  	int chk_resume = 0, ret = 0; -	size_t dl_thisfile = 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); +	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); @@ -168,10 +147,11 @@ static int download_internal(const char *url, const char *localpath,  	 * something along those lines. Store the old signal handler first. */  	new_action.sa_handler = SIG_IGN;  	sigemptyset(&new_action.sa_mask); +	new_action.sa_flags = 0;  	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); @@ -220,14 +200,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; @@ -323,7 +301,7 @@ 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; 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..572b863e 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; @@ -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/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/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..aea71db1 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; @@ -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   */ @@ -416,7 +320,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 +369,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 +408,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 082c095b..d9108096 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 */ @@ -261,13 +215,11 @@ int _alpm_lckmk()  	while((fd = open(file, O_WRONLY | O_CREAT | O_EXCL, 0000)) == -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 +238,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; @@ -346,14 +322,23 @@ int _alpm_unpack(const char *archive, const char *prefix, const char *fn)  			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 +354,7 @@ int _alpm_unpack(const char *archive, const char *prefix, const char *fn)  			goto cleanup;  		} -		if(fn) { +		if(breakfirst) {  			break;  		}  	} @@ -425,8 +410,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; 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); | 
