diff options
Diffstat (limited to 'lib')
52 files changed, 1593 insertions, 1232 deletions
| diff --git a/lib/libalpm/Makefile.am b/lib/libalpm/Makefile.am index 99f9c1b7..61dcb877 100644 --- a/lib/libalpm/Makefile.am +++ b/lib/libalpm/Makefile.am @@ -7,6 +7,9 @@ include_HEADERS = alpm_list.h alpm.h  DEFS = -DLOCALEDIR=\"@localedir@\" @DEFS@ +AM_CPPFLAGS = \ +	-imacros $(top_builddir)/config.h +  AM_CFLAGS = -pedantic -D_GNU_SOURCE  if ENABLE_VISIBILITY_CC diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c index 6c2f0cb6..b0077665 100644 --- a/lib/libalpm/add.c +++ b/lib/libalpm/add.c @@ -1,7 +1,7 @@  /*   *  add.c   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>   *   *  This program is free software; you can redistribute it and/or modify @@ -18,19 +18,15 @@   *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include "config.h" -  #include <stdlib.h>  #include <errno.h> -#include <time.h>  #include <string.h>  #include <limits.h>  #include <fcntl.h>  #include <sys/types.h>  #include <sys/stat.h>  #include <unistd.h> -#include <inttypes.h> /* int64_t */ -#include <stdint.h> /* intmax_t */ +#include <stdint.h> /* int64_t */  /* libarchive */  #include <archive.h> @@ -132,6 +128,18 @@ static int perform_extraction(alpm_handle_t *handle, struct archive *archive,  	return 0;  } +static int try_rename(alpm_handle_t *handle, const char *src, const char *dest) +{ +	if(rename(src, dest)) { +		_alpm_log(handle, ALPM_LOG_ERROR, _("could not rename %s to %s (%s)\n"), +				src, dest, strerror(errno)); +		alpm_logaction(handle, "error: could not rename %s to %s (%s)\n", +				src, dest, strerror(errno)); +		return 1; +	} +	return 0; +} +  static int extract_single_file(alpm_handle_t *handle, struct archive *archive,  		struct archive_entry *entry, alpm_pkg_t *newpkg, alpm_pkg_t *oldpkg)  { @@ -146,8 +154,6 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,  	entryname = archive_entry_pathname(entry);  	entrymode = archive_entry_mode(entry); -	memset(filename, 0, PATH_MAX); /* just to be sure */ -  	if(strcmp(entryname, ".INSTALL") == 0) {  		/* the install script goes inside the db */  		snprintf(filename, PATH_MAX, "%s%s-%s/install", @@ -170,7 +176,7 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,  	}  	/* if a file is in NoExtract then we never extract it */ -	if(alpm_list_find_str(handle->noextract, entryname)) { +	if(alpm_list_find(handle->noextract, entryname, _alpm_fnmatch)) {  		_alpm_log(handle, ALPM_LOG_DEBUG, "%s is in NoExtract, skipping extraction\n",  				entryname);  		alpm_logaction(handle, "note: %s is in NoExtract, skipping extraction\n", @@ -250,7 +256,7 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,  		} else if(S_ISREG(entrymode)) {  			/* case 4,7: */  			/* if file is in NoUpgrade, don't touch it */ -			if(alpm_list_find_str(handle->noupgrade, entryname)) { +			if(alpm_list_find(handle->noupgrade, entryname, _alpm_fnmatch)) {  				notouch = 1;  			} else {  				alpm_backup_t *backup; @@ -282,17 +288,18 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,  	STRDUP(entryname_orig, entryname, RET_ERR(handle, ALPM_ERR_MEMORY, -1));  	if(needbackup) { -		char checkfile[PATH_MAX]; +		char *checkfile;  		char *hash_local = NULL, *hash_pkg = NULL; -		int ret; +		size_t len; -		snprintf(checkfile, PATH_MAX, "%s.paccheck", filename); +		len = strlen(filename) + 10; +		MALLOC(checkfile, len, +				errors++; handle->pm_errno = ALPM_ERR_MEMORY; goto needbackup_cleanup); +		snprintf(checkfile, len, "%s.paccheck", filename); -		ret = perform_extraction(handle, archive, entry, checkfile, entryname_orig); -		if(ret == 1) { -			/* error */ -			FREE(entryname_orig); -			return 1; +		if(perform_extraction(handle, archive, entry, checkfile, entryname_orig)) { +			errors++; +			goto needbackup_cleanup;  		}  		hash_local = alpm_compute_md5sum(filename); @@ -320,29 +327,26 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,  			if(hash_local && hash_pkg && strcmp(hash_local, hash_pkg) != 0) {  				/* looks like we have a local file that has a different hash as the  				 * file in the package, move it to a .pacorig */ -				char newpath[PATH_MAX]; -				snprintf(newpath, PATH_MAX, "%s.pacorig", filename); +				char *newpath; +				size_t newlen = strlen(filename) + 9; +				MALLOC(newpath, newlen, +						errors++; handle->pm_errno = ALPM_ERR_MEMORY; goto needbackup_cleanup); +				snprintf(newpath, newlen, "%s.pacorig", filename);  				/* move the existing file to the "pacorig" */ -				if(rename(filename, newpath)) { -					_alpm_log(handle, ALPM_LOG_ERROR, _("could not rename %s to %s (%s)\n"), -							filename, newpath, strerror(errno)); -					alpm_logaction(handle, "error: could not rename %s to %s (%s)\n", -							filename, newpath, strerror(errno)); +				if(try_rename(handle, filename, newpath)) { +						errors++;  					errors++;  				} else {  					/* rename the file we extracted to the real name */ -					if(rename(checkfile, filename)) { -						_alpm_log(handle, ALPM_LOG_ERROR, _("could not rename %s to %s (%s)\n"), -								checkfile, filename, strerror(errno)); -						alpm_logaction(handle, "error: could not rename %s to %s (%s)\n", -								checkfile, filename, strerror(errno)); +					if(try_rename(handle, checkfile, filename)) {  						errors++;  					} else {  						_alpm_log(handle, ALPM_LOG_WARNING, _("%s saved as %s\n"), filename, newpath);  						alpm_logaction(handle, "warning: %s saved as %s\n", filename, newpath);  					}  				} +				free(newpath);  			} else {  				/* local file is identical to pkg one, so just remove pkg one */  				unlink(checkfile); @@ -356,11 +360,7 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,  					_alpm_log(handle, ALPM_LOG_DEBUG, "action: installing new file: %s\n",  							entryname_orig); -					if(rename(checkfile, filename)) { -						_alpm_log(handle, ALPM_LOG_ERROR, _("could not rename %s to %s (%s)\n"), -								checkfile, filename, strerror(errno)); -						alpm_logaction(handle, "error: could not rename %s to %s (%s)\n", -								checkfile, filename, strerror(errno)); +					if(try_rename(handle, checkfile, filename)) {  						errors++;  					}  				} else { @@ -382,29 +382,30 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,  				_alpm_log(handle, ALPM_LOG_DEBUG, "action: leaving existing file in place\n");  				unlink(checkfile);  			} else { -				char newpath[PATH_MAX]; +				char *newpath; +				size_t newlen = strlen(filename) + 8;  				_alpm_log(handle, ALPM_LOG_DEBUG, "action: keeping current file and installing"  						" new one with .pacnew ending\n"); -				snprintf(newpath, PATH_MAX, "%s.pacnew", filename); -				if(rename(checkfile, newpath)) { -					_alpm_log(handle, ALPM_LOG_ERROR, _("could not install %s as %s (%s)\n"), -							filename, newpath, strerror(errno)); -					alpm_logaction(handle, "error: could not install %s as %s (%s)\n", -							filename, newpath, strerror(errno)); +				MALLOC(newpath, newlen, +						errors++; handle->pm_errno = ALPM_ERR_MEMORY; goto needbackup_cleanup); +				snprintf(newpath, newlen, "%s.pacnew", filename); +				if(try_rename(handle, checkfile, newpath)) { +					errors++;  				} else {  					_alpm_log(handle, ALPM_LOG_WARNING, _("%s installed as %s\n"),  							filename, newpath);  					alpm_logaction(handle, "warning: %s installed as %s\n",  							filename, newpath);  				} +				free(newpath);  			}  		} -		FREE(hash_local); -		FREE(hash_pkg); +needbackup_cleanup: +		free(checkfile); +		free(hash_local); +		free(hash_pkg);  	} else { -		int ret; -  		/* we didn't need a backup */  		if(notouch) {  			/* change the path to a .pacnew extension */ @@ -423,11 +424,11 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,  			unlink(filename);  		} -		ret = perform_extraction(handle, archive, entry, filename, entryname_orig); -		if(ret == 1) { +		if(perform_extraction(handle, archive, entry, filename, entryname_orig)) {  			/* error */ -			FREE(entryname_orig); -			return 1; +			free(entryname_orig); +			errors++; +			return errors;  		}  		/* calculate an hash if this is in newpkg's backup */ @@ -444,7 +445,7 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,  			backup->hash = newhash;  		}  	} -	FREE(entryname_orig); +	free(entryname_orig);  	return errors;  } @@ -521,31 +522,20 @@ static int commit_single_pkg(alpm_handle_t *handle, alpm_pkg_t *newpkg,  	if(!(trans->flags & ALPM_TRANS_FLAG_DBONLY)) {  		struct archive *archive;  		struct archive_entry *entry; -		int cwdfd; +		struct stat buf; +		int fd, cwdfd;  		_alpm_log(handle, ALPM_LOG_DEBUG, "extracting files\n"); -		if((archive = archive_read_new()) == NULL) { -			handle->pm_errno = ALPM_ERR_LIBARCHIVE; -			ret = -1; -			goto cleanup; -		} - -		archive_read_support_compression_all(archive); -		archive_read_support_format_all(archive); - -		_alpm_log(handle, ALPM_LOG_DEBUG, "archive: %s\n", pkgfile); -		if(archive_read_open_filename(archive, pkgfile, -					ALPM_BUFFER_SIZE) != ARCHIVE_OK) { -			handle->pm_errno = ALPM_ERR_PKG_OPEN; +		fd = _alpm_open_archive(db->handle, pkgfile, &buf, +				&archive, ALPM_ERR_PKG_OPEN); +		if(fd < 0) {  			ret = -1;  			goto cleanup;  		}  		/* save the cwd so we can restore it later */ -		do { -			cwdfd = open(".", O_RDONLY); -		} while(cwdfd == -1 && errno == EINTR); +		OPEN(cwdfd, ".", O_RDONLY);  		if(cwdfd < 0) {  			_alpm_log(handle, ALPM_LOG_ERROR, _("could not get current working directory\n"));  		} @@ -554,6 +544,8 @@ static int commit_single_pkg(alpm_handle_t *handle, alpm_pkg_t *newpkg,  		if(chdir(handle->root) != 0) {  			_alpm_log(handle, ALPM_LOG_ERROR, _("could not change directory to %s (%s)\n"),  					handle->root, strerror(errno)); +			archive_read_finish(archive); +			CLOSE(fd);  			ret = -1;  			goto cleanup;  		} @@ -595,6 +587,7 @@ static int commit_single_pkg(alpm_handle_t *handle, alpm_pkg_t *newpkg,  			errors += extract_single_file(handle, archive, entry, newpkg, oldpkg);  		}  		archive_read_finish(archive); +		CLOSE(fd);  		/* restore the old cwd if we have it */  		if(cwdfd >= 0) { @@ -602,7 +595,7 @@ static int commit_single_pkg(alpm_handle_t *handle, alpm_pkg_t *newpkg,  				_alpm_log(handle, ALPM_LOG_ERROR,  						_("could not restore working directory (%s)\n"), strerror(errno));  			} -			close(cwdfd); +			CLOSE(cwdfd);  		}  		if(errors) { diff --git a/lib/libalpm/add.h b/lib/libalpm/add.h index 77a3d22a..d1368e8a 100644 --- a/lib/libalpm/add.h +++ b/lib/libalpm/add.h @@ -1,7 +1,7 @@  /*   *  add.h   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>   *   *  This program is free software; you can redistribute it and/or modify diff --git a/lib/libalpm/alpm.c b/lib/libalpm/alpm.c index 38843342..c58a4069 100644 --- a/lib/libalpm/alpm.c +++ b/lib/libalpm/alpm.c @@ -1,7 +1,7 @@  /*   *  alpm.c   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>   *  Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>   *  Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu> @@ -21,8 +21,6 @@   *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include "config.h" -  #ifdef HAVE_LIBCURL  #include <curl/curl.h>  #endif @@ -47,9 +45,9 @@   * @return a context handle on success, NULL on error, err will be set if provided   */  alpm_handle_t SYMEXPORT *alpm_initialize(const char *root, const char *dbpath, -		enum _alpm_errno_t *err) +		alpm_errno_t *err)  { -	enum _alpm_errno_t myerr; +	alpm_errno_t myerr;  	const char *lf = "db.lck";  	size_t lockfilelen;  	alpm_handle_t *myhandle = _alpm_handle_new(); @@ -108,7 +106,7 @@ int SYMEXPORT alpm_release(alpm_handle_t *myhandle)  		myhandle->db_local = NULL;  	} -	if(alpm_db_unregister_all(myhandle) == -1) { +	if(alpm_unregister_all_syncdbs(myhandle) == -1) {  		ret = -1;  	} diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index 6df3e1f5..2e666294 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -1,7 +1,7 @@  /*   * alpm.h   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>   *  Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>   *  Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu> @@ -27,14 +27,12 @@  extern "C" {  #endif -#include <sys/types.h> /* for off_t */ -#include <time.h> /* for time_t */ -#include <stdarg.h> /* for va_list */ +#include <stdint.h>    /* int64_t */ +#include <sys/types.h> /* off_t */ +#include <stdarg.h>    /* va_list */  #include <alpm_list.h> -#define DEPRECATED __attribute__((deprecated)) -  /*   * Arch Linux Package Management library   */ @@ -44,15 +42,14 @@ extern "C" {   * @{   */ +typedef int64_t alpm_time_t; +  /*   * Enumerations   * These ones are used in multiple contexts, so are forward-declared.   */ -/** - * Install reasons. - * Why the package was installed. - */ +/** Package install reasons. */  typedef enum _alpm_pkgreason_t {  	/** Explicitly requested by the user. */  	ALPM_PKG_REASON_EXPLICIT = 0, @@ -60,12 +57,22 @@ typedef enum _alpm_pkgreason_t {  	ALPM_PKG_REASON_DEPEND = 1  } alpm_pkgreason_t; +/** Location a package object was loaded from. */  typedef enum _alpm_pkgfrom_t {  	PKG_FROM_FILE = 1,  	PKG_FROM_LOCALDB,  	PKG_FROM_SYNCDB  } alpm_pkgfrom_t; +/** Location a package object was loaded from. */ +typedef enum _alpm_pkgvalidation_t { +	ALPM_PKG_VALIDATION_UNKNOWN = 0, +	ALPM_PKG_VALIDATION_NONE = (1 << 0), +	ALPM_PKG_VALIDATION_MD5SUM = (1 << 1), +	ALPM_PKG_VALIDATION_SHA256SUM = (1 << 2), +	ALPM_PKG_VALIDATION_SIGNATURE = (1 << 3) +} alpm_pkgvalidation_t; +  /** Types of version constraints in dependency specs. */  typedef enum _alpm_depmod_t {    /** No version constraint */ @@ -92,9 +99,7 @@ typedef enum _alpm_fileconflicttype_t {  	ALPM_FILECONFLICT_FILESYSTEM  } alpm_fileconflicttype_t; -/** - * PGP signature verification options - */ +/** PGP signature verification options */  typedef enum _alpm_siglevel_t {  	ALPM_SIG_PACKAGE = (1 << 0),  	ALPM_SIG_PACKAGE_OPTIONAL = (1 << 1), @@ -109,9 +114,7 @@ typedef enum _alpm_siglevel_t {  	ALPM_SIG_USE_DEFAULT = (1 << 31)  } alpm_siglevel_t; -/** - * PGP signature verification status return codes - */ +/** PGP signature verification status return codes */  typedef enum _alpm_sigstatus_t {  	ALPM_SIGSTATUS_VALID,  	ALPM_SIGSTATUS_KEY_EXPIRED, @@ -121,9 +124,7 @@ typedef enum _alpm_sigstatus_t {  	ALPM_SIGSTATUS_INVALID  } alpm_sigstatus_t; -/** - * PGP signature verification status return codes - */ +/** PGP signature verification status return codes */  typedef enum _alpm_sigvalidity_t {  	ALPM_SIGVALIDITY_FULL,  	ALPM_SIGVALIDITY_MARGINAL, @@ -144,6 +145,7 @@ typedef struct __alpm_trans_t alpm_trans_t;  typedef struct _alpm_depend_t {  	char *name;  	char *version; +	char *desc;  	unsigned long name_hash;  	alpm_depmod_t mod;  } alpm_depend_t; @@ -152,7 +154,7 @@ typedef struct _alpm_depend_t {  typedef struct _alpm_depmissing_t {  	char *target;  	alpm_depend_t *depend; -	/* this is used in case of remove dependency error only */ +	/* this is used only in the case of a remove dependency error */  	char *causingpkg;  } alpm_depmissing_t; @@ -222,11 +224,15 @@ typedef struct _alpm_pgpkey_t {  	char *uid;  	char *name;  	char *email; -	time_t created; -	time_t expires; +	alpm_time_t created; +	alpm_time_t expires; +	unsigned int length; +	unsigned int revoked; +	char pubkey_algo;  } alpm_pgpkey_t; -/** Signature result. Contains the key, status, and validity of a given +/** + * Signature result. Contains the key, status, and validity of a given   * signature.   */  typedef struct _alpm_sigresult_t { @@ -235,7 +241,8 @@ typedef struct _alpm_sigresult_t {  	alpm_sigvalidity_t validity;  } alpm_sigresult_t; -/** Signature list. Contains the number of signatures found and a pointer to an +/** + * Signature list. Contains the number of signatures found and a pointer to an   * array of results.  The array is of size count.   */  typedef struct _alpm_siglist_t { @@ -247,9 +254,7 @@ typedef struct _alpm_siglist_t {   * Logging facilities   */ -/** - * Logging Levels - */ +/** Logging Levels */  typedef enum _alpm_loglevel_t {  	ALPM_LOG_ERROR    = 1,  	ALPM_LOG_WARNING  = (1 << 1), @@ -260,7 +265,8 @@ typedef enum _alpm_loglevel_t {  typedef void (*alpm_cb_log)(alpm_loglevel_t, const char *, va_list);  int alpm_logaction(alpm_handle_t *handle, const char *fmt, ...); -/** Events. +/** + * Events.   * NULL parameters are passed to in all events unless specified otherwise.   */  typedef enum _alpm_event_t { @@ -341,13 +347,18 @@ typedef enum _alpm_event_t {  	/** Disk space usage will be computed for a package */  	ALPM_EVENT_DISKSPACE_START,  	/** Disk space usage was computed for a package */ -	ALPM_EVENT_DISKSPACE_DONE, +	ALPM_EVENT_DISKSPACE_DONE  } alpm_event_t;  /** Event callback */  typedef void (*alpm_cb_event)(alpm_event_t, void *, void *); -/** Questions */ +/** + * Questions. + * Unlike the events or progress enumerations, this enum has bitmask values + * so a frontend can use a bitmask map to supply preselected answers to the + * different types of questions. + */  typedef enum _alpm_question_t {  	ALPM_QUESTION_INSTALL_IGNOREPKG = 1,  	ALPM_QUESTION_REPLACE_PKG = (1 << 1), @@ -370,7 +381,7 @@ typedef enum _alpm_progress_t {  	ALPM_PROGRESS_CONFLICTS_START,  	ALPM_PROGRESS_DISKSPACE_START,  	ALPM_PROGRESS_INTEGRITY_START, -	ALPM_PROGRESS_LOAD_START, +	ALPM_PROGRESS_LOAD_START  } alpm_progress_t;  /** Progress callback */ @@ -530,8 +541,8 @@ const char *alpm_option_get_arch(alpm_handle_t *handle);  /** Sets the targeted architecture. */  int alpm_option_set_arch(alpm_handle_t *handle, const char *arch); -int alpm_option_get_usedelta(alpm_handle_t *handle); -int alpm_option_set_usedelta(alpm_handle_t *handle, int usedelta); +double alpm_option_get_deltaratio(alpm_handle_t *handle); +int alpm_option_set_deltaratio(alpm_handle_t *handle, double ratio);  int alpm_option_get_checkspace(alpm_handle_t *handle);  int alpm_option_set_checkspace(alpm_handle_t *handle, int checkspace); @@ -552,7 +563,7 @@ int alpm_option_set_default_siglevel(alpm_handle_t *handle, alpm_siglevel_t leve   * libalpm functions.   * @return a reference to the local database   */ -alpm_db_t *alpm_option_get_localdb(alpm_handle_t *handle); +alpm_db_t *alpm_get_localdb(alpm_handle_t *handle);  /** Get the list of sync databases.   * Returns a list of alpm_db_t structures, one for each registered @@ -560,7 +571,7 @@ alpm_db_t *alpm_option_get_localdb(alpm_handle_t *handle);   * @param handle the context handle   * @return a reference to an internal list of alpm_db_t structures   */ -alpm_list_t *alpm_option_get_syncdbs(alpm_handle_t *handle); +alpm_list_t *alpm_get_syncdbs(alpm_handle_t *handle);  /** Register a sync database of packages.   * @param handle the context handle @@ -569,20 +580,20 @@ alpm_list_t *alpm_option_get_syncdbs(alpm_handle_t *handle);   * database; note that this must be a '.sig' file type verification   * @return an alpm_db_t* on success (the value), NULL on error   */ -alpm_db_t *alpm_db_register_sync(alpm_handle_t *handle, const char *treename, +alpm_db_t *alpm_register_syncdb(alpm_handle_t *handle, const char *treename,  		alpm_siglevel_t level); -/** Unregister a package database. - * @param db pointer to the package database to unregister +/** Unregister all package databases. + * @param handle the context handle   * @return 0 on success, -1 on error (pm_errno is set accordingly)   */ -int alpm_db_unregister(alpm_db_t *db); +int alpm_unregister_all_syncdbs(alpm_handle_t *handle); -/** Unregister all package databases. - * @param handle the context handle +/** Unregister a package database. + * @param db pointer to the package database to unregister   * @return 0 on success, -1 on error (pm_errno is set accordingly)   */ -int alpm_db_unregister_all(alpm_handle_t *handle); +int alpm_db_unregister(alpm_db_t *db);  /** Get the name of a package database.   * @param db pointer to the package database @@ -635,7 +646,7 @@ alpm_list_t *alpm_db_get_pkgcache(alpm_db_t *db);   * @param name of the group   * @return the groups entry on success, NULL on error   */ -alpm_group_t *alpm_db_readgroup(alpm_db_t *db, const char *name); +alpm_group_t *alpm_db_get_group(alpm_db_t *db, const char *name);  /** Get the group cache of a package database.   * @param db pointer to the package database to get the group from @@ -648,16 +659,7 @@ alpm_list_t *alpm_db_get_groupcache(alpm_db_t *db);   * @param needles a list of regular expressions to search for   * @return the list of packages matching all regular expressions on success, NULL on error   */ -alpm_list_t *alpm_db_search(alpm_db_t *db, const alpm_list_t* needles); - -/** Set install reason for a package in db. - * @param handle the context handle - * @param pkg the package to update - * @param reason the new install reason - * @return 0 on success, -1 on error (pm_errno is set accordingly) - */ -int alpm_db_set_pkgreason(alpm_handle_t *handle, alpm_pkg_t *pkg, -		alpm_pkgreason_t reason); +alpm_list_t *alpm_db_search(alpm_db_t *db, const alpm_list_t *needles);  /** @} */ @@ -754,13 +756,13 @@ const char *alpm_pkg_get_url(alpm_pkg_t *pkg);   * @param pkg a pointer to package   * @return the timestamp of the build time   */ -time_t alpm_pkg_get_builddate(alpm_pkg_t *pkg); +alpm_time_t alpm_pkg_get_builddate(alpm_pkg_t *pkg);  /** Returns the install timestamp of the package.   * @param pkg a pointer to package   * @return the timestamp of the install time   */ -time_t alpm_pkg_get_installdate(alpm_pkg_t *pkg); +alpm_time_t alpm_pkg_get_installdate(alpm_pkg_t *pkg);  /** Returns the packager's name.   * @param pkg a pointer to package @@ -827,7 +829,7 @@ alpm_list_t *alpm_pkg_get_depends(alpm_pkg_t *pkg);  /** Returns the list of package optional dependencies.   * @param pkg a pointer to package - * @return a reference to an internal list of strings. + * @return a reference to an internal list of alpm_depend_t structures.   */  alpm_list_t *alpm_pkg_get_optdepends(alpm_pkg_t *pkg); @@ -887,6 +889,12 @@ alpm_db_t *alpm_pkg_get_db(alpm_pkg_t *pkg);   */  const char *alpm_pkg_get_base64_sig(alpm_pkg_t *pkg); +/** Returns the method used to validate a package during install. + * @param pkg a pointer to package + * @return an enum member giving the validation method + */ +alpm_pkgvalidation_t alpm_pkg_get_validation(alpm_pkg_t *pkg); +  /* End of alpm_pkg_t accessors */  /* @} */ @@ -928,6 +936,16 @@ off_t alpm_pkg_download_size(alpm_pkg_t *newpkg);  alpm_list_t *alpm_pkg_unused_deltas(alpm_pkg_t *pkg); +/** Set install reason for a package in the local database. + * The provided package object must be from the local database or this method + * will fail. The write to the local database is performed immediately. + * @param pkg the package to update + * @param reason the new install reason + * @return 0 on success, -1 on error (pm_errno is set accordingly) + */ +int alpm_pkg_set_reason(alpm_pkg_t *pkg, alpm_pkgreason_t reason); + +  /* End of alpm_pkg */  /** @} */ @@ -1107,13 +1125,13 @@ char *alpm_dep_compute_string(const alpm_depend_t *dep);   */  /* checksums */ -char *alpm_compute_md5sum(const char *name); +char *alpm_compute_md5sum(const char *filename);  char *alpm_compute_sha256sum(const char *filename);  /** @addtogroup alpm_api_errors Error Codes   * @{   */ -enum _alpm_errno_t { +typedef enum _alpm_errno_t {  	ALPM_ERR_MEMORY = 1,  	ALPM_ERR_SYSTEM,  	ALPM_ERR_BADPERMS, @@ -1177,19 +1195,19 @@ enum _alpm_errno_t {  	ALPM_ERR_LIBCURL,  	ALPM_ERR_EXTERNAL_DOWNLOAD,  	ALPM_ERR_GPGME -}; +} alpm_errno_t;  /** Returns the current error code from the handle. */ -enum _alpm_errno_t alpm_errno(alpm_handle_t *handle); +alpm_errno_t alpm_errno(alpm_handle_t *handle);  /** Returns the string corresponding to an error number. */ -const char *alpm_strerror(enum _alpm_errno_t err); +const char *alpm_strerror(alpm_errno_t err);  /* End of alpm_api_errors */  /** @} */  alpm_handle_t *alpm_initialize(const char *root, const char *dbpath, -		enum _alpm_errno_t *err); +		alpm_errno_t *err);  int alpm_release(alpm_handle_t *handle);  enum alpm_caps { diff --git a/lib/libalpm/alpm_list.c b/lib/libalpm/alpm_list.c index 3aa4f9bc..39eded13 100644 --- a/lib/libalpm/alpm_list.c +++ b/lib/libalpm/alpm_list.c @@ -1,7 +1,7 @@  /*   *  alpm_list.c   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>   *   *  This program is free software; you can redistribute it and/or modify @@ -204,7 +204,8 @@ alpm_list_t SYMEXPORT *alpm_list_join(alpm_list_t *first, alpm_list_t *second)   *   * @return the resultant list   */ -alpm_list_t SYMEXPORT *alpm_list_mmerge(alpm_list_t *left, alpm_list_t *right, alpm_list_fn_cmp fn) +alpm_list_t SYMEXPORT *alpm_list_mmerge(alpm_list_t *left, alpm_list_t *right, +		alpm_list_fn_cmp fn)  {  	alpm_list_t *newlist, *lp, *tail_ptr, *left_tail_ptr, *right_tail_ptr; @@ -273,20 +274,26 @@ alpm_list_t SYMEXPORT *alpm_list_mmerge(alpm_list_t *left, alpm_list_t *right, a   *   * @return the resultant list   */ -alpm_list_t SYMEXPORT *alpm_list_msort(alpm_list_t *list, size_t n, alpm_list_fn_cmp fn) +alpm_list_t SYMEXPORT *alpm_list_msort(alpm_list_t *list, size_t n, +		alpm_list_fn_cmp fn)  {  	if(n > 1) { -		alpm_list_t *left = list; -		alpm_list_t *lastleft = alpm_list_nth(list, n/2 - 1); -		alpm_list_t *right = lastleft->next; +		size_t half = n / 2; +		size_t i = half - 1; +		alpm_list_t *left = list, *lastleft = list, *right; + +		while(i--) { +			lastleft = lastleft->next; +		} +		right = lastleft->next;  		/* tidy new lists */  		lastleft->next = NULL;  		right->prev = left->prev;  		left->prev = lastleft; -		left = alpm_list_msort(left, n/2, fn); -		right = alpm_list_msort(right, n - (n/2), fn); +		left = alpm_list_msort(left, half, fn); +		right = alpm_list_msort(right, n - half, fn);  		list = alpm_list_mmerge(left, right, fn);  	}  	return list; @@ -579,19 +586,6 @@ alpm_list_t SYMEXPORT *alpm_list_last(const alpm_list_t *list)  	}  } -/** - * @brief Get the data member of a list node. - * - * @param node the list node - * - * @return the contained data, or NULL if none - */ -void SYMEXPORT *alpm_list_getdata(const alpm_list_t *node) -{ -	if(node == NULL) return NULL; -	return node->data; -} -  /* Misc */  /** diff --git a/lib/libalpm/alpm_list.h b/lib/libalpm/alpm_list.h index cd7b0291..8f743a28 100644 --- a/lib/libalpm/alpm_list.h +++ b/lib/libalpm/alpm_list.h @@ -1,7 +1,7 @@  /*   *  alpm_list.h   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>   *   *  This program is free software; you can redistribute it and/or modify @@ -71,7 +71,6 @@ alpm_list_t *alpm_list_nth(const alpm_list_t *list, size_t n);  alpm_list_t *alpm_list_next(const alpm_list_t *list);  alpm_list_t *alpm_list_previous(const alpm_list_t *list);  alpm_list_t *alpm_list_last(const alpm_list_t *list); -void *alpm_list_getdata(const alpm_list_t *entry);  /* misc */  size_t alpm_list_count(const alpm_list_t *list); diff --git a/lib/libalpm/backup.c b/lib/libalpm/backup.c index 728c1d05..98b5f5e3 100644 --- a/lib/libalpm/backup.c +++ b/lib/libalpm/backup.c @@ -1,7 +1,7 @@  /*   *  backup.c   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2005 by Judd Vinet <jvinet@zeroflux.org>   *  Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>   *  Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu> @@ -21,8 +21,6 @@   *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include "config.h" -  #include <stdlib.h>  #include <string.h> diff --git a/lib/libalpm/backup.h b/lib/libalpm/backup.h index 0b84a68c..c539406d 100644 --- a/lib/libalpm/backup.h +++ b/lib/libalpm/backup.h @@ -1,7 +1,7 @@  /*   *  backup.h   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>   *   *  This program is free software; you can redistribute it and/or modify diff --git a/lib/libalpm/base64.c b/lib/libalpm/base64.c index 5c9fa814..32c44459 100644 --- a/lib/libalpm/base64.c +++ b/lib/libalpm/base64.c @@ -32,6 +32,8 @@   *  * removal of SELF_TEST code   */ +#include <stdint.h> +  #include "base64.h"  static const unsigned char base64_enc_map[64] = @@ -62,6 +64,7 @@ static const unsigned char base64_dec_map[128] =       49,  50,  51, 127, 127, 127, 127, 127  }; +#if 0  /*   * Encode a buffer into base64 format   */ @@ -124,6 +127,7 @@ int base64_encode( unsigned char *dst, size_t *dlen,      return( 0 );  } +#endif  /*   * Decode a base64-formatted buffer @@ -131,8 +135,8 @@ int base64_encode( unsigned char *dst, size_t *dlen,  int base64_decode( unsigned char *dst, size_t *dlen,                     const unsigned char *src, size_t slen )  { -    size_t i, j, n; -    unsigned long x; +    size_t i, n; +    uint32_t j, x;      unsigned char *p;      for( i = j = n = 0; i < slen; i++ ) diff --git a/lib/libalpm/base64.h b/lib/libalpm/base64.h index 406aefa1..df684ab7 100644 --- a/lib/libalpm/base64.h +++ b/lib/libalpm/base64.h @@ -30,6 +30,7 @@  #define POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL               -0x0010  /**< Output buffer too small. */  #define POLARSSL_ERR_BASE64_INVALID_CHARACTER              -0x0012  /**< Invalid character in input. */ +#if 0  /**   * \brief          Encode a buffer into base64 format   * @@ -47,6 +48,7 @@   */  int base64_encode( unsigned char *dst, size_t *dlen,                     const unsigned char *src, size_t slen ); +#endif  /**   * \brief          Decode a base64-formatted buffer diff --git a/lib/libalpm/be_local.c b/lib/libalpm/be_local.c index 56cf38bb..9090c815 100644 --- a/lib/libalpm/be_local.c +++ b/lib/libalpm/be_local.c @@ -1,7 +1,7 @@  /*   *  be_local.c : backend for the local database   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>   *   *  This program is free software; you can redistribute it and/or modify @@ -18,8 +18,6 @@   *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include "config.h" -  #include <unistd.h>  #include <stdio.h>  #include <stdlib.h> @@ -28,7 +26,6 @@  #include <stdint.h> /* intmax_t */  #include <sys/stat.h>  #include <dirent.h> -#include <time.h>  #include <limits.h> /* PATH_MAX */  /* libalpm */ @@ -69,13 +66,13 @@ static const char *_cache_get_url(alpm_pkg_t *pkg)  	return pkg->url;  } -static time_t _cache_get_builddate(alpm_pkg_t *pkg) +static alpm_time_t _cache_get_builddate(alpm_pkg_t *pkg)  {  	LAZY_LOAD(INFRQ_DESC, 0);  	return pkg->builddate;  } -static time_t _cache_get_installdate(alpm_pkg_t *pkg) +static alpm_time_t _cache_get_installdate(alpm_pkg_t *pkg)  {  	LAZY_LOAD(INFRQ_DESC, 0);  	return pkg->installdate; @@ -105,6 +102,12 @@ static alpm_pkgreason_t _cache_get_reason(alpm_pkg_t *pkg)  	return pkg->reason;  } +static alpm_pkgvalidation_t _cache_get_validation(alpm_pkg_t *pkg) +{ +	LAZY_LOAD(INFRQ_DESC, -1); +	return pkg->validation; +} +  static alpm_list_t *_cache_get_licenses(alpm_pkg_t *pkg)  {  	LAZY_LOAD(INFRQ_DESC, NULL); @@ -226,6 +229,7 @@ static struct pkg_operations local_pkg_ops = {  	.get_arch        = _cache_get_arch,  	.get_isize       = _cache_get_isize,  	.get_reason      = _cache_get_reason, +	.get_validation  = _cache_get_validation,  	.has_scriptlet   = _cache_has_scriptlet,  	.get_licenses    = _cache_get_licenses,  	.get_groups      = _cache_get_groups, @@ -401,12 +405,11 @@ static int local_db_populate(alpm_db_t *db)  		rewinddir(dbdir);  	}  	if(est_count >= 2) { -		/* subtract the two extra pointers to get # of children */ +		/* subtract the '.' and '..' pointers to get # of children */  		est_count -= 2;  	} -	/* initialize hash at 50% full */ -	db->pkgcache = _alpm_pkghash_create(est_count * 2); +	db->pkgcache = _alpm_pkghash_create(est_count);  	if(db->pkgcache == NULL){  		closedir(dbdir);  		RET_ERR(db->handle, ALPM_ERR_MEMORY, -1); @@ -475,7 +478,8 @@ static int local_db_populate(alpm_db_t *db)  }  /* Note: the return value must be freed by the caller */ -char *_alpm_local_db_pkgpath(alpm_db_t *db, alpm_pkg_t *info, const char *filename) +char *_alpm_local_db_pkgpath(alpm_db_t *db, alpm_pkg_t *info, +		const char *filename)  {  	size_t len;  	char *pkgpath; @@ -522,7 +526,6 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq)  {  	FILE *fp = NULL;  	char line[1024]; -	char *pkgpath;  	alpm_db_t *db = info->origin_data.db;  	/* bitmask logic here: @@ -541,18 +544,10 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq)  		return -1;  	} -	_alpm_log(db->handle, ALPM_LOG_FUNCTION, "loading package data for %s : level=0x%x\n", +	_alpm_log(db->handle, ALPM_LOG_FUNCTION, +			"loading package data for %s : level=0x%x\n",  			info->name, inforeq); -	pkgpath = _alpm_local_db_pkgpath(db, info, NULL); -	if(!pkgpath || access(pkgpath, F_OK)) { -		/* directory doesn't exist or can't be opened */ -		_alpm_log(db->handle, ALPM_LOG_DEBUG, "cannot find '%s-%s' in db '%s'\n", -				info->name, info->version, db->treename); -		goto error; -	} -	free(pkgpath); -  	/* clear out 'line', to be certain - and to make valgrind happy */  	memset(line, 0, sizeof(line)); @@ -606,6 +601,26 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq)  			} else if(strcmp(line, "%REASON%") == 0) {  				READ_NEXT();  				info->reason = (alpm_pkgreason_t)atoi(line); +			} else if(strcmp(line, "%VALIDATION%") == 0) { +				alpm_list_t *i, *v = NULL; +				READ_AND_STORE_ALL(v); +				for(i = v; i; i = alpm_list_next(i)) +				{ +					if(strcmp(i->data, "none") == 0) { +						info->validation |= ALPM_PKG_VALIDATION_NONE; +					} else if(strcmp(i->data, "md5") == 0) { +						info->validation |= ALPM_PKG_VALIDATION_MD5SUM; +					} else if(strcmp(i->data, "sha256") == 0) { +						info->validation |= ALPM_PKG_VALIDATION_SHA256SUM; +					} else if(strcmp(i->data, "pgp") == 0) { +						info->validation |= ALPM_PKG_VALIDATION_SIGNATURE; +					} else { +						_alpm_log(db->handle, ALPM_LOG_WARNING, +								_("unknown validation type for package %s: %s\n"), +								info->name, (const char *)i->data); +					} +				} +				FREELIST(v);  			} else if(strcmp(line, "%SIZE%") == 0) {  				READ_NEXT();  				info->isize = _alpm_strtoofft(line); @@ -614,7 +629,7 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq)  			} else if(strcmp(line, "%DEPENDS%") == 0) {  				READ_AND_SPLITDEP(info->depends);  			} else if(strcmp(line, "%OPTDEPENDS%") == 0) { -				READ_AND_STORE_ALL(info->optdepends); +				READ_AND_SPLITDEP(info->optdepends);  			} else if(strcmp(line, "%CONFLICTS%") == 0) {  				READ_AND_SPLITDEP(info->conflicts);  			} else if(strcmp(line, "%PROVIDES%") == 0) { @@ -638,10 +653,11 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq)  		while(fgets(line, sizeof(line), fp)) {  			_alpm_strip_newline(line);  			if(strcmp(line, "%FILES%") == 0) { -				size_t files_count = 0, files_size = 0; +				size_t files_count = 0, files_size = 0, len;  				alpm_file_t *files = NULL; -				while(fgets(line, sizeof(line), fp) && _alpm_strip_newline(line)) { +				while(fgets(line, sizeof(line), fp) && +						(len = _alpm_strip_newline(line))) {  					if(files_count >= files_size) {  						size_t old_size = files_size;  						if(files_size == 0) { @@ -659,8 +675,14 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq)  						memset(files + old_size, 0,  								sizeof(alpm_file_t) * (files_size - old_size));  					} -					STRDUP(files[files_count].name, line, goto error); -					/* TODO: lstat file, get mode/size */ +					/* since we know the length of the file string already, +					 * we can do malloc + memcpy rather than strdup */ +					files[files_count].name = malloc(len + 1); +					if(files[files_count].name == NULL) { +						ALLOC_FAIL(len); +						goto error; +					} +					memcpy(files[files_count].name, line, len + 1);  					files_count++;  				}  				/* attempt to hand back any memory we don't need */ @@ -727,6 +749,23 @@ int _alpm_local_db_prepare(alpm_db_t *db, alpm_pkg_t *info)  	return retval;  } +static void write_deps(FILE *fp, const char *header, alpm_list_t *deplist) +{ +	alpm_list_t *lp; +	if(!deplist) { +		return; +	} +	fputs(header, fp); +	fputc('\n', fp); +	for(lp = deplist; lp; lp = lp->next) { +		char *depstring = alpm_dep_compute_string(lp->data); +		fputs(depstring, fp); +		fputc('\n', fp); +		free(depstring); +	} +	fputc('\n', fp); +} +  int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, alpm_dbinfrq_t inforeq)  {  	FILE *fp = NULL; @@ -764,18 +803,10 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, alpm_dbinfrq_t inforeq  		if(info->groups) {  			fputs("%GROUPS%\n", fp);  			for(lp = info->groups; lp; lp = lp->next) { -				fprintf(fp, "%s\n", (char *)lp->data); +				fputs(lp->data, fp); +				fputc('\n', fp);  			} -			fprintf(fp, "\n"); -		} -		if(info->replaces) { -			fputs("%REPLACES%\n", fp); -			for(lp = info->replaces; lp; lp = lp->next) { -				char *depstring = alpm_dep_compute_string(lp->data); -				fprintf(fp, "%s\n", depstring); -				free(depstring); -			} -			fprintf(fp, "\n"); +			fputc('\n', fp);  		}  		if(info->url) {  			fprintf(fp, "%%URL%%\n" @@ -784,9 +815,10 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, alpm_dbinfrq_t inforeq  		if(info->licenses) {  			fputs("%LICENSE%\n", fp);  			for(lp = info->licenses; lp; lp = lp->next) { -				fprintf(fp, "%s\n", (char *)lp->data); +				fputs(lp->data, fp); +				fputc('\n', fp);  			} -			fprintf(fp, "\n"); +			fputc('\n', fp);  		}  		if(info->arch) {  			fprintf(fp, "%%ARCH%%\n" @@ -794,11 +826,11 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, alpm_dbinfrq_t inforeq  		}  		if(info->builddate) {  			fprintf(fp, "%%BUILDDATE%%\n" -							"%ld\n\n", info->builddate); +							"%jd\n\n", (intmax_t)info->builddate);  		}  		if(info->installdate) {  			fprintf(fp, "%%INSTALLDATE%%\n" -							"%ld\n\n", info->installdate); +							"%jd\n\n", (intmax_t)info->installdate);  		}  		if(info->packager) {  			fprintf(fp, "%%PACKAGER%%\n" @@ -813,41 +845,29 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, alpm_dbinfrq_t inforeq  			fprintf(fp, "%%REASON%%\n"  							"%u\n\n", info->reason);  		} -		if(info->depends) { -			fputs("%DEPENDS%\n", fp); -			for(lp = info->depends; lp; lp = lp->next) { -				char *depstring = alpm_dep_compute_string(lp->data); -				fprintf(fp, "%s\n", depstring); -				free(depstring); +		if(info->validation) { +			fputs("%VALIDATION%\n", fp); +			if(info->validation & ALPM_PKG_VALIDATION_NONE) { +				fputs("none\n", fp);  			} -			fprintf(fp, "\n"); -		} -		if(info->optdepends) { -			fputs("%OPTDEPENDS%\n", fp); -			for(lp = info->optdepends; lp; lp = lp->next) { -				fprintf(fp, "%s\n", (char *)lp->data); +			if(info->validation & ALPM_PKG_VALIDATION_MD5SUM) { +				fputs("md5\n", fp);  			} -			fprintf(fp, "\n"); -		} -		if(info->conflicts) { -			fputs("%CONFLICTS%\n", fp); -			for(lp = info->conflicts; lp; lp = lp->next) { -				char *depstring = alpm_dep_compute_string(lp->data); -				fprintf(fp, "%s\n", depstring); -				free(depstring); +			if(info->validation & ALPM_PKG_VALIDATION_SHA256SUM) { +				fputs("sha256\n", fp);  			} -			fprintf(fp, "\n"); -		} -		if(info->provides) { -			fputs("%PROVIDES%\n", fp); -			for(lp = info->provides; lp; lp = lp->next) { -				char *depstring = alpm_dep_compute_string(lp->data); -				fprintf(fp, "%s\n", depstring); -				free(depstring); +			if(info->validation & ALPM_PKG_VALIDATION_SIGNATURE) { +				fputs("pgp\n", fp);  			} -			fprintf(fp, "\n"); +			fputc('\n', fp);  		} +		write_deps(fp, "%REPLACES%", info->replaces); +		write_deps(fp, "%DEPENDS%", info->depends); +		write_deps(fp, "%OPTDEPENDS%", info->optdepends); +		write_deps(fp, "%CONFLICTS%", info->conflicts); +		write_deps(fp, "%PROVIDES%", info->provides); +  		fclose(fp);  		fp = NULL;  	} @@ -868,20 +888,21 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, alpm_dbinfrq_t inforeq  		free(path);  		if(info->files.count) {  			size_t i; -			fprintf(fp, "%%FILES%%\n"); +			fputs("%FILES%\n", fp);  			for(i = 0; i < info->files.count; i++) {  				const alpm_file_t *file = info->files.files + i; -				fprintf(fp, "%s\n", file->name); +				fputs(file->name, fp); +				fputc('\n', fp);  			} -			fprintf(fp, "\n"); +			fputc('\n', fp);  		}  		if(info->backup) { -			fprintf(fp, "%%BACKUP%%\n"); +			fputs("%BACKUP%\n", fp);  			for(lp = info->backup; lp; lp = lp->next) {  				const alpm_backup_t *backup = lp->data;  				fprintf(fp, "%s\t%s\n", backup->name, backup->hash);  			} -			fprintf(fp, "\n"); +			fputc('\n', fp);  		}  		fclose(fp);  		fp = NULL; @@ -903,17 +924,71 @@ cleanup:  int _alpm_local_db_remove(alpm_db_t *db, alpm_pkg_t *info)  {  	int ret = 0; -	char *pkgpath = _alpm_local_db_pkgpath(db, info, NULL); +	DIR *dirp; +	struct dirent *dp; +	char *pkgpath; +	size_t pkgpath_len; -	/* TODO explicit file removes and then an rmdir? */ -	ret = _alpm_rmrf(pkgpath); -	free(pkgpath); -	if(ret != 0) { +	pkgpath = _alpm_local_db_pkgpath(db, info, NULL); +	if(!pkgpath) { +		return -1; +	} +	pkgpath_len = strlen(pkgpath); + +	dirp = opendir(pkgpath); +	if(!dirp) { +		return -1; +	} +	/* go through the local DB entry, removing the files within, which we know +	 * are not nested directories of any kind. */ +	for(dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { +		if(strcmp(dp->d_name, "..") != 0 && strcmp(dp->d_name, ".") != 0) { +			char name[PATH_MAX]; +			if(pkgpath_len + strlen(dp->d_name) + 2 > PATH_MAX) { +				/* file path is too long to remove, hmm. */ +				ret = -1; +			} else { +				sprintf(name, "%s/%s", pkgpath, dp->d_name); +				if(unlink(name)) { +					ret = -1; +				} +			} +		} +	} +	closedir(dirp); + +	/* after removing all enclosed files, we can remove the directory itself. */ +	if(rmdir(pkgpath)) {  		ret = -1;  	} +	free(pkgpath);  	return ret;  } +int SYMEXPORT alpm_pkg_set_reason(alpm_pkg_t *pkg, alpm_pkgreason_t reason) +{ +	ASSERT(pkg != NULL, return -1); +	ASSERT(pkg->origin == PKG_FROM_LOCALDB, +			RET_ERR(pkg->handle, ALPM_ERR_WRONG_ARGS, -1)); +	ASSERT(pkg->origin_data.db == pkg->handle->db_local, +			RET_ERR(pkg->handle, ALPM_ERR_WRONG_ARGS, -1)); + +	_alpm_log(pkg->handle, ALPM_LOG_DEBUG, +			"setting install reason %u for %s\n", reason, pkg->name); +	if(alpm_pkg_get_reason(pkg) == reason) { +		/* we are done */ +		return 0; +	} +	/* set reason (in pkgcache) */ +	pkg->reason = reason; +	/* write DESC */ +	if(_alpm_local_db_write(pkg->handle->db_local, pkg, INFRQ_DESC)) { +		RET_ERR(pkg->handle, ALPM_ERR_DB_WRITE, -1); +	} + +	return 0; +} +  struct db_operations local_db_ops = {  	.validate         = local_db_validate,  	.populate         = local_db_populate, diff --git a/lib/libalpm/be_package.c b/lib/libalpm/be_package.c index 93b762a1..a33a591a 100644 --- a/lib/libalpm/be_package.c +++ b/lib/libalpm/be_package.c @@ -1,7 +1,7 @@  /*   *  be_package.c : backend for packages   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>   *   *  This program is free software; you can redistribute it and/or modify @@ -18,11 +18,12 @@   *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include "config.h" -  #include <stdlib.h>  #include <string.h>  #include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h>  /* libarchive */  #include <archive.h> @@ -35,7 +36,12 @@  #include "log.h"  #include "handle.h"  #include "package.h" -#include "deps.h" /* _alpm_splitdep */ +#include "deps.h" + +struct package_changelog { +	struct archive *archive; +	int fd; +};  /**   * Open a package changelog for reading. Similar to fopen in functionality, @@ -47,31 +53,38 @@ static void *_package_changelog_open(alpm_pkg_t *pkg)  {  	ASSERT(pkg != NULL, return NULL); -	struct archive *archive = NULL; +	struct package_changelog *changelog; +	struct archive *archive;  	struct archive_entry *entry;  	const char *pkgfile = pkg->origin_data.file; +	struct stat buf; +	int fd; -	if((archive = archive_read_new()) == NULL) { -		RET_ERR(pkg->handle, ALPM_ERR_LIBARCHIVE, NULL); -	} - -	archive_read_support_compression_all(archive); -	archive_read_support_format_all(archive); - -	if(archive_read_open_filename(archive, pkgfile, -				ALPM_BUFFER_SIZE) != ARCHIVE_OK) { -		RET_ERR(pkg->handle, ALPM_ERR_PKG_OPEN, NULL); +	fd = _alpm_open_archive(pkg->handle, pkgfile, &buf, +			&archive, ALPM_ERR_PKG_OPEN); +	if(fd < 0) { +		return NULL;  	}  	while(archive_read_next_header(archive, &entry) == ARCHIVE_OK) {  		const char *entry_name = archive_entry_pathname(entry);  		if(strcmp(entry_name, ".CHANGELOG") == 0) { -			return archive; +			changelog = malloc(sizeof(struct package_changelog)); +			if(!changelog) { +				pkg->handle->pm_errno = ALPM_ERR_MEMORY; +				archive_read_finish(archive); +				CLOSE(fd); +				return NULL; +			} +			changelog->archive = archive; +			changelog->fd = fd; +			return changelog;  		}  	}  	/* we didn't find a changelog */  	archive_read_finish(archive); +	CLOSE(fd);  	errno = ENOENT;  	return NULL; @@ -89,7 +102,8 @@ static void *_package_changelog_open(alpm_pkg_t *pkg)  static size_t _package_changelog_read(void *ptr, size_t size,  		const alpm_pkg_t UNUSED *pkg, void *fp)  { -	ssize_t sret = archive_read_data((struct archive *)fp, ptr, size); +	struct package_changelog *changelog = fp; +	ssize_t sret = archive_read_data(changelog->archive, ptr, size);  	/* Report error (negative values) */  	if(sret < 0) {  		RET_ERR(pkg->handle, ALPM_ERR_LIBARCHIVE, 0); @@ -107,7 +121,12 @@ static size_t _package_changelog_read(void *ptr, size_t size,   */  static int _package_changelog_close(const alpm_pkg_t UNUSED *pkg, void *fp)  { -	return archive_read_finish((struct archive *)fp); +	int ret; +	struct package_changelog *changelog = fp; +	ret = archive_read_finish(changelog->archive); +	CLOSE(changelog->fd); +	free(changelog); +	return ret;  }  /** Package file operations struct accessor. We implement this as a method @@ -152,18 +171,21 @@ static int parse_descfile(alpm_handle_t *handle, struct archive *a, alpm_pkg_t *  		size_t len = _alpm_strip_newline(buf.line);  		linenum++; -		if(len == 0 || buf.line[0] == '#') { +		key = buf.line; +		if(len == 0 || key[0] == '#') {  			continue;  		} -		ptr = buf.line; -		key = strsep(&ptr, "="); -		if(key == NULL || ptr == NULL) { -			_alpm_log(handle, ALPM_LOG_DEBUG, "%s: syntax error in description file line %d\n", -								newpkg->name ? newpkg->name : "error", linenum); +		/* line is always in this format: "key = value" +		 * we can be sure the " = " exists, so look for that */ +		ptr = memchr(key, ' ', len); +		if(!ptr || (size_t)(ptr - key + 2) > len || memcmp(ptr, " = ", 3) != 0) { +			_alpm_log(handle, ALPM_LOG_DEBUG, +					"%s: syntax error in description file line %d\n", +					newpkg->name ? newpkg->name : "error", linenum);  		} else { -			key = _alpm_strtrim(key); -			while(*ptr == ' ') ptr++; -			ptr = _alpm_strtrim(ptr); +			/* NULL the end of the key portion, move ptr to start of value */ +			*ptr = '\0'; +			ptr += 3;  			if(strcmp(key, "pkgname") == 0) {  				STRDUP(newpkg->name, ptr, return -1);  				newpkg->name_hash = _alpm_hash_sdbm(newpkg->name); @@ -192,7 +214,8 @@ static int parse_descfile(alpm_handle_t *handle, struct archive *a, alpm_pkg_t *  				alpm_depend_t *dep = _alpm_splitdep(ptr);  				newpkg->depends = alpm_list_add(newpkg->depends, dep);  			} else if(strcmp(key, "optdepend") == 0) { -				newpkg->optdepends = alpm_list_add(newpkg->optdepends, strdup(ptr)); +				alpm_depend_t *optdep = _alpm_splitdep(ptr); +				newpkg->optdepends = alpm_list_add(newpkg->optdepends, optdep);  			} else if(strcmp(key, "conflict") == 0) {  				alpm_depend_t *conflict = _alpm_splitdep(ptr);  				newpkg->conflicts = alpm_list_add(newpkg->conflicts, conflict); @@ -280,11 +303,12 @@ static alpm_file_t *files_msort(alpm_file_t *files, size_t n)   * sha256sum, and/or base64 signature)   * @param level the required level of signature verification   * @param sigdata signature data from the package to pass back + * @param validation successful validations performed on the package file   * @return 0 if package is fully valid, -1 and pm_errno otherwise   */  int _alpm_pkg_validate_internal(alpm_handle_t *handle,  		const char *pkgfile, alpm_pkg_t *syncpkg, alpm_siglevel_t level, -		alpm_siglist_t **sigdata) +		alpm_siglist_t **sigdata, alpm_pkgvalidation_t *validation)  {  	int has_sig;  	handle->pm_errno = 0; @@ -294,7 +318,7 @@ int _alpm_pkg_validate_internal(alpm_handle_t *handle,  	}  	/* attempt to access the package file, ensure it exists */ -	if(access(pkgfile, R_OK) != 0) { +	if(_alpm_access(handle, NULL, pkgfile, R_OK) != 0) {  		RET_ERR(handle, ALPM_ERR_PKG_NOT_FOUND, -1);  	} @@ -316,17 +340,23 @@ int _alpm_pkg_validate_internal(alpm_handle_t *handle,  		if(syncpkg->md5sum && !syncpkg->sha256sum) {  			_alpm_log(handle, ALPM_LOG_DEBUG, "md5sum: %s\n", syncpkg->md5sum);  			_alpm_log(handle, ALPM_LOG_DEBUG, "checking md5sum for %s\n", pkgfile); -			if(_alpm_test_checksum(pkgfile, syncpkg->md5sum, ALPM_CSUM_MD5) != 0) { +			if(_alpm_test_checksum(pkgfile, syncpkg->md5sum, ALPM_PKG_VALIDATION_MD5SUM) != 0) {  				RET_ERR(handle, ALPM_ERR_PKG_INVALID_CHECKSUM, -1);  			} +			if(validation) { +				*validation |= ALPM_PKG_VALIDATION_MD5SUM; +			}  		}  		if(syncpkg->sha256sum) {  			_alpm_log(handle, ALPM_LOG_DEBUG, "sha256sum: %s\n", syncpkg->sha256sum);  			_alpm_log(handle, ALPM_LOG_DEBUG, "checking sha256sum for %s\n", pkgfile); -			if(_alpm_test_checksum(pkgfile, syncpkg->sha256sum, ALPM_CSUM_SHA256) != 0) { +			if(_alpm_test_checksum(pkgfile, syncpkg->sha256sum, ALPM_PKG_VALIDATION_SHA256SUM) != 0) {  				RET_ERR(handle, ALPM_ERR_PKG_INVALID_CHECKSUM, -1);  			} +			if(validation) { +				*validation |= ALPM_PKG_VALIDATION_SHA256SUM; +			}  		}  	} @@ -340,6 +370,13 @@ int _alpm_pkg_validate_internal(alpm_handle_t *handle,  			handle->pm_errno = ALPM_ERR_PKG_INVALID_SIG;  			return -1;  		} +		if(validation && has_sig) { +			*validation |= ALPM_PKG_VALIDATION_SIGNATURE; +		} +	} + +	if (validation && !*validation) { +		*validation = ALPM_PKG_VALIDATION_NONE;  	}  	return 0; @@ -355,10 +392,10 @@ int _alpm_pkg_validate_internal(alpm_handle_t *handle,  alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle,  		const char *pkgfile, int full)  { -	int ret, config = 0; +	int ret, fd, config = 0;  	struct archive *archive;  	struct archive_entry *entry; -	alpm_pkg_t *newpkg = NULL; +	alpm_pkg_t *newpkg;  	struct stat st;  	size_t files_size = 0; @@ -366,33 +403,22 @@ alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle,  		RET_ERR(handle, ALPM_ERR_WRONG_ARGS, NULL);  	} -	/* attempt to stat the package file, ensure it exists */ -	if(stat(pkgfile, &st) == 0) { -		newpkg = _alpm_pkg_new(); -		if(newpkg == NULL) { -			RET_ERR(handle, ALPM_ERR_MEMORY, NULL); +	fd = _alpm_open_archive(handle, pkgfile, &st, &archive, ALPM_ERR_PKG_OPEN); +	if(fd < 0) { +		if(errno == ENOENT) { +			handle->pm_errno = ALPM_ERR_PKG_NOT_FOUND;  		} -		newpkg->filename = strdup(pkgfile); -		newpkg->size = st.st_size; -	} else { -		/* couldn't stat the pkgfile, return an error */ -		RET_ERR(handle, ALPM_ERR_PKG_NOT_FOUND, NULL); +		return NULL;  	} -	/* try to create an archive object to read in the package */ -	if((archive = archive_read_new()) == NULL) { -		_alpm_pkg_free(newpkg); -		RET_ERR(handle, ALPM_ERR_LIBARCHIVE, NULL); -	} - -	archive_read_support_compression_all(archive); -	archive_read_support_format_all(archive); - -	if(archive_read_open_filename(archive, pkgfile, -				ALPM_BUFFER_SIZE) != ARCHIVE_OK) { -		handle->pm_errno = ALPM_ERR_PKG_OPEN; +	newpkg = _alpm_pkg_new(); +	if(newpkg == NULL) { +		handle->pm_errno = ALPM_ERR_MEMORY;  		goto error;  	} +	STRDUP(newpkg->filename, pkgfile, +			handle->pm_errno = ALPM_ERR_MEMORY; goto error); +	newpkg->size = st.st_size;  	_alpm_log(handle, ALPM_LOG_DEBUG, "starting package load for %s\n", pkgfile); @@ -481,6 +507,7 @@ alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle,  	}  	archive_read_finish(archive); +	CLOSE(fd);  	/* internal fields for package struct */  	newpkg->origin = PKG_FROM_FILE; @@ -488,6 +515,7 @@ alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle,  	newpkg->ops = get_file_pkg_ops();  	newpkg->handle = handle;  	newpkg->infolevel = INFRQ_BASE | INFRQ_DESC | INFRQ_SCRIPTLET; +	newpkg->validation = ALPM_PKG_VALIDATION_NONE;  	if(full) {  		if(newpkg->files.files) { @@ -510,6 +538,9 @@ pkg_invalid:  error:  	_alpm_pkg_free(newpkg);  	archive_read_finish(archive); +	if(fd >= 0) { +		CLOSE(fd); +	}  	return NULL;  } @@ -517,10 +548,13 @@ error:  int SYMEXPORT alpm_pkg_load(alpm_handle_t *handle, const char *filename, int full,  		alpm_siglevel_t level, alpm_pkg_t **pkg)  { +	alpm_pkgvalidation_t validation = 0; +  	CHECK_HANDLE(handle, return -1);  	ASSERT(pkg != NULL, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1)); -	if(_alpm_pkg_validate_internal(handle, filename, NULL, level, NULL) == -1) { +	if(_alpm_pkg_validate_internal(handle, filename, NULL, level, NULL, +				&validation) == -1) {  		/* pm_errno is set by pkg_validate */  		return -1;  	} @@ -529,6 +563,7 @@ int SYMEXPORT alpm_pkg_load(alpm_handle_t *handle, const char *filename, int ful  		/* pm_errno is set by pkg_load */  		return -1;  	} +	(*pkg)->validation = validation;  	return 0;  } diff --git a/lib/libalpm/be_sync.c b/lib/libalpm/be_sync.c index 3c990246..6af5aacd 100644 --- a/lib/libalpm/be_sync.c +++ b/lib/libalpm/be_sync.c @@ -1,7 +1,7 @@  /*   *  be_sync.c : backend for sync databases   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>   *   *  This program is free software; you can redistribute it and/or modify @@ -18,10 +18,10 @@   *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include "config.h" -  #include <errno.h> +#include <sys/types.h>  #include <sys/stat.h> +#include <fcntl.h>  #include <unistd.h>  /* libarchive */ @@ -86,7 +86,7 @@ static int sync_db_validate(alpm_db_t *db)  	}  	/* we can skip any validation if the database doesn't exist */ -	if(access(dbpath, R_OK) != 0 && errno == ENOENT) { +	if(_alpm_access(db->handle, NULL, dbpath, R_OK) != 0 && errno == ENOENT) {  		db->status &= ~DB_STATUS_EXISTS;  		db->status |= DB_STATUS_MISSING;  		_alpm_log(db->handle, ALPM_LOG_WARNING, @@ -212,6 +212,7 @@ int SYMEXPORT alpm_db_update(int force, alpm_db_t *db)  		/* print server + filename into a buffer */  		len = strlen(server) + strlen(db->treename) + 5; +		/* TODO fix leak syncpath and umask unset */  		MALLOC(payload.fileurl, len, RET_ERR(handle, ALPM_ERR_MEMORY, -1));  		snprintf(payload.fileurl, len, "%s/%s.db", server, db->treename);  		payload.handle = handle; @@ -234,6 +235,7 @@ int SYMEXPORT alpm_db_update(int force, alpm_db_t *db)  			/* if we downloaded a DB, we want the .sig from the same server */  			/* print server + filename into a buffer (leave space for .sig) */  			len = strlen(server) + strlen(db->treename) + 9; +			/* TODO fix leak syncpath and umask unset */  			MALLOC(payload.fileurl, len, RET_ERR(handle, ALPM_ERR_MEMORY, -1));  			snprintf(payload.fileurl, len, "%s/%s.db.sig", server, db->treename);  			payload.handle = handle; @@ -294,6 +296,29 @@ cleanup:  static int sync_db_read(alpm_db_t *db, struct archive *archive,  		struct archive_entry *entry, alpm_pkg_t **likely_pkg); +static alpm_pkgvalidation_t _sync_get_validation(alpm_pkg_t *pkg) +{ +	if(pkg->validation) { +		return pkg->validation; +	} + +	if(pkg->md5sum) { +		pkg->validation |= ALPM_PKG_VALIDATION_MD5SUM; +	} +	if(pkg->sha256sum) { +		pkg->validation |= ALPM_PKG_VALIDATION_SHA256SUM; +	} +	if(pkg->base64_sig) { +		pkg->validation |= ALPM_PKG_VALIDATION_SIGNATURE; +	} + +	if(!pkg->validation) { +		pkg->validation |= ALPM_PKG_VALIDATION_NONE; +	} + +	return pkg->validation; +} +  static alpm_pkg_t *load_pkg_for_entry(alpm_db_t *db, const char *entryname,  		const char **entry_filename, alpm_pkg_t *likely_pkg)  { @@ -316,7 +341,8 @@ static alpm_pkg_t *load_pkg_for_entry(alpm_db_t *db, const char *entryname,  		return NULL;  	} -	if(likely_pkg && strcmp(likely_pkg->name, pkgname) == 0) { +	if(likely_pkg && pkgname_hash == likely_pkg->name_hash +			&& strcmp(likely_pkg->name, pkgname) == 0) {  		pkg = likely_pkg;  	} else {  		pkg = _alpm_pkghash_find(db->pkgcache, pkgname); @@ -334,6 +360,7 @@ static alpm_pkg_t *load_pkg_for_entry(alpm_db_t *db, const char *entryname,  		pkg->origin = PKG_FROM_SYNCDB;  		pkg->origin_data.db = db;  		pkg->ops = &default_pkg_ops; +		pkg->ops->get_validation = _sync_get_validation;  		pkg->handle = db->handle;  		/* add to the collection */ @@ -348,61 +375,38 @@ static alpm_pkg_t *load_pkg_for_entry(alpm_db_t *db, const char *entryname,  	return pkg;  } -/* - * This is the data table used to generate the estimating function below. - * "Weighted Avg" means averaging the bottom table values; thus each repo, big - * or small, will have equal influence.  "Unweighted Avg" means averaging the - * sums of the top table columns, thus each package has equal influence.  The - * final values are calculated by (surprise) averaging the averages, because - * why the hell not. - * - * Database   Pkgs  tar      bz2     gz      xz - * community  2096  5294080  256391  421227  301296 - * core        180   460800   25257   36850   29356 - * extra      2606  6635520  294647  470818  339392 - * multilib    126   327680   16120   23261   18732 - * testing      76   204800   10902   14348   12100 - * - * Bytes Per Package - * community  2096  2525.80  122.32  200.97  143.75 - * core        180  2560.00  140.32  204.72  163.09 - * extra      2606  2546.25  113.06  180.67  130.23 - * multilib    126  2600.63  127.94  184.61  148.67 - * testing      76  2694.74  143.45  188.79  159.21 - - * Weighted Avg     2585.48  129.42  191.95  148.99 - * Unweighted Avg   2543.39  118.74  190.16  137.93 - * Average of Avgs  2564.44  124.08  191.06  143.46 - */ +/* This function doesn't work as well as one might think, as size of database + * entries varies considerably. Adding signatures nearly doubles the size of a + * single entry; deltas also can make for large variations in size. These + * current values are heavily influenced by Arch Linux; databases with no + * deltas and a single signature per package. */  static size_t estimate_package_count(struct stat *st, struct archive *archive)  { -	unsigned int per_package; +	int per_package;  	switch(archive_compression(archive)) {  		case ARCHIVE_COMPRESSION_NONE: -			per_package = 2564; +			per_package = 3015;  			break;  		case ARCHIVE_COMPRESSION_GZIP: -			per_package = 191; +		case ARCHIVE_COMPRESSION_COMPRESS: +			per_package = 464;  			break;  		case ARCHIVE_COMPRESSION_BZIP2: -			per_package = 124; -			break; -		case ARCHIVE_COMPRESSION_COMPRESS: -			per_package = 193; +			per_package = 394;  			break;  		case ARCHIVE_COMPRESSION_LZMA:  		case ARCHIVE_COMPRESSION_XZ: -			per_package = 143; +			per_package = 400;  			break;  #ifdef ARCHIVE_COMPRESSION_UU  		case ARCHIVE_COMPRESSION_UU: -			per_package = 3543; +			per_package = 3015 * 4 / 3;  			break;  #endif  		default:  			/* assume it is at least somewhat compressed */ -			per_package = 200; +			per_package = 500;  	}  	return (size_t)((st->st_size / per_package) + 1);  } @@ -411,7 +415,7 @@ static int sync_db_populate(alpm_db_t *db)  {  	const char *dbpath;  	size_t est_count; -	int count = 0; +	int count, fd;  	struct stat buf;  	struct archive *archive;  	struct archive_entry *entry; @@ -423,38 +427,24 @@ static int sync_db_populate(alpm_db_t *db)  	if(db->status & DB_STATUS_MISSING) {  		RET_ERR(db->handle, ALPM_ERR_DB_NOT_FOUND, -1);  	} - -	if((archive = archive_read_new()) == NULL) { -		RET_ERR(db->handle, ALPM_ERR_LIBARCHIVE, -1); -	} - -	archive_read_support_compression_all(archive); -	archive_read_support_format_all(archive); -  	dbpath = _alpm_db_path(db);  	if(!dbpath) {  		/* pm_errno set in _alpm_db_path() */  		return -1;  	} -	_alpm_log(db->handle, ALPM_LOG_DEBUG, "opening database archive %s\n", dbpath); - -	if(archive_read_open_filename(archive, dbpath, -				ALPM_BUFFER_SIZE) != ARCHIVE_OK) { -		_alpm_log(db->handle, ALPM_LOG_ERROR, _("could not open file %s: %s\n"), dbpath, -				archive_error_string(archive)); -		archive_read_finish(archive); -		RET_ERR(db->handle, ALPM_ERR_DB_OPEN, -1); -	} -	if(stat(dbpath, &buf) != 0) { -		RET_ERR(db->handle, ALPM_ERR_DB_OPEN, -1); +	fd = _alpm_open_archive(db->handle, dbpath, &buf, +			&archive, ALPM_ERR_DB_OPEN); +	if(fd < 0) { +		return -1;  	}  	est_count = estimate_package_count(&buf, archive); -	/* initialize hash at 66% full */ -	db->pkgcache = _alpm_pkghash_create(est_count * 3 / 2); +	db->pkgcache = _alpm_pkghash_create(est_count);  	if(db->pkgcache == NULL) { -		RET_ERR(db->handle, ALPM_ERR_MEMORY, -1); +		db->handle->pm_errno = ALPM_ERR_MEMORY; +		count = -1; +		goto cleanup;  	}  	while(archive_read_next_header(archive, &entry) == ARCHIVE_OK) { @@ -473,14 +463,19 @@ static int sync_db_populate(alpm_db_t *db)  	}  	count = alpm_list_count(db->pkgcache->list); -  	if(count > 0) { -		db->pkgcache->list = alpm_list_msort(db->pkgcache->list, (size_t)count, _alpm_pkg_cmp); +		db->pkgcache->list = alpm_list_msort(db->pkgcache->list, +				(size_t)count, _alpm_pkg_cmp);  	} -	archive_read_finish(archive); -	_alpm_log(db->handle, ALPM_LOG_DEBUG, "added %d packages to package cache for db '%s'\n", +	_alpm_log(db->handle, ALPM_LOG_DEBUG, +			"added %d packages to package cache for db '%s'\n",  			count, db->treename); +cleanup: +	archive_read_finish(archive); +	if(fd >= 0) { +		CLOSE(fd); +	}  	return count;  } @@ -595,7 +590,7 @@ static int sync_db_read(alpm_db_t *db, struct archive *archive,  			} else if(strcmp(line, "%DEPENDS%") == 0) {  				READ_AND_SPLITDEP(pkg->depends);  			} else if(strcmp(line, "%OPTDEPENDS%") == 0) { -				READ_AND_STORE_ALL(pkg->optdepends); +				READ_AND_SPLITDEP(pkg->optdepends);  			} else if(strcmp(line, "%CONFLICTS%") == 0) {  				READ_AND_SPLITDEP(pkg->conflicts);  			} else if(strcmp(line, "%PROVIDES%") == 0) { @@ -605,7 +600,8 @@ static int sync_db_read(alpm_db_t *db, struct archive *archive,  				while(1) {  					READ_NEXT();  					if(strlen(line) == 0) break; -					pkg->deltas = alpm_list_add(pkg->deltas, _alpm_delta_parse(line)); +					pkg->deltas = alpm_list_add(pkg->deltas, +							_alpm_delta_parse(db->handle, line));  				}  			}  		} diff --git a/lib/libalpm/conflict.c b/lib/libalpm/conflict.c index 32f6f303..85429029 100644 --- a/lib/libalpm/conflict.c +++ b/lib/libalpm/conflict.c @@ -1,7 +1,7 @@  /*   *  conflict.c   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>   *  Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>   *  Copyright (c) 2006 by David Kimpe <dnaku@frugalware.org> @@ -22,8 +22,6 @@   *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include "config.h" -  #include <stdlib.h>  #include <stdio.h>  #include <string.h> @@ -318,12 +316,16 @@ const alpm_file_t *_alpm_filelist_contains(alpm_filelist_t *filelist,  		const char *name)  {  	size_t i; -	const alpm_file_t *file = filelist->files; -	for(i = 0; i < filelist->count; i++) { +	const alpm_file_t *file; + +	if(!filelist) { +		return NULL; +	} + +	for(file = filelist->files, i = 0; i < filelist->count; file++, i++) {  		if(strcmp(file->name, name) == 0) {  			return file;  		} -		file++;  	}  	return NULL;  } @@ -383,11 +385,14 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,  	alpm_list_t *i, *conflicts = NULL;  	size_t numtargs = alpm_list_count(upgrade);  	size_t current; +	size_t rootlen;  	if(!upgrade) {  		return NULL;  	} +	rootlen = strlen(handle->root); +  	/* TODO this whole function needs a huge change, which hopefully will  	 * be possible with real transactions. Right now we only do half as much  	 * here as we do when we actually extract files in add.c with our 12 @@ -461,8 +466,9 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,  			int resolved_conflict = 0;  			struct stat lsbuf;  			char path[PATH_MAX]; +			size_t pathlen; -			snprintf(path, PATH_MAX, "%s%s", handle->root, filestr); +			pathlen = snprintf(path, PATH_MAX, "%s%s", handle->root, filestr);  			/* stat the file - if it exists, do some checks */  			if(_alpm_lstat(path, &lsbuf) != 0) { @@ -486,10 +492,10 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,  				/* if we made it to here, we want all subsequent path comparisons to  				 * not include the trailing slash. This allows things like file ->  				 * directory replacements. */ -				path[strlen(path) - 1] = '\0'; +				path[pathlen - 1] = '\0';  			} -			relative_path = path + strlen(handle->root); +			relative_path = path + rootlen;  			/* Check remove list (will we remove the conflicting local file?) */  			for(k = remove; k && !resolved_conflict; k = k->next) { @@ -542,9 +548,8 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,  			 * components can be safely checked as all directories are "unowned". */  			if(!resolved_conflict && dbpkg && !S_ISLNK(lsbuf.st_mode)) {  				char *rpath = calloc(PATH_MAX, sizeof(char)); -				const char *relative_rpath;  				if(realpath(path, rpath)) { -					relative_rpath = rpath + strlen(handle->root); +					const char *relative_rpath = rpath + rootlen;  					if(_alpm_filelist_contains(alpm_pkg_get_files(dbpkg), relative_rpath)) {  						_alpm_log(handle, ALPM_LOG_DEBUG,  								"package contained the resolved realpath\n"); diff --git a/lib/libalpm/conflict.h b/lib/libalpm/conflict.h index 8b7471fd..a129d8b0 100644 --- a/lib/libalpm/conflict.h +++ b/lib/libalpm/conflict.h @@ -1,7 +1,7 @@  /*   *  conflict.h   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>   *   *  This program is free software; you can redistribute it and/or modify diff --git a/lib/libalpm/db.c b/lib/libalpm/db.c index 8688a3cd..8bbdc903 100644 --- a/lib/libalpm/db.c +++ b/lib/libalpm/db.c @@ -1,7 +1,7 @@  /*   *  db.c   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>   *  Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>   *  Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu> @@ -22,8 +22,6 @@   *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include "config.h" -  #include <stdio.h>  #include <stdlib.h>  #include <string.h> @@ -45,7 +43,7 @@   */  /** Register a sync database of packages. */ -alpm_db_t SYMEXPORT *alpm_db_register_sync(alpm_handle_t *handle, +alpm_db_t SYMEXPORT *alpm_register_syncdb(alpm_handle_t *handle,  		const char *treename, alpm_siglevel_t level)  {  	/* Sanity checks */ @@ -70,7 +68,7 @@ void _alpm_db_unregister(alpm_db_t *db)  }  /** Unregister all package databases. */ -int SYMEXPORT alpm_db_unregister_all(alpm_handle_t *handle) +int SYMEXPORT alpm_unregister_all_syncdbs(alpm_handle_t *handle)  {  	alpm_list_t *i;  	alpm_db_t *db; @@ -263,7 +261,7 @@ alpm_list_t SYMEXPORT *alpm_db_get_pkgcache(alpm_db_t *db)  }  /** Get a group entry from a package database. */ -alpm_group_t SYMEXPORT *alpm_db_readgroup(alpm_db_t *db, const char *name) +alpm_group_t SYMEXPORT *alpm_db_get_group(alpm_db_t *db, const char *name)  {  	ASSERT(db != NULL, return NULL);  	db->handle->pm_errno = 0; @@ -291,32 +289,6 @@ alpm_list_t SYMEXPORT *alpm_db_search(alpm_db_t *db, const alpm_list_t* needles)  	return _alpm_db_search(db, needles);  } -/** Set install reason for a package in db. */ -int SYMEXPORT alpm_db_set_pkgreason(alpm_handle_t *handle, alpm_pkg_t *pkg, -		alpm_pkgreason_t reason) -{ -	CHECK_HANDLE(handle, return -1); -	ASSERT(pkg != NULL, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1)); -	ASSERT(pkg->origin == PKG_FROM_LOCALDB, -			RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1)); -	ASSERT(pkg->origin_data.db == handle->db_local, -			RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1)); - -	_alpm_log(handle, ALPM_LOG_DEBUG, -			"setting install reason %u for %s\n", reason, pkg->name); -	if(alpm_pkg_get_reason(pkg) == reason) { -		/* we are done */ -		return 0; -	} -	/* set reason (in pkgcache) */ -	pkg->reason = reason; -	/* write DESC */ -	if(_alpm_local_db_write(handle->db_local, pkg, INFRQ_DESC)) { -		RET_ERR(handle, ALPM_ERR_DB_WRITE, -1); -	} - -	return 0; -}  /** @} */ diff --git a/lib/libalpm/db.h b/lib/libalpm/db.h index 224bfbeb..94659b77 100644 --- a/lib/libalpm/db.h +++ b/lib/libalpm/db.h @@ -1,7 +1,7 @@  /*   *  db.h   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>   *  Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>   *  Copyright (c) 2006 by Miklos Vajna <vmiklos@frugalware.org> @@ -22,8 +22,6 @@  #ifndef _ALPM_DB_H  #define _ALPM_DB_H -#include <time.h> -  /* libarchive */  #include <archive.h>  #include <archive_entry.h> diff --git a/lib/libalpm/delta.c b/lib/libalpm/delta.c index 6315a851..26ae5d5d 100644 --- a/lib/libalpm/delta.c +++ b/lib/libalpm/delta.c @@ -1,7 +1,7 @@  /*   *  delta.c   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2007-2006 by Judd Vinet <jvinet@zeroflux.org>   *   *  This program is free software; you can redistribute it and/or modify @@ -18,8 +18,6 @@   *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include "config.h" -  #include <stdlib.h>  #include <string.h>  #include <stdint.h> /* intmax_t */ @@ -266,7 +264,8 @@ static alpm_list_t *find_unused(alpm_list_t *deltas, const char *to, off_t quota  alpm_list_t SYMEXPORT *alpm_pkg_unused_deltas(alpm_pkg_t *pkg)  {  	ASSERT(pkg != NULL, return NULL); -	return find_unused(pkg->deltas, pkg->filename, pkg->size * MAX_DELTA_RATIO); +	return find_unused(pkg->deltas, pkg->filename, +			pkg->size * pkg->handle->deltaratio);  }  /** @} */ @@ -275,51 +274,54 @@ alpm_list_t SYMEXPORT *alpm_pkg_unused_deltas(alpm_pkg_t *pkg)   * This function assumes that the string is in the correct format.   * This format is as follows:   * $deltafile $deltamd5 $deltasize $oldfile $newfile + * @param handle the context handle   * @param line the string to parse   * @return A pointer to the new alpm_delta_t object   */ -/* TODO this does not really belong here, but in a parsing lib */ -alpm_delta_t *_alpm_delta_parse(char *line) +alpm_delta_t *_alpm_delta_parse(alpm_handle_t *handle, const char *line)  {  	alpm_delta_t *delta; -	char *tmp = line, *tmp2; -	regex_t reg; - -	regcomp(®, -			"^[^[:space:]]* [[:xdigit:]]{32} [[:digit:]]*" -			" [^[:space:]]* [^[:space:]]*$", -			REG_EXTENDED | REG_NOSUB | REG_NEWLINE); -	if(regexec(®, line, 0, 0, 0) != 0) { +	const int num_matches = 6; +	size_t len; +	regmatch_t pmatch[num_matches]; +	char filesize[32]; + +	/* this is so we only have to compile the pattern once */ +	if(!handle->delta_regex_compiled) { +		/* $deltafile $deltamd5 $deltasize $oldfile $newfile*/ +		regcomp(&handle->delta_regex, +				"^([^[:space:]]+) ([[:xdigit:]]{32}) ([[:digit:]]+)" +				" ([^[:space:]]+) ([^[:space:]]+)$", +				REG_EXTENDED | REG_NEWLINE); +		handle->delta_regex_compiled = 1; +	} + +	if(regexec(&handle->delta_regex, line, num_matches, pmatch, 0) != 0) {  		/* delta line is invalid, return NULL */ -		regfree(®);  		return NULL;  	} -	regfree(®);  	CALLOC(delta, 1, sizeof(alpm_delta_t), return NULL); -	tmp2 = tmp; -	tmp = strchr(tmp, ' '); -	*(tmp++) = '\0'; -	STRDUP(delta->delta, tmp2, return NULL); +	/* start at index 1 -- match 0 is the entire match */ +	len = pmatch[1].rm_eo - pmatch[1].rm_so; +	STRNDUP(delta->delta, &line[pmatch[1].rm_so], len, return NULL); -	tmp2 = tmp; -	tmp = strchr(tmp, ' '); -	*(tmp++) = '\0'; -	STRDUP(delta->delta_md5, tmp2, return NULL); +	len = pmatch[2].rm_eo - pmatch[2].rm_so; +	STRNDUP(delta->delta_md5, &line[pmatch[2].rm_so], len, return NULL); -	tmp2 = tmp; -	tmp = strchr(tmp, ' '); -	*(tmp++) = '\0'; -	delta->delta_size = _alpm_strtoofft(tmp2); +	len = pmatch[3].rm_eo - pmatch[3].rm_so; +	if(len < sizeof(filesize)) { +		strncpy(filesize, &line[pmatch[3].rm_so], len); +		filesize[len] = '\0'; +		delta->delta_size = _alpm_strtoofft(filesize); +	} -	tmp2 = tmp; -	tmp = strchr(tmp, ' '); -	*(tmp++) = '\0'; -	STRDUP(delta->from, tmp2, return NULL); +	len = pmatch[4].rm_eo - pmatch[4].rm_so; +	STRNDUP(delta->from, &line[pmatch[4].rm_so], len, return NULL); -	tmp2 = tmp; -	STRDUP(delta->to, tmp2, return NULL); +	len = pmatch[5].rm_eo - pmatch[5].rm_so; +	STRNDUP(delta->to, &line[pmatch[5].rm_so], len, return NULL);  	return delta;  } diff --git a/lib/libalpm/delta.h b/lib/libalpm/delta.h index 05df4207..b1c89912 100644 --- a/lib/libalpm/delta.h +++ b/lib/libalpm/delta.h @@ -1,7 +1,7 @@  /*   *  delta.h   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2007-2006 by Judd Vinet <jvinet@zeroflux.org>   *   *  This program is free software; you can redistribute it and/or modify @@ -20,21 +20,16 @@  #ifndef _ALPM_DELTA_H  #define _ALPM_DELTA_H -#include "config.h" /* ensure off_t is correct length */ -  #include <sys/types.h> /* off_t */  #include "alpm.h" -alpm_delta_t *_alpm_delta_parse(char *line); +alpm_delta_t *_alpm_delta_parse(alpm_handle_t *handle, const char *line);  void _alpm_delta_free(alpm_delta_t *delta);  alpm_delta_t *_alpm_delta_dup(const alpm_delta_t *delta);  off_t _alpm_shortest_delta_path(alpm_handle_t *handle, alpm_list_t *deltas,  		const char *to, alpm_list_t **path); -/* max percent of package size to download deltas */ -#define MAX_DELTA_RATIO 0.7 -  #endif /* _ALPM_DELTA_H */  /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c index 0c0a054e..6069f5e6 100644 --- a/lib/libalpm/deps.c +++ b/lib/libalpm/deps.c @@ -1,7 +1,7 @@  /*   *  deps.c   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>   *  Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>   *  Copyright (c) 2005, 2006 by Miklos Vajna <vmiklos@frugalware.org> @@ -20,8 +20,6 @@   *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include "config.h" -  #include <stdlib.h>  #include <stdio.h>  #include <string.h> @@ -41,6 +39,7 @@ void _alpm_dep_free(alpm_depend_t *dep)  {  	FREE(dep->name);  	FREE(dep->version); +	FREE(dep->desc);  	FREE(dep);  } @@ -204,8 +203,10 @@ alpm_list_t *_alpm_sortbydeps(alpm_handle_t *handle,  static int no_dep_version(alpm_handle_t *handle)  { -	int flags = alpm_trans_get_flags(handle); -	return flags != -1 && (flags & ALPM_TRANS_FLAG_NODEPVERSION); +	if(!handle->trans) { +		return 0; +	} +	return (handle->trans->flags & ALPM_TRANS_FLAG_NODEPVERSION);  }  static alpm_depend_t *filtered_depend(alpm_depend_t *dep, int nodepversion) @@ -395,7 +396,7 @@ int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep)  			/* any version will satisfy the requirement */  			satisfy = (provision->name_hash == dep->name_hash  					&& strcmp(provision->name, dep->name) == 0); -		} else if (provision->mod == ALPM_DEP_MOD_EQ) { +		} else if(provision->mod == ALPM_DEP_MOD_EQ) {  			/* provision specifies a version, so try it out */  			satisfy = (provision->name_hash == dep->name_hash  					&& strcmp(provision->name, dep->name) == 0 @@ -409,7 +410,7 @@ int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep)  alpm_depend_t *_alpm_splitdep(const char *depstring)  {  	alpm_depend_t *depend; -	const char *ptr, *version; +	const char *ptr, *version, *desc;  	size_t deplen;  	if(depstring == NULL) { @@ -417,7 +418,17 @@ alpm_depend_t *_alpm_splitdep(const char *depstring)  	}  	MALLOC(depend, sizeof(alpm_depend_t), return NULL); -	deplen = strlen(depstring); + +	/* Note the extra space in ": " to avoid matching the epoch */ +	if((desc = strstr(depstring, ": ")) != NULL) { +		STRDUP(depend->desc, desc + 2, return NULL); +		deplen = desc - depstring; +	} else { +		/* no description- point desc at NULL at end of string for later use */ +		depend->desc = NULL; +		deplen = strlen(depstring); +		desc = depstring + deplen; +	}  	/* Find a version comparator if one exists. If it does, set the type and  	 * increment the ptr accordingly so we can copy the right strings. */ @@ -442,21 +453,18 @@ alpm_depend_t *_alpm_splitdep(const char *depstring)  		depend->mod = ALPM_DEP_MOD_EQ;  		version = ptr + 1;  	} else { -		/* no version specified, leave ptr NULL and set version to NULL */ +		/* no version specified, set ptr to end of string and version to NULL */ +		ptr = depstring + deplen;  		depend->mod = ALPM_DEP_MOD_ANY;  		depend->version = NULL;  		version = NULL;  	}  	/* copy the right parts to the right places */ -	if(ptr) { -		STRNDUP(depend->name, depstring, ptr - depstring, return NULL); -	} else { -		STRDUP(depend->name, depstring, return NULL); -	} +	STRNDUP(depend->name, depstring, ptr - depstring, return NULL);  	depend->name_hash = _alpm_hash_sdbm(depend->name);  	if(version) { -		STRDUP(depend->version, version, return NULL); +		STRNDUP(depend->version, version, desc - version, return NULL);  	}  	return depend; @@ -468,8 +476,9 @@ alpm_depend_t *_alpm_dep_dup(const alpm_depend_t *dep)  	CALLOC(newdep, 1, sizeof(alpm_depend_t), return NULL);  	STRDUP(newdep->name, dep->name, return NULL); -	newdep->name_hash = dep->name_hash;  	STRDUP(newdep->version, dep->version, return NULL); +	STRDUP(newdep->desc, dep->desc, return NULL); +	newdep->name_hash = dep->name_hash;  	newdep->mod = dep->mod;  	return newdep; @@ -792,7 +801,7 @@ int _alpm_resolvedeps(alpm_handle_t *handle, alpm_list_t *localpkgs,   */  char SYMEXPORT *alpm_dep_compute_string(const alpm_depend_t *dep)  { -	const char *name, *opr, *ver; +	const char *name, *opr, *ver, *desc_delim, *desc;  	char *str;  	size_t len; @@ -834,12 +843,21 @@ char SYMEXPORT *alpm_dep_compute_string(const alpm_depend_t *dep)  		ver = "";  	} +	if(dep->desc) { +		desc_delim = ": "; +		desc = dep->desc; +	} else { +		desc_delim = ""; +		desc = ""; +	} +  	/* we can always compute len and print the string like this because opr  	 * and ver will be empty when ALPM_DEP_MOD_ANY is the depend type. the  	 * reassignments above also ensure we do not do a strlen(NULL). */ -	len = strlen(name) + strlen(opr) + strlen(ver) + 1; +	len = strlen(name) + strlen(opr) + strlen(ver) +		+ strlen(desc_delim) + strlen(desc) + 1;  	MALLOC(str, len, return NULL); -	snprintf(str, len, "%s%s%s", name, opr, ver); +	snprintf(str, len, "%s%s%s%s%s", name, opr, ver, desc_delim, desc);  	return str;  } diff --git a/lib/libalpm/deps.h b/lib/libalpm/deps.h index ce25bda6..c8e1bc3d 100644 --- a/lib/libalpm/deps.h +++ b/lib/libalpm/deps.h @@ -1,7 +1,7 @@  /*   *  deps.h   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>   *  Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>   *  Copyright (c) 2006 by Miklos Vajna <vmiklos@frugalware.org> diff --git a/lib/libalpm/diskspace.c b/lib/libalpm/diskspace.c index 45908b22..ac7dab00 100644 --- a/lib/libalpm/diskspace.c +++ b/lib/libalpm/diskspace.c @@ -17,8 +17,6 @@   *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include "config.h" -  #include <stdio.h>  #include <errno.h> @@ -60,6 +58,17 @@ static int mount_point_cmp(const void *p1, const void *p2)  	return -strcmp(mp1->mount_dir, mp2->mount_dir);  } +static void mount_point_list_free(alpm_list_t *mount_points) +{ +	alpm_list_t *i; + +	for(i = mount_points; i; i = i->next) { +		alpm_mountpoint_t *data = i->data; +		FREE(data->mount_dir); +	} +	FREELIST(mount_points); +} +  static alpm_list_t *mount_point_list(alpm_handle_t *handle)  {  	alpm_list_t *mount_points = NULL, *ptr; @@ -288,6 +297,72 @@ static int calculate_installed_size(alpm_handle_t *handle,  	return 0;  } +static int check_mountpoint(alpm_handle_t *handle, alpm_mountpoint_t *mp) +{ +	/* cushion is roughly min(5% capacity, 20MiB) */ +	fsblkcnt_t fivepc = (mp->fsp.f_blocks / 20) + 1; +	fsblkcnt_t twentymb = (20 * 1024 * 1024 / mp->fsp.f_bsize) + 1; +	fsblkcnt_t cushion = fivepc < twentymb ? fivepc : twentymb; +	blkcnt_t needed = mp->max_blocks_needed + cushion; + +	_alpm_log(handle, ALPM_LOG_DEBUG, +			"partition %s, needed %jd, cushion %ju, free %ju\n", +			mp->mount_dir, (intmax_t)mp->max_blocks_needed, +			(uintmax_t)cushion, (uintmax_t)mp->fsp.f_bfree); +	if(needed >= 0 && (fsblkcnt_t)needed > mp->fsp.f_bfree) { +		_alpm_log(handle, ALPM_LOG_ERROR, +				_("Partition %s too full: %jd blocks needed, %jd blocks free\n"), +				mp->mount_dir, (intmax_t)needed, (uintmax_t)mp->fsp.f_bfree); +		return 1; +	} +	return 0; +} + +int _alpm_check_downloadspace(alpm_handle_t *handle, const char *cachedir, +		size_t num_files, off_t *file_sizes) +{ +	alpm_list_t *mount_points; +	alpm_mountpoint_t *cachedir_mp; +	size_t j; +	int error = 0; + +	mount_points = mount_point_list(handle); +	if(mount_points == NULL) { +		_alpm_log(handle, ALPM_LOG_ERROR, _("could not determine filesystem mount points\n")); +		return -1; +	} + +	cachedir_mp = match_mount_point(mount_points, cachedir); +	if(cachedir == NULL) { +		_alpm_log(handle, ALPM_LOG_ERROR, _("could not determine cachedir mount point %s\n"), +				cachedir); +		error = 1; +		goto finish; +	} + +	/* there's no need to check for a R/O mounted filesystem here, as +	 * _alpm_filecache_setup will never give us a non-writable directory */ + +	/* round up the size of each file to the nearest block and accumulate */ +	for(j = 0; j < num_files; j++) { +		cachedir_mp->max_blocks_needed += (file_sizes[j] + cachedir_mp->fsp.f_bsize + 1) / +			cachedir_mp->fsp.f_bsize; +	} + +	if(check_mountpoint(handle, cachedir_mp)) { +		error = 1; +	} + +finish: +	mount_point_list_free(mount_points); + +	if(error) { +		RET_ERR(handle, ALPM_ERR_DISK_SPACE, -1); +	} + +	return 0; +} +  int _alpm_check_diskspace(alpm_handle_t *handle)  {  	alpm_list_t *mount_points, *i; @@ -356,32 +431,13 @@ int _alpm_check_diskspace(alpm_handle_t *handle)  			_alpm_log(handle, ALPM_LOG_ERROR, _("Partition %s is mounted read only\n"),  					data->mount_dir);  			error = 1; -		} else if(data->used & USED_INSTALL) { -			/* cushion is roughly min(5% capacity, 20MiB) */ -			fsblkcnt_t fivepc = (data->fsp.f_blocks / 20) + 1; -			fsblkcnt_t twentymb = (20 * 1024 * 1024 / data->fsp.f_bsize) + 1; -			fsblkcnt_t cushion = fivepc < twentymb ? fivepc : twentymb; -			blkcnt_t needed = data->max_blocks_needed + cushion; - -			_alpm_log(handle, ALPM_LOG_DEBUG, -					"partition %s, needed %jd, cushion %ju, free %ju\n", -					data->mount_dir, (intmax_t)data->max_blocks_needed, -					(uintmax_t)cushion, (uintmax_t)data->fsp.f_bfree); -			if(needed >= 0 && (fsblkcnt_t)needed > data->fsp.f_bfree) { -				_alpm_log(handle, ALPM_LOG_ERROR, -						_("Partition %s too full: %jd blocks needed, %jd blocks free\n"), -						data->mount_dir, (intmax_t)needed, (uintmax_t)data->fsp.f_bfree); -				error = 1; -			} +		} else if(data->used & USED_INSTALL && check_mountpoint(handle, data)) { +			error = 1;  		}  	}  finish: -	for(i = mount_points; i; i = i->next) { -		alpm_mountpoint_t *data = i->data; -		FREE(data->mount_dir); -	} -	FREELIST(mount_points); +	mount_point_list_free(mount_points);  	if(error) {  		RET_ERR(handle, ALPM_ERR_DISK_SPACE, -1); diff --git a/lib/libalpm/diskspace.h b/lib/libalpm/diskspace.h index 5944bb17..a54aa5e3 100644 --- a/lib/libalpm/diskspace.h +++ b/lib/libalpm/diskspace.h @@ -1,7 +1,7 @@  /*   *  diskspace.h   * - *  Copyright (c) 2010-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2010-2012 Pacman Development Team <pacman-dev@archlinux.org>   *   *  This program is free software; you can redistribute it and/or modify   *  it under the terms of the GNU General Public License as published by @@ -50,6 +50,8 @@ typedef struct __alpm_mountpoint_t {  } alpm_mountpoint_t;  int _alpm_check_diskspace(alpm_handle_t *handle); +int _alpm_check_downloadspace(alpm_handle_t *handle, const char *cachedir, +		size_t num_files, off_t *file_sizes);  #endif /* _ALPM_DISKSPACE_H */ diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c index 9d982183..b3ac024c 100644 --- a/lib/libalpm/dload.c +++ b/lib/libalpm/dload.c @@ -18,8 +18,6 @@   *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include "config.h" -  #include <stdlib.h>  #include <stdio.h>  #include <errno.h> @@ -357,9 +355,7 @@ static FILE *create_tempfile(struct dload_payload *payload, const char *localpat  			fchmod(fd, ~(_getumask()) & 0666) ||  			!(fp = fdopen(fd, payload->tempfile_openmode))) {  		unlink(randpath); -		if(fd >= 0) { -			close(fd); -		} +		CLOSE(fd);  		_alpm_log(payload->handle, ALPM_LOG_ERROR,  				_("failed to create temporary file for download\n"));  		return NULL; @@ -431,6 +427,10 @@ static int curl_download_internal(struct dload_payload *payload,  	if(localf == NULL) {  		localf = fopen(payload->tempfile_name, payload->tempfile_openmode);  		if(localf == NULL) { +			handle->pm_errno = ALPM_ERR_RETRIEVE; +			_alpm_log(handle, ALPM_LOG_ERROR, +					_("could not open file %s: %s\n"), +					payload->tempfile_name, strerror(errno));  			goto cleanup;  		}  	} diff --git a/lib/libalpm/dload.h b/lib/libalpm/dload.h index f5f2cd9c..e279d564 100644 --- a/lib/libalpm/dload.h +++ b/lib/libalpm/dload.h @@ -1,7 +1,7 @@  /*   *  dload.h   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>   *   *  This program is free software; you can redistribute it and/or modify @@ -23,8 +23,6 @@  #include "alpm_list.h"  #include "alpm.h" -#include <time.h> -  struct dload_payload {  	alpm_handle_t *handle;  	const char *tempfile_openmode; @@ -40,6 +38,7 @@ struct dload_payload {  	int allow_resume;  	int errors_ok;  	int unlink_on_fail; +	alpm_list_t *servers;  #ifdef HAVE_LIBCURL  	CURLcode curlerr;       /* last error produced by curl */  #endif diff --git a/lib/libalpm/error.c b/lib/libalpm/error.c index b3f56819..5354a47e 100644 --- a/lib/libalpm/error.c +++ b/lib/libalpm/error.c @@ -1,7 +1,7 @@  /*   *  error.c   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>   *   *  This program is free software; you can redistribute it and/or modify @@ -18,8 +18,6 @@   *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include "config.h" -  #ifdef HAVE_LIBCURL  #include <curl/curl.h>  #endif @@ -29,12 +27,12 @@  #include "alpm.h"  #include "handle.h" -enum _alpm_errno_t SYMEXPORT alpm_errno(alpm_handle_t *handle) +alpm_errno_t SYMEXPORT alpm_errno(alpm_handle_t *handle)  {  	return handle->pm_errno;  } -const char SYMEXPORT *alpm_strerror(enum _alpm_errno_t err) +const char SYMEXPORT *alpm_strerror(alpm_errno_t err)  {  	switch(err) {  		/* System */ diff --git a/lib/libalpm/graph.c b/lib/libalpm/graph.c index 3a7f24b8..69be9e30 100644 --- a/lib/libalpm/graph.c +++ b/lib/libalpm/graph.c @@ -1,7 +1,7 @@  /*   *  graph.c - helpful graph structure and setup/teardown methods   * - *  Copyright (c) 2007-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2007-2012 Pacman Development Team <pacman-dev@archlinux.org>   *   *  This program is free software; you can redistribute it and/or modify   *  it under the terms of the GNU General Public License as published by @@ -17,8 +17,6 @@   *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include "config.h" -  #include "graph.h"  #include "util.h"  #include "log.h" diff --git a/lib/libalpm/graph.h b/lib/libalpm/graph.h index d4d134b5..463b2cd8 100644 --- a/lib/libalpm/graph.h +++ b/lib/libalpm/graph.h @@ -1,7 +1,7 @@  /*   *  graph.h - helpful graph structure and setup/teardown methods   * - *  Copyright (c) 2007-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2007-2012 Pacman Development Team <pacman-dev@archlinux.org>   *   *  This program is free software; you can redistribute it and/or modify   *  it under the terms of the GNU General Public License as published by @@ -19,8 +19,6 @@  #ifndef _ALPM_GRAPH_H  #define _ALPM_GRAPH_H -#include "config.h" /* ensure off_t is correct length */ -  #include <sys/types.h> /* off_t */  #include "alpm_list.h" diff --git a/lib/libalpm/group.c b/lib/libalpm/group.c index 47458df2..4f4d8ce0 100644 --- a/lib/libalpm/group.c +++ b/lib/libalpm/group.c @@ -1,7 +1,7 @@  /*   *  group.c   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>   *   *  This program is free software; you can redistribute it and/or modify @@ -18,8 +18,6 @@   *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include "config.h" -  #include <stdlib.h>  #include <string.h> diff --git a/lib/libalpm/group.h b/lib/libalpm/group.h index 078c9af7..1f776ebf 100644 --- a/lib/libalpm/group.h +++ b/lib/libalpm/group.h @@ -1,7 +1,7 @@  /*   *  group.h   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>   *   *  This program is free software; you can redistribute it and/or modify diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c index 7402be50..2db27fbf 100644 --- a/lib/libalpm/handle.c +++ b/lib/libalpm/handle.c @@ -1,7 +1,7 @@  /*   *  handle.c   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>   *  Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>   *  Copyright (c) 2005, 2006 by Miklos Vajna <vmiklos@frugalware.org> @@ -20,8 +20,6 @@   *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include "config.h" -  #include <errno.h>  #include <stdlib.h>  #include <string.h> @@ -36,6 +34,7 @@  #include "alpm_list.h"  #include "util.h"  #include "log.h" +#include "delta.h"  #include "trans.h"  #include "alpm.h" @@ -44,6 +43,7 @@ alpm_handle_t *_alpm_handle_new(void)  	alpm_handle_t *handle;  	CALLOC(handle, 1, sizeof(alpm_handle_t), return NULL); +	handle->deltaratio = 0.0;  	return handle;  } @@ -69,6 +69,8 @@ void _alpm_handle_free(alpm_handle_t *handle)  	curl_easy_cleanup(handle->curl);  #endif +	regfree(&handle->delta_regex); +  	/* free memory */  	_alpm_trans_free(handle->trans);  	FREE(handle->root); @@ -251,10 +253,10 @@ const char SYMEXPORT *alpm_option_get_arch(alpm_handle_t *handle)  	return handle->arch;  } -int SYMEXPORT alpm_option_get_usedelta(alpm_handle_t *handle) +double SYMEXPORT alpm_option_get_deltaratio(alpm_handle_t *handle)  {  	CHECK_HANDLE(handle, return -1); -	return handle->usedelta; +	return handle->deltaratio;  }  int SYMEXPORT alpm_option_get_checkspace(alpm_handle_t *handle) @@ -263,18 +265,6 @@ int SYMEXPORT alpm_option_get_checkspace(alpm_handle_t *handle)  	return handle->checkspace;  } -alpm_db_t SYMEXPORT *alpm_option_get_localdb(alpm_handle_t *handle) -{ -	CHECK_HANDLE(handle, return NULL); -	return handle->db_local; -} - -alpm_list_t SYMEXPORT *alpm_option_get_syncdbs(alpm_handle_t *handle) -{ -	CHECK_HANDLE(handle, return NULL); -	return handle->dbs_sync; -} -  int SYMEXPORT alpm_option_set_logcb(alpm_handle_t *handle, alpm_cb_log cb)  {  	CHECK_HANDLE(handle, return -1); @@ -339,7 +329,7 @@ static char *canonicalize_path(const char *path) {  	return new_path;  } -enum _alpm_errno_t _alpm_set_directory_option(const char *value, +alpm_errno_t _alpm_set_directory_option(const char *value,  		char **storage, int must_exist)   {  	struct stat st; @@ -596,10 +586,13 @@ int SYMEXPORT alpm_option_set_arch(alpm_handle_t *handle, const char *arch)  	return 0;  } -int SYMEXPORT alpm_option_set_usedelta(alpm_handle_t *handle, int usedelta) +int SYMEXPORT alpm_option_set_deltaratio(alpm_handle_t *handle, double ratio)  {  	CHECK_HANDLE(handle, return -1); -	handle->usedelta = usedelta; +	if(ratio < 0.0 || ratio > 2.0) { +		RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1); +	} +	handle->deltaratio = ratio;  	return 0;  } @@ -630,4 +623,16 @@ alpm_siglevel_t SYMEXPORT alpm_option_get_default_siglevel(alpm_handle_t *handle  	return handle->siglevel;  } +alpm_db_t SYMEXPORT *alpm_get_localdb(alpm_handle_t *handle) +{ +	CHECK_HANDLE(handle, return NULL); +	return handle->db_local; +} + +alpm_list_t SYMEXPORT *alpm_get_syncdbs(alpm_handle_t *handle) +{ +	CHECK_HANDLE(handle, return NULL); +	return handle->dbs_sync; +} +  /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/handle.h b/lib/libalpm/handle.h index 8477dcae..c0ad6686 100644 --- a/lib/libalpm/handle.h +++ b/lib/libalpm/handle.h @@ -1,7 +1,7 @@  /*   *  handle.h   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>   *   *  This program is free software; you can redistribute it and/or modify @@ -22,6 +22,7 @@  #include <stdio.h>  #include <sys/types.h> +#include <regex.h>  #include "alpm_list.h"  #include "alpm.h" @@ -86,14 +87,18 @@ struct __alpm_handle_t {  	alpm_list_t *ignoregroup; /* List of groups to ignore */  	/* options */ -	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 */ +	double deltaratio;       /* Download deltas if possible; a ratio value */ +	int usesyslog;           /* Use syslog instead of logfile? */ /* TODO move to frontend */  	int checkspace;          /* Check disk space before installing */  	alpm_siglevel_t siglevel;   /* Default signature verification level */  	/* error code */ -	enum _alpm_errno_t pm_errno; +	alpm_errno_t pm_errno; + +	/* for delta parsing efficiency */ +	int delta_regex_compiled; +	regex_t delta_regex;  };  alpm_handle_t *_alpm_handle_new(void); @@ -102,7 +107,7 @@ void _alpm_handle_free(alpm_handle_t *handle);  int _alpm_handle_lock(alpm_handle_t *handle);  int _alpm_handle_unlock(alpm_handle_t *handle); -enum _alpm_errno_t _alpm_set_directory_option(const char *value, +alpm_errno_t _alpm_set_directory_option(const char *value,  		char **storage, int must_exist);  #endif /* _ALPM_HANDLE_H */ diff --git a/lib/libalpm/log.c b/lib/libalpm/log.c index 692ff79c..8486716e 100644 --- a/lib/libalpm/log.c +++ b/lib/libalpm/log.c @@ -1,7 +1,7 @@  /*   *  log.c   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>   *   *  This program is free software; you can redistribute it and/or modify @@ -18,8 +18,6 @@   *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include "config.h" -  #include <stdio.h>  #include <stdarg.h>  #include <errno.h> diff --git a/lib/libalpm/log.h b/lib/libalpm/log.h index a43290d8..22c3d065 100644 --- a/lib/libalpm/log.h +++ b/lib/libalpm/log.h @@ -1,7 +1,7 @@  /*   *  log.h   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>   *   *  This program is free software; you can redistribute it and/or modify diff --git a/lib/libalpm/md5.c b/lib/libalpm/md5.c index b4391a61..0d5ed9e0 100644 --- a/lib/libalpm/md5.c +++ b/lib/libalpm/md5.c @@ -33,33 +33,34 @@   *  GPL. This is from version 1.0.0 of the library, and has been modified   *  as following, which may be helpful for future updates:   *  * remove "polarssl/config.h" include - *  * change include from "polarssl/sha2.h" to "sha2.h" + *  * change include from "polarssl/md5.h" to "md5.h"   *  * removal of HMAC code   *  * removal of SELF_TEST code - *  * removal of ipad and opad from the md5_context struct in sha2.h + *  * removal of ipad and opad from the md5_context struct in md5.h   *  * increase the size of buffer for performance reasons - *  * various static changes + *  * change 'unsigned long' to uint32_t   */  #include <stdio.h> +#include <stdint.h>  #include "md5.h"  /*   * 32-bit integer manipulation macros (little endian)   */ -#ifndef GET_ULONG_LE -#define GET_ULONG_LE(n,b,i)                             \ +#ifndef GET_U32_LE +#define GET_U32_LE(n,b,i)                               \  {                                                       \ -    (n) = ( (unsigned long) (b)[(i)    ]       )        \ -        | ( (unsigned long) (b)[(i) + 1] <<  8 )        \ -        | ( (unsigned long) (b)[(i) + 2] << 16 )        \ -        | ( (unsigned long) (b)[(i) + 3] << 24 );       \ +    (n) = ( (uint32_t) (b)[(i)    ]       )             \ +        | ( (uint32_t) (b)[(i) + 1] <<  8 )             \ +        | ( (uint32_t) (b)[(i) + 2] << 16 )             \ +        | ( (uint32_t) (b)[(i) + 3] << 24 );            \  }  #endif -#ifndef PUT_ULONG_LE -#define PUT_ULONG_LE(n,b,i)                             \ +#ifndef PUT_U32_LE +#define PUT_U32_LE(n,b,i)                               \  {                                                       \      (b)[(i)    ] = (unsigned char) ( (n)       );       \      (b)[(i) + 1] = (unsigned char) ( (n) >>  8 );       \ @@ -84,24 +85,24 @@ static void md5_starts( md5_context *ctx )  static void md5_process( md5_context *ctx, const unsigned char data[64] )  { -    unsigned long X[16], A, B, C, D; - -    GET_ULONG_LE( X[ 0], data,  0 ); -    GET_ULONG_LE( X[ 1], data,  4 ); -    GET_ULONG_LE( X[ 2], data,  8 ); -    GET_ULONG_LE( X[ 3], data, 12 ); -    GET_ULONG_LE( X[ 4], data, 16 ); -    GET_ULONG_LE( X[ 5], data, 20 ); -    GET_ULONG_LE( X[ 6], data, 24 ); -    GET_ULONG_LE( X[ 7], data, 28 ); -    GET_ULONG_LE( X[ 8], data, 32 ); -    GET_ULONG_LE( X[ 9], data, 36 ); -    GET_ULONG_LE( X[10], data, 40 ); -    GET_ULONG_LE( X[11], data, 44 ); -    GET_ULONG_LE( X[12], data, 48 ); -    GET_ULONG_LE( X[13], data, 52 ); -    GET_ULONG_LE( X[14], data, 56 ); -    GET_ULONG_LE( X[15], data, 60 ); +    uint32_t X[16], A, B, C, D; + +    GET_U32_LE( X[ 0], data,  0 ); +    GET_U32_LE( X[ 1], data,  4 ); +    GET_U32_LE( X[ 2], data,  8 ); +    GET_U32_LE( X[ 3], data, 12 ); +    GET_U32_LE( X[ 4], data, 16 ); +    GET_U32_LE( X[ 5], data, 20 ); +    GET_U32_LE( X[ 6], data, 24 ); +    GET_U32_LE( X[ 7], data, 28 ); +    GET_U32_LE( X[ 8], data, 32 ); +    GET_U32_LE( X[ 9], data, 36 ); +    GET_U32_LE( X[10], data, 40 ); +    GET_U32_LE( X[11], data, 44 ); +    GET_U32_LE( X[12], data, 48 ); +    GET_U32_LE( X[13], data, 52 ); +    GET_U32_LE( X[14], data, 56 ); +    GET_U32_LE( X[15], data, 60 );  #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) @@ -211,7 +212,7 @@ static void md5_process( md5_context *ctx, const unsigned char data[64] )  static void md5_update( md5_context *ctx, const unsigned char *input, size_t ilen )  {      size_t fill; -    unsigned long left; +    uint32_t left;      if( ilen <= 0 )          return; @@ -219,10 +220,10 @@ static void md5_update( md5_context *ctx, const unsigned char *input, size_t ile      left = ctx->total[0] & 0x3F;      fill = 64 - left; -    ctx->total[0] += (unsigned long) ilen; +    ctx->total[0] += (uint32_t) ilen;      ctx->total[0] &= 0xFFFFFFFF; -    if( ctx->total[0] < (unsigned long) ilen ) +    if( ctx->total[0] < (uint32_t) ilen )          ctx->total[1]++;      if( left && ilen >= fill ) @@ -262,16 +263,16 @@ static const unsigned char md5_padding[64] =   */  static void md5_finish( md5_context *ctx, unsigned char output[16] )  { -    unsigned long last, padn; -    unsigned long high, low; +    uint32_t last, padn; +    uint32_t high, low;      unsigned char msglen[8];      high = ( ctx->total[0] >> 29 )           | ( ctx->total[1] <<  3 );      low  = ( ctx->total[0] <<  3 ); -    PUT_ULONG_LE( low,  msglen, 0 ); -    PUT_ULONG_LE( high, msglen, 4 ); +    PUT_U32_LE( low,  msglen, 0 ); +    PUT_U32_LE( high, msglen, 4 );      last = ctx->total[0] & 0x3F;      padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); @@ -279,10 +280,10 @@ static void md5_finish( md5_context *ctx, unsigned char output[16] )      md5_update( ctx, (unsigned char *) md5_padding, padn );      md5_update( ctx, msglen, 8 ); -    PUT_ULONG_LE( ctx->state[0], output,  0 ); -    PUT_ULONG_LE( ctx->state[1], output,  4 ); -    PUT_ULONG_LE( ctx->state[2], output,  8 ); -    PUT_ULONG_LE( ctx->state[3], output, 12 ); +    PUT_U32_LE( ctx->state[0], output,  0 ); +    PUT_U32_LE( ctx->state[1], output,  4 ); +    PUT_U32_LE( ctx->state[2], output,  8 ); +    PUT_U32_LE( ctx->state[3], output, 12 );  }  /* diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c index a5ff238f..6b648675 100644 --- a/lib/libalpm/package.c +++ b/lib/libalpm/package.c @@ -1,7 +1,7 @@  /*   *  package.c   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>   *  Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>   *  Copyright (c) 2005, 2006 by Christian Hamar <krics@linuxforum.hu> @@ -21,8 +21,6 @@   *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include "config.h" -  #include <stdlib.h>  #include <string.h>  #include <sys/types.h> @@ -69,7 +67,7 @@ int SYMEXPORT alpm_pkg_checkmd5sum(alpm_pkg_t *pkg)  	fpath = _alpm_filecache_find(pkg->handle, pkg->filename); -	retval = _alpm_test_checksum(fpath, pkg->md5sum, ALPM_CSUM_MD5); +	retval = _alpm_test_checksum(fpath, pkg->md5sum, ALPM_PKG_VALIDATION_MD5SUM);  	if(retval == 0) {  		return 0; @@ -87,12 +85,13 @@ int SYMEXPORT alpm_pkg_checkmd5sum(alpm_pkg_t *pkg)   * populated package structures. */  static const char *_pkg_get_desc(alpm_pkg_t *pkg)        { return pkg->desc; }  static const char *_pkg_get_url(alpm_pkg_t *pkg)         { return pkg->url; } -static time_t _pkg_get_builddate(alpm_pkg_t *pkg)        { return pkg->builddate; } -static time_t _pkg_get_installdate(alpm_pkg_t *pkg)      { return pkg->installdate; } +static alpm_time_t _pkg_get_builddate(alpm_pkg_t *pkg)   { return pkg->builddate; } +static alpm_time_t _pkg_get_installdate(alpm_pkg_t *pkg) { return pkg->installdate; }  static const char *_pkg_get_packager(alpm_pkg_t *pkg)    { return pkg->packager; }  static const char *_pkg_get_arch(alpm_pkg_t *pkg)        { return pkg->arch; }  static off_t _pkg_get_isize(alpm_pkg_t *pkg)             { return pkg->isize; } -static alpm_pkgreason_t _pkg_get_reason(alpm_pkg_t *pkg)    { return pkg->reason; } +static alpm_pkgreason_t _pkg_get_reason(alpm_pkg_t *pkg) { return pkg->reason; } +static alpm_pkgvalidation_t _pkg_get_validation(alpm_pkg_t *pkg) { return pkg->validation; }  static int _pkg_has_scriptlet(alpm_pkg_t *pkg)           { return pkg->scriptlet; }  static alpm_list_t *_pkg_get_licenses(alpm_pkg_t *pkg)   { return pkg->licenses; } @@ -136,6 +135,7 @@ struct pkg_operations default_pkg_ops = {  	.get_arch        = _pkg_get_arch,  	.get_isize       = _pkg_get_isize,  	.get_reason      = _pkg_get_reason, +	.get_validation  = _pkg_get_validation,  	.has_scriptlet   = _pkg_has_scriptlet,  	.get_licenses    = _pkg_get_licenses, @@ -200,14 +200,14 @@ const char SYMEXPORT *alpm_pkg_get_url(alpm_pkg_t *pkg)  	return pkg->ops->get_url(pkg);  } -time_t SYMEXPORT alpm_pkg_get_builddate(alpm_pkg_t *pkg) +alpm_time_t SYMEXPORT alpm_pkg_get_builddate(alpm_pkg_t *pkg)  {  	ASSERT(pkg != NULL, return -1);  	pkg->handle->pm_errno = 0;  	return pkg->ops->get_builddate(pkg);  } -time_t SYMEXPORT alpm_pkg_get_installdate(alpm_pkg_t *pkg) +alpm_time_t SYMEXPORT alpm_pkg_get_installdate(alpm_pkg_t *pkg)  {  	ASSERT(pkg != NULL, return -1);  	pkg->handle->pm_errno = 0; @@ -270,6 +270,13 @@ alpm_pkgreason_t SYMEXPORT alpm_pkg_get_reason(alpm_pkg_t *pkg)  	return pkg->ops->get_reason(pkg);  } +alpm_pkgvalidation_t SYMEXPORT alpm_pkg_get_validation(alpm_pkg_t *pkg) +{ +	ASSERT(pkg != NULL, return -1); +	pkg->handle->pm_errno = 0; +	return pkg->ops->get_validation(pkg); +} +  alpm_list_t SYMEXPORT *alpm_pkg_get_licenses(alpm_pkg_t *pkg)  {  	ASSERT(pkg != NULL, return NULL); @@ -461,6 +468,15 @@ alpm_pkg_t *_alpm_pkg_new(void)  	return pkg;  } +static alpm_list_t *list_depdup(alpm_list_t *old) +{ +	alpm_list_t *i, *new = NULL; +	for(i = old; i; i = i->next) { +		new = alpm_list_add(new, _alpm_dep_dup(i->data)); +	} +	return new; +} +  /**   * Duplicate a package data struct.   * @param pkg the package to duplicate @@ -509,10 +525,19 @@ int _alpm_pkg_dup(alpm_pkg_t *pkg, alpm_pkg_t **new_ptr)  	newpkg->reason = pkg->reason;  	newpkg->licenses   = alpm_list_strdup(pkg->licenses); -	for(i = pkg->replaces; i; i = i->next) { -		newpkg->replaces = alpm_list_add(newpkg->replaces, _alpm_dep_dup(i->data)); -	} +	newpkg->replaces   = list_depdup(pkg->replaces);  	newpkg->groups     = alpm_list_strdup(pkg->groups); +	for(i = pkg->backup; i; i = i->next) { +		newpkg->backup = alpm_list_add(newpkg->backup, _alpm_backup_dup(i->data)); +	} +	newpkg->depends    = list_depdup(pkg->depends); +	newpkg->optdepends = list_depdup(pkg->optdepends); +	newpkg->conflicts  = list_depdup(pkg->conflicts); +	newpkg->provides   = list_depdup(pkg->provides); +	for(i = pkg->deltas; i; i = i->next) { +		newpkg->deltas = alpm_list_add(newpkg->deltas, _alpm_delta_dup(i->data)); +	} +  	if(pkg->files.count) {  		size_t filenum;  		size_t len = sizeof(alpm_file_t) * pkg->files.count; @@ -525,22 +550,6 @@ int _alpm_pkg_dup(alpm_pkg_t *pkg, alpm_pkg_t **new_ptr)  		}  		newpkg->files.count = pkg->files.count;  	} -	for(i = pkg->backup; i; i = i->next) { -		newpkg->backup = alpm_list_add(newpkg->backup, _alpm_backup_dup(i->data)); -	} -	for(i = pkg->depends; i; i = i->next) { -		newpkg->depends = alpm_list_add(newpkg->depends, _alpm_dep_dup(i->data)); -	} -	newpkg->optdepends = alpm_list_strdup(pkg->optdepends); -	for(i = pkg->conflicts; i; i = i->next) { -		newpkg->conflicts = alpm_list_add(newpkg->conflicts, _alpm_dep_dup(i->data)); -	} -	for(i = pkg->provides; i; i = i->next) { -		newpkg->provides = alpm_list_add(newpkg->provides, _alpm_dep_dup(i->data)); -	} -	for(i = pkg->deltas; i; i = i->next) { -		newpkg->deltas = alpm_list_add(newpkg->deltas, _alpm_delta_dup(i->data)); -	}  	/* internal */  	newpkg->infolevel = pkg->infolevel; @@ -561,6 +570,12 @@ cleanup:  	RET_ERR(pkg->handle, ALPM_ERR_MEMORY, -1);  } +static void free_deplist(alpm_list_t *deps) +{ +	alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_dep_free); +	alpm_list_free(deps); +} +  void _alpm_pkg_free(alpm_pkg_t *pkg)  {  	if(pkg == NULL) { @@ -579,8 +594,7 @@ void _alpm_pkg_free(alpm_pkg_t *pkg)  	FREE(pkg->arch);  	FREELIST(pkg->licenses); -	alpm_list_free_inner(pkg->replaces, (alpm_list_fn_free)_alpm_dep_free); -	alpm_list_free(pkg->replaces); +	free_deplist(pkg->replaces);  	FREELIST(pkg->groups);  	if(pkg->files.count) {  		size_t i; @@ -591,13 +605,10 @@ void _alpm_pkg_free(alpm_pkg_t *pkg)  	}  	alpm_list_free_inner(pkg->backup, (alpm_list_fn_free)_alpm_backup_free);  	alpm_list_free(pkg->backup); -	alpm_list_free_inner(pkg->depends, (alpm_list_fn_free)_alpm_dep_free); -	alpm_list_free(pkg->depends); -	FREELIST(pkg->optdepends); -	alpm_list_free_inner(pkg->conflicts, (alpm_list_fn_free)_alpm_dep_free); -	alpm_list_free(pkg->conflicts); -	alpm_list_free_inner(pkg->provides, (alpm_list_fn_free)_alpm_dep_free); -	alpm_list_free(pkg->provides); +	free_deplist(pkg->depends); +	free_deplist(pkg->optdepends); +	free_deplist(pkg->conflicts); +	free_deplist(pkg->provides);  	alpm_list_free_inner(pkg->deltas, (alpm_list_fn_free)_alpm_delta_free);  	alpm_list_free(pkg->deltas);  	alpm_list_free(pkg->delta_path); @@ -690,14 +701,14 @@ int _alpm_pkg_should_ignore(alpm_handle_t *handle, alpm_pkg_t *pkg)  	alpm_list_t *groups = NULL;  	/* first see if the package is ignored */ -	if(alpm_list_find_str(handle->ignorepkg, pkg->name)) { +	if(alpm_list_find(handle->ignorepkg, pkg->name, _alpm_fnmatch)) {  		return 1;  	}  	/* next see if the package is in a group that is ignored */ -	for(groups = handle->ignoregroup; groups; groups = groups->next) { +	for(groups = alpm_pkg_get_groups(pkg); groups; groups = groups->next) {  		char *grp = groups->data; -		if(alpm_list_find_str(alpm_pkg_get_groups(pkg), grp)) { +		if(alpm_list_find(handle->ignoregroup, grp, _alpm_fnmatch)) {  			return 1;  		}  	} diff --git a/lib/libalpm/package.h b/lib/libalpm/package.h index eff7d898..be779b46 100644 --- a/lib/libalpm/package.h +++ b/lib/libalpm/package.h @@ -1,7 +1,7 @@  /*   *  package.h   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>   *  Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>   *  Copyright (c) 2006 by David Kimpe <dnaku@frugalware.org> @@ -24,10 +24,7 @@  #ifndef _ALPM_PACKAGE_H  #define _ALPM_PACKAGE_H -#include "config.h" /* ensure off_t is correct length */ -  #include <sys/types.h> /* off_t */ -#include <time.h> /* time_t */  #include "alpm.h"  #include "backup.h" @@ -44,12 +41,13 @@  struct pkg_operations {  	const char *(*get_desc) (alpm_pkg_t *);  	const char *(*get_url) (alpm_pkg_t *); -	time_t (*get_builddate) (alpm_pkg_t *); -	time_t (*get_installdate) (alpm_pkg_t *); +	alpm_time_t (*get_builddate) (alpm_pkg_t *); +	alpm_time_t (*get_installdate) (alpm_pkg_t *);  	const char *(*get_packager) (alpm_pkg_t *);  	const char *(*get_arch) (alpm_pkg_t *);  	off_t (*get_isize) (alpm_pkg_t *);  	alpm_pkgreason_t (*get_reason) (alpm_pkg_t *); +	alpm_pkgvalidation_t (*get_validation) (alpm_pkg_t *);  	int (*has_scriptlet) (alpm_pkg_t *);  	alpm_list_t *(*get_licenses) (alpm_pkg_t *); @@ -89,8 +87,8 @@ struct __alpm_pkg_t {  	char *base64_sig;  	char *arch; -	time_t builddate; -	time_t installdate; +	alpm_time_t builddate; +	alpm_time_t installdate;  	off_t size;  	off_t isize; @@ -99,6 +97,7 @@ struct __alpm_pkg_t {  	int scriptlet;  	alpm_pkgreason_t reason; +	alpm_pkgvalidation_t validation;  	alpm_dbinfrq_t infolevel;  	alpm_pkgfrom_t origin;  	/* origin == PKG_FROM_FILE, use pkg->origin_data.file @@ -136,7 +135,7 @@ void _alpm_pkg_free_trans(alpm_pkg_t *pkg);  int _alpm_pkg_validate_internal(alpm_handle_t *handle,  		const char *pkgfile, alpm_pkg_t *syncpkg, alpm_siglevel_t level, -		alpm_siglist_t **sigdata); +		alpm_siglist_t **sigdata, alpm_pkgvalidation_t *validation);  alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle,  		const char *pkgfile, int full); diff --git a/lib/libalpm/pkghash.c b/lib/libalpm/pkghash.c index 963ba25e..7b388004 100644 --- a/lib/libalpm/pkghash.c +++ b/lib/libalpm/pkghash.c @@ -1,7 +1,7 @@  /*   *  pkghash.c   * - *  Copyright (c) 2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2011-2012 Pacman Development Team <pacman-dev@archlinux.org>   *   *  This program is free software; you can redistribute it and/or modify   *  it under the terms of the GNU General Public License as published by @@ -26,42 +26,51 @@   *   * The maximum table size is the last prime under 1,000,000.  That is   * more than an order of magnitude greater than the number of packages - * in any Linux distribution. + * in any Linux distribution, and well under UINT_MAX.   */ -static const size_t prime_list[] = +static const unsigned int prime_list[] =  { -	11ul, 13ul, 17ul, 19ul, 23ul, 29ul, 31ul, 37ul, 41ul, 43ul, 47ul, -	53ul, 59ul, 61ul, 67ul, 71ul, 73ul, 79ul, 83ul, 89ul, 97ul, 103ul, -	109ul, 113ul, 127ul, 137ul, 139ul, 149ul, 157ul, 167ul, 179ul, 193ul, -	199ul, 211ul, 227ul, 241ul, 257ul, 277ul, 293ul, 313ul, 337ul, 359ul, -	383ul, 409ul, 439ul, 467ul, 503ul, 541ul, 577ul, 619ul, 661ul, 709ul, -	761ul, 823ul, 887ul, 953ul, 1031ul, 1109ul, 1193ul, 1289ul, 1381ul, -	1493ul, 1613ul, 1741ul, 1879ul, 2029ul, 2179ul, 2357ul, 2549ul, -	2753ul, 2971ul, 3209ul, 3469ul, 3739ul, 4027ul, 4349ul, 4703ul, -	5087ul, 5503ul, 5953ul, 6427ul, 6949ul, 7517ul, 8123ul, 8783ul, -	9497ul, 10273ul, 11113ul, 12011ul, 12983ul, 14033ul, 15173ul, -	16411ul, 17749ul, 19183ul, 20753ul, 22447ul, 24281ul, 26267ul, -	28411ul, 30727ul, 33223ul, 35933ul, 38873ul, 42043ul, 45481ul, -	49201ul, 53201ul, 57557ul, 62233ul, 67307ul, 72817ul, 78779ul, -	85229ul, 92203ul, 99733ul, 107897ul, 116731ul, 126271ul, 136607ul, -	147793ul, 159871ul, 172933ul, 187091ul, 202409ul, 218971ul, 236897ul, -	256279ul, 277261ul, 299951ul, 324503ul, 351061ul, 379787ul, 410857ul, -	444487ul, 480881ul, 520241ul, 562841ul, 608903ul, 658753ul, 712697ul, -	771049ul, 834181ul, 902483ul, 976369ul +	11u, 13u, 17u, 19u, 23u, 29u, 31u, 37u, 41u, 43u, 47u, +	53u, 59u, 61u, 67u, 71u, 73u, 79u, 83u, 89u, 97u, 103u, +	109u, 113u, 127u, 137u, 139u, 149u, 157u, 167u, 179u, 193u, +	199u, 211u, 227u, 241u, 257u, 277u, 293u, 313u, 337u, 359u, +	383u, 409u, 439u, 467u, 503u, 541u, 577u, 619u, 661u, 709u, +	761u, 823u, 887u, 953u, 1031u, 1109u, 1193u, 1289u, 1381u, +	1493u, 1613u, 1741u, 1879u, 2029u, 2179u, 2357u, 2549u, +	2753u, 2971u, 3209u, 3469u, 3739u, 4027u, 4349u, 4703u, +	5087u, 5503u, 5953u, 6427u, 6949u, 7517u, 8123u, 8783u, +	9497u, 10273u, 11113u, 12011u, 12983u, 14033u, 15173u, +	16411u, 17749u, 19183u, 20753u, 22447u, 24281u, 26267u, +	28411u, 30727u, 33223u, 35933u, 38873u, 42043u, 45481u, +	49201u, 53201u, 57557u, 62233u, 67307u, 72817u, 78779u, +	85229u, 92203u, 99733u, 107897u, 116731u, 126271u, 136607u, +	147793u, 159871u, 172933u, 187091u, 202409u, 218971u, 236897u, +	256279u, 277261u, 299951u, 324503u, 351061u, 379787u, 410857u, +	444487u, 480881u, 520241u, 562841u, 608903u, 658753u, 712697u, +	771049u, 834181u, 902483u, 976369u  }; -/* Allocate a hash table with at least "size" buckets */ -alpm_pkghash_t *_alpm_pkghash_create(size_t size) +/* How far forward do we look when linear probing for a spot? */ +static const unsigned int stride = 1; +/* What is the maximum load percentage of our hash table? */ +static const double max_hash_load = 0.68; +/* Initial load percentage given a certain size */ +static const double initial_hash_load = 0.58; + +/* Allocate a hash table with space for at least "size" elements */ +alpm_pkghash_t *_alpm_pkghash_create(unsigned int size)  {  	alpm_pkghash_t *hash = NULL; -	size_t i, loopsize; +	unsigned int i, loopsize;  	CALLOC(hash, 1, sizeof(alpm_pkghash_t), return NULL); +	size = size / initial_hash_load + 1;  	loopsize = sizeof(prime_list) / sizeof(*prime_list);  	for(i = 0; i < loopsize; i++) {  		if(prime_list[i] > size) {  			hash->buckets = prime_list[i]; +			hash->limit = hash->buckets * max_hash_load;  			break;  		}  	} @@ -78,15 +87,19 @@ alpm_pkghash_t *_alpm_pkghash_create(size_t size)  	return hash;  } -static size_t get_hash_position(unsigned long name_hash, alpm_pkghash_t *hash) +static unsigned int get_hash_position(unsigned long name_hash, +		alpm_pkghash_t *hash)  { -	size_t position; +	unsigned int position;  	position = name_hash % hash->buckets;  	/* collision resolution using open addressing with linear probing */  	while(hash->hash_table[position] != NULL) { -		position = (position + 1) % hash->buckets; +		position += stride; +		while(position >= hash->buckets) { +			position -= hash->buckets; +		}  	}  	return position; @@ -96,7 +109,7 @@ static size_t get_hash_position(unsigned long name_hash, alpm_pkghash_t *hash)  static alpm_pkghash_t *rehash(alpm_pkghash_t *oldhash)  {  	alpm_pkghash_t *newhash; -	size_t newsize, position, i; +	unsigned int newsize, i;  	/* Hash tables will need resized in two cases:  	 *  - adding packages to the local database @@ -129,8 +142,7 @@ static alpm_pkghash_t *rehash(alpm_pkghash_t *oldhash)  	for(i = 0; i < oldhash->buckets; i++) {  		if(oldhash->hash_table[i] != NULL) {  			alpm_pkg_t *package = oldhash->hash_table[i]->data; - -			position = get_hash_position(package->name_hash, newhash); +			unsigned int position = get_hash_position(package->name_hash, newhash);  			newhash->hash_table[position] = oldhash->hash_table[i];  			oldhash->hash_table[i] = NULL; @@ -144,16 +156,17 @@ static alpm_pkghash_t *rehash(alpm_pkghash_t *oldhash)  	return newhash;  } -static alpm_pkghash_t *pkghash_add_pkg(alpm_pkghash_t *hash, alpm_pkg_t *pkg, int sorted) +static alpm_pkghash_t *pkghash_add_pkg(alpm_pkghash_t *hash, alpm_pkg_t *pkg, +		int sorted)  {  	alpm_list_t *ptr; -	size_t position; +	unsigned int position;  	if(pkg == NULL || hash == NULL) {  		return hash;  	} -	if((hash->entries + 1) / MAX_HASH_LOAD > hash->buckets) { +	if(hash->entries >= hash->limit) {  		hash = rehash(hash);  	} @@ -189,7 +202,8 @@ alpm_pkghash_t *_alpm_pkghash_add_sorted(alpm_pkghash_t *hash, alpm_pkg_t *pkg)  	return pkghash_add_pkg(hash, pkg, 1);  } -static size_t move_one_entry(alpm_pkghash_t *hash, size_t start, size_t end) +static unsigned int move_one_entry(alpm_pkghash_t *hash, +		unsigned int start, unsigned int end)  {  	/* Iterate backwards from 'end' to 'start', seeing if any of the items  	 * would hash to 'start'. If we find one, we move it there and break.  If @@ -201,7 +215,7 @@ static size_t move_one_entry(alpm_pkghash_t *hash, size_t start, size_t end)  	while(end != start) {  		alpm_list_t *i = hash->hash_table[end];  		alpm_pkg_t *info = i->data; -		size_t new_position = get_hash_position(info->name_hash, hash); +		unsigned int new_position = get_hash_position(info->name_hash, hash);  		if(new_position == start) {  			hash->hash_table[start] = i; @@ -212,7 +226,7 @@ static size_t move_one_entry(alpm_pkghash_t *hash, size_t start, size_t end)  		/* the odd math ensures we are always positive, e.g.  		 * e.g. (0 - 1) % 47      == -1  		 * e.g. (47 + 0 - 1) % 47 == 46 */ -		end = (hash->buckets + end - 1) % hash->buckets; +		end = (hash->buckets + end - stride) % hash->buckets;  	}  	return end;  } @@ -230,7 +244,7 @@ alpm_pkghash_t *_alpm_pkghash_remove(alpm_pkghash_t *hash, alpm_pkg_t *pkg,  		alpm_pkg_t **data)  {  	alpm_list_t *i; -	size_t position; +	unsigned int position;  	if(data) {  		*data = NULL; @@ -246,7 +260,7 @@ alpm_pkghash_t *_alpm_pkghash_remove(alpm_pkghash_t *hash, alpm_pkg_t *pkg,  		if(info->name_hash == pkg->name_hash &&  					strcmp(info->name, pkg->name) == 0) { -			size_t stop, prev; +			unsigned int stop, prev;  			/* remove from list and hash */  			hash->list = alpm_list_remove_item(hash->list, i); @@ -260,11 +274,17 @@ alpm_pkghash_t *_alpm_pkghash_remove(alpm_pkghash_t *hash, alpm_pkg_t *pkg,  			/* Potentially move entries following removed entry to keep open  			 * addressing collision resolution working. We start by finding the  			 * next null bucket to know how far we have to look. */ -			stop = (position + 1) % hash->buckets; +			stop = position + stride; +			while(stop >= hash->buckets) { +				stop -= hash->buckets; +			}  			while(hash->hash_table[stop] != NULL && stop != position) { -				stop = (stop + 1) % hash->buckets; +				stop += stride; +				while(stop >= hash->buckets) { +					stop -= hash->buckets; +				}  			} -			stop = (hash->buckets + stop - 1) % hash->buckets; +			stop = (hash->buckets + stop - stride) % hash->buckets;  			/* We now search backwards from stop to position. If we find an  			 * item that now hashes to position, we will move it, and then try @@ -277,7 +297,10 @@ alpm_pkghash_t *_alpm_pkghash_remove(alpm_pkghash_t *hash, alpm_pkg_t *pkg,  			return hash;  		} -		position = (position + 1) % hash->buckets; +		position += stride; +		while(position >= hash->buckets) { +			position -= hash->buckets; +		}  	}  	return hash; @@ -285,8 +308,8 @@ alpm_pkghash_t *_alpm_pkghash_remove(alpm_pkghash_t *hash, alpm_pkg_t *pkg,  void _alpm_pkghash_free(alpm_pkghash_t *hash)  { -	size_t i;  	if(hash != NULL) { +		unsigned int i;  		for(i = 0; i < hash->buckets; i++) {  			free(hash->hash_table[i]);  		} @@ -299,7 +322,7 @@ alpm_pkg_t *_alpm_pkghash_find(alpm_pkghash_t *hash, const char *name)  {  	alpm_list_t *lp;  	unsigned long name_hash; -	size_t position; +	unsigned int position;  	if(name == NULL || hash == NULL) {  		return NULL; @@ -316,7 +339,10 @@ alpm_pkg_t *_alpm_pkghash_find(alpm_pkghash_t *hash, const char *name)  			return info;  		} -		position = (position + 1) % hash->buckets; +		position += stride; +		while(position >= hash->buckets) { +			position -= hash->buckets; +		}  	}  	return NULL; diff --git a/lib/libalpm/pkghash.h b/lib/libalpm/pkghash.h index edd500e9..a2c39c7f 100644 --- a/lib/libalpm/pkghash.h +++ b/lib/libalpm/pkghash.h @@ -1,7 +1,7 @@  /*   *  pkghash.h   * - *  Copyright (c) 2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2011-2012 Pacman Development Team <pacman-dev@archlinux.org>   *   *  This program is free software; you can redistribute it and/or modify   *  it under the terms of the GNU General Public License as published by @@ -35,17 +35,19 @@  struct __alpm_pkghash_t {  	/** data held by the hash table */  	alpm_list_t **hash_table; -	/** number of buckets in hash table */ -	size_t buckets; -	/** number of entries in hash table */ -	size_t entries;  	/** head node of the hash table data in normal list format */  	alpm_list_t *list; +	/** number of buckets in hash table */ +	unsigned int buckets; +	/** number of entries in hash table */ +	unsigned int entries; +	/** max number of entries before a resize is needed */ +	unsigned int limit;  };  typedef struct __alpm_pkghash_t alpm_pkghash_t; -alpm_pkghash_t *_alpm_pkghash_create(size_t size); +alpm_pkghash_t *_alpm_pkghash_create(unsigned int size);  alpm_pkghash_t *_alpm_pkghash_add(alpm_pkghash_t *hash, alpm_pkg_t *pkg);  alpm_pkghash_t *_alpm_pkghash_add_sorted(alpm_pkghash_t *hash, alpm_pkg_t *pkg); @@ -55,6 +57,4 @@ void _alpm_pkghash_free(alpm_pkghash_t *hash);  alpm_pkg_t *_alpm_pkghash_find(alpm_pkghash_t *hash, const char *name); -#define MAX_HASH_LOAD 0.7 -  #endif /* _ALPM_PKGHASH_H */ diff --git a/lib/libalpm/remove.c b/lib/libalpm/remove.c index cc9e289d..469ce9bb 100644 --- a/lib/libalpm/remove.c +++ b/lib/libalpm/remove.c @@ -22,8 +22,6 @@   *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include "config.h" -  #include <stdlib.h>  #include <errno.h>  #include <string.h> @@ -216,7 +214,7 @@ static int can_remove_file(alpm_handle_t *handle, const alpm_file_t *file,  {  	char filepath[PATH_MAX]; -	if(alpm_list_find_str(skip_remove, file->name)) { +	if(alpm_list_find(skip_remove, file->name, _alpm_fnmatch)) {  		/* return success because we will never actually remove this file */  		return 1;  	} @@ -239,8 +237,9 @@ static int can_remove_file(alpm_handle_t *handle, const alpm_file_t *file,  /* Helper function for iterating through a package's file and deleting them   * Used by _alpm_remove_commit. */ -static int unlink_file(alpm_handle_t *handle, alpm_pkg_t *info, -		const alpm_file_t *fileobj, alpm_list_t *skip_remove, int nosave) +static int unlink_file(alpm_handle_t *handle, alpm_pkg_t *oldpkg, +		alpm_pkg_t *newpkg, const alpm_file_t *fileobj, alpm_list_t *skip_remove, +		int nosave)  {  	struct stat buf;  	char file[PATH_MAX]; @@ -250,7 +249,7 @@ static int unlink_file(alpm_handle_t *handle, alpm_pkg_t *info,  	/* 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, fileobj->name)) { +	if(alpm_list_find(skip_remove, fileobj->name, _alpm_fnmatch)) {  		_alpm_log(handle, ALPM_LOG_DEBUG,  				"%s is in skip_remove, skipping removal\n", file);  		return 1; @@ -274,6 +273,10 @@ static int unlink_file(alpm_handle_t *handle, alpm_pkg_t *info,  		} else if(files < 0) {  			_alpm_log(handle, ALPM_LOG_DEBUG,  					"keeping directory %s (could not count files)\n", file); +		} else if(newpkg && _alpm_filelist_contains(alpm_pkg_get_files(newpkg), +					fileobj->name)) { +			_alpm_log(handle, ALPM_LOG_DEBUG, +					"keeping directory %s (in new package)\n", file);  		} else {  			/* one last check- does any other package own this file? */  			alpm_list_t *local, *local_pkgs; @@ -285,7 +288,8 @@ static int unlink_file(alpm_handle_t *handle, alpm_pkg_t *info,  				/* we duplicated the package when we put it in the removal list, so we  				 * so we can't use direct pointer comparison here. */ -				if(_alpm_pkg_cmp(info, local_pkg) == 0) { +				if(oldpkg->name_hash == local_pkg->name_hash +						&& strcmp(oldpkg->name, local_pkg->name) == 0) {  					continue;  				}  				filelist = alpm_pkg_get_files(local_pkg); @@ -308,7 +312,7 @@ static int unlink_file(alpm_handle_t *handle, alpm_pkg_t *info,  		}  	} else {  		/* if the file needs backup and has been modified, back it up to .pacsave */ -		alpm_backup_t *backup = _alpm_needbackup(fileobj->name, info); +		alpm_backup_t *backup = _alpm_needbackup(fileobj->name, oldpkg);  		if(backup) {  			if(nosave) {  				_alpm_log(handle, ALPM_LOG_DEBUG, "transaction is set to NOSAVE, not backing up '%s'\n", file); @@ -350,38 +354,15 @@ static int unlink_file(alpm_handle_t *handle, alpm_pkg_t *info,  	return 0;  } -int _alpm_remove_single_package(alpm_handle_t *handle, +static int remove_package_files(alpm_handle_t *handle,  		alpm_pkg_t *oldpkg, alpm_pkg_t *newpkg,  		size_t targ_count, size_t pkg_count)  {  	alpm_list_t *skip_remove; -	size_t filenum = 0, position = 0; -	const char *pkgname = oldpkg->name; -	const char *pkgver = oldpkg->version;  	alpm_filelist_t *filelist;  	size_t i; - -	if(newpkg) { -		_alpm_log(handle, ALPM_LOG_DEBUG, "removing old package first (%s-%s)\n", -				pkgname, pkgver); -	} else { -		EVENT(handle, ALPM_EVENT_REMOVE_START, oldpkg, NULL); -		_alpm_log(handle, ALPM_LOG_DEBUG, "removing package %s-%s\n", -				pkgname, pkgver); - -		/* run the pre-remove scriptlet if it exists  */ -		if(alpm_pkg_has_scriptlet(oldpkg) && -				!(handle->trans->flags & ALPM_TRANS_FLAG_NOSCRIPTLET)) { -			char *scriptlet = _alpm_local_db_pkgpath(handle->db_local, -					oldpkg, "install"); -			_alpm_runscriptlet(handle, scriptlet, "pre_remove", pkgver, NULL, 0); -			free(scriptlet); -		} -	} - -	if(handle->trans->flags & ALPM_TRANS_FLAG_DBONLY) { -		goto db; -	} +	int err = 0; +	int nosave = handle->trans->flags & ALPM_TRANS_FLAG_NOSAVE;  	if(newpkg) {  		alpm_filelist_t *newfiles; @@ -412,54 +393,89 @@ int _alpm_remove_single_package(alpm_handle_t *handle,  		alpm_file_t *file = filelist->files + i;  		if(!can_remove_file(handle, file, skip_remove)) {  			_alpm_log(handle, ALPM_LOG_DEBUG, -					"not removing package '%s', can't remove all files\n", pkgname); +					"not removing package '%s', can't remove all files\n", +					oldpkg->name); +			FREELIST(skip_remove);  			RET_ERR(handle, ALPM_ERR_PKG_CANT_REMOVE, -1);  		} -		filenum++;  	} -	_alpm_log(handle, ALPM_LOG_DEBUG, "removing %ld files\n", (unsigned long)filenum); +	_alpm_log(handle, ALPM_LOG_DEBUG, "removing %zd files\n", filelist->count);  	if(!newpkg) {  		/* init progress bar, but only on true remove transactions */ -		PROGRESS(handle, ALPM_PROGRESS_REMOVE_START, pkgname, 0, +		PROGRESS(handle, ALPM_PROGRESS_REMOVE_START, oldpkg->name, 0,  				pkg_count, targ_count);  	}  	/* iterate through the list backwards, unlinking files */  	for(i = filelist->count; i > 0; i--) {  		alpm_file_t *file = filelist->files + i - 1; -		int percent; -		/* TODO: check return code and handle accordingly */ -		unlink_file(handle, oldpkg, file, skip_remove, -				handle->trans->flags & ALPM_TRANS_FLAG_NOSAVE); +		if(unlink_file(handle, oldpkg, newpkg, file, skip_remove, nosave) < 0) { +			err++; +		}  		if(!newpkg) {  			/* update progress bar after each file */ -			percent = (position * 100) / filenum; -			PROGRESS(handle, ALPM_PROGRESS_REMOVE_START, pkgname, +			int percent = ((filelist->count - i) * 100) / filelist->count; +			PROGRESS(handle, ALPM_PROGRESS_REMOVE_START, oldpkg->name,  					percent, pkg_count, targ_count);  		} -		position++;  	}  	FREELIST(skip_remove);  	if(!newpkg) {  		/* set progress to 100% after we finish unlinking files */ -		PROGRESS(handle, ALPM_PROGRESS_REMOVE_START, pkgname, 100, +		PROGRESS(handle, ALPM_PROGRESS_REMOVE_START, oldpkg->name, 100,  				pkg_count, targ_count); +	} + +	return err; +} -		/* run the post-remove script if it exists  */ +int _alpm_remove_single_package(alpm_handle_t *handle, +		alpm_pkg_t *oldpkg, alpm_pkg_t *newpkg, +		size_t targ_count, size_t pkg_count) +{ +	const char *pkgname = oldpkg->name; +	const char *pkgver = oldpkg->version; + +	if(newpkg) { +		_alpm_log(handle, ALPM_LOG_DEBUG, "removing old package first (%s-%s)\n", +				pkgname, pkgver); +	} else { +		EVENT(handle, ALPM_EVENT_REMOVE_START, oldpkg, NULL); +		_alpm_log(handle, ALPM_LOG_DEBUG, "removing package %s-%s\n", +				pkgname, pkgver); + +		/* run the pre-remove scriptlet if it exists  */  		if(alpm_pkg_has_scriptlet(oldpkg) &&  				!(handle->trans->flags & ALPM_TRANS_FLAG_NOSCRIPTLET)) {  			char *scriptlet = _alpm_local_db_pkgpath(handle->db_local,  					oldpkg, "install"); -			_alpm_runscriptlet(handle, scriptlet, "post_remove", pkgver, NULL, 0); +			_alpm_runscriptlet(handle, scriptlet, "pre_remove", pkgver, NULL, 0);  			free(scriptlet);  		}  	} -db: +	if(!(handle->trans->flags & ALPM_TRANS_FLAG_DBONLY)) { +		/* TODO check returned errors if any */ +		remove_package_files(handle, oldpkg, newpkg, targ_count, pkg_count); +	} + +	/* run the post-remove script if it exists  */ +	if(!newpkg && alpm_pkg_has_scriptlet(oldpkg) && +			!(handle->trans->flags & ALPM_TRANS_FLAG_NOSCRIPTLET)) { +		char *scriptlet = _alpm_local_db_pkgpath(handle->db_local, +				oldpkg, "install"); +		_alpm_runscriptlet(handle, scriptlet, "post_remove", pkgver, NULL, 0); +		free(scriptlet); +	} + +	if(!newpkg) { +		EVENT(handle, ALPM_EVENT_REMOVE_DONE, oldpkg, NULL); +	} +  	/* remove the package from the database */  	_alpm_log(handle, ALPM_LOG_DEBUG, "removing database entry '%s'\n", pkgname);  	if(_alpm_local_db_remove(handle->db_local, oldpkg) == -1) { @@ -472,11 +488,6 @@ db:  				pkgname);  	} -	if(!newpkg) { -		/* TODO: awesome! we're passing invalid pointers. */ -		EVENT(handle, ALPM_EVENT_REMOVE_DONE, oldpkg, NULL); -	} -  	return 0;  } diff --git a/lib/libalpm/remove.h b/lib/libalpm/remove.h index 251e4548..203eccb4 100644 --- a/lib/libalpm/remove.h +++ b/lib/libalpm/remove.h @@ -1,7 +1,7 @@  /*   *  remove.h   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>   *   *  This program is free software; you can redistribute it and/or modify diff --git a/lib/libalpm/sha2.c b/lib/libalpm/sha2.c index 3632c131..366dc650 100644 --- a/lib/libalpm/sha2.c +++ b/lib/libalpm/sha2.c @@ -38,28 +38,29 @@   *  * removal of SELF_TEST code   *  * removal of ipad and opad from the sha2_context struct in sha2.h   *  * increase the size of buffer for performance reasons - *  * various static changes + *  * change 'unsigned long' to uint32_t   */  #include <stdio.h> +#include <stdint.h>  #include "sha2.h"  /*   * 32-bit integer manipulation macros (big endian)   */ -#ifndef GET_ULONG_BE -#define GET_ULONG_BE(n,b,i)                             \ +#ifndef GET_U32_BE +#define GET_U32_BE(n,b,i)                               \  {                                                       \ -    (n) = ( (unsigned long) (b)[(i)    ] << 24 )        \ -        | ( (unsigned long) (b)[(i) + 1] << 16 )        \ -        | ( (unsigned long) (b)[(i) + 2] <<  8 )        \ -        | ( (unsigned long) (b)[(i) + 3]       );       \ +    (n) = ( (uint32_t) (b)[(i)    ] << 24 )             \ +        | ( (uint32_t) (b)[(i) + 1] << 16 )             \ +        | ( (uint32_t) (b)[(i) + 2] <<  8 )             \ +        | ( (uint32_t) (b)[(i) + 3]       );            \  }  #endif -#ifndef PUT_ULONG_BE -#define PUT_ULONG_BE(n,b,i)                             \ +#ifndef PUT_U32_BE +#define PUT_U32_BE(n,b,i)                               \  {                                                       \      (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \      (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \ @@ -106,25 +107,25 @@ static void sha2_starts( sha2_context *ctx, int is224 )  static void sha2_process( sha2_context *ctx, const unsigned char data[64] )  { -    unsigned long temp1, temp2, W[64]; -    unsigned long A, B, C, D, E, F, G, H; - -    GET_ULONG_BE( W[ 0], data,  0 ); -    GET_ULONG_BE( W[ 1], data,  4 ); -    GET_ULONG_BE( W[ 2], data,  8 ); -    GET_ULONG_BE( W[ 3], data, 12 ); -    GET_ULONG_BE( W[ 4], data, 16 ); -    GET_ULONG_BE( W[ 5], data, 20 ); -    GET_ULONG_BE( W[ 6], data, 24 ); -    GET_ULONG_BE( W[ 7], data, 28 ); -    GET_ULONG_BE( W[ 8], data, 32 ); -    GET_ULONG_BE( W[ 9], data, 36 ); -    GET_ULONG_BE( W[10], data, 40 ); -    GET_ULONG_BE( W[11], data, 44 ); -    GET_ULONG_BE( W[12], data, 48 ); -    GET_ULONG_BE( W[13], data, 52 ); -    GET_ULONG_BE( W[14], data, 56 ); -    GET_ULONG_BE( W[15], data, 60 ); +    uint32_t temp1, temp2, W[64]; +    uint32_t A, B, C, D, E, F, G, H; + +    GET_U32_BE( W[ 0], data,  0 ); +    GET_U32_BE( W[ 1], data,  4 ); +    GET_U32_BE( W[ 2], data,  8 ); +    GET_U32_BE( W[ 3], data, 12 ); +    GET_U32_BE( W[ 4], data, 16 ); +    GET_U32_BE( W[ 5], data, 20 ); +    GET_U32_BE( W[ 6], data, 24 ); +    GET_U32_BE( W[ 7], data, 28 ); +    GET_U32_BE( W[ 8], data, 32 ); +    GET_U32_BE( W[ 9], data, 36 ); +    GET_U32_BE( W[10], data, 40 ); +    GET_U32_BE( W[11], data, 44 ); +    GET_U32_BE( W[12], data, 48 ); +    GET_U32_BE( W[13], data, 52 ); +    GET_U32_BE( W[14], data, 56 ); +    GET_U32_BE( W[15], data, 60 );  #define  SHR(x,n) ((x & 0xFFFFFFFF) >> n)  #define ROTR(x,n) (SHR(x,n) | (x << (32 - n))) @@ -241,7 +242,7 @@ static void sha2_process( sha2_context *ctx, const unsigned char data[64] )  static void sha2_update( sha2_context *ctx, const unsigned char *input, size_t ilen )  {      size_t fill; -    unsigned long left; +    uint32_t left;      if( ilen <= 0 )          return; @@ -249,10 +250,10 @@ static void sha2_update( sha2_context *ctx, const unsigned char *input, size_t i      left = ctx->total[0] & 0x3F;      fill = 64 - left; -    ctx->total[0] += (unsigned long) ilen; +    ctx->total[0] += (uint32_t) ilen;      ctx->total[0] &= 0xFFFFFFFF; -    if( ctx->total[0] < (unsigned long) ilen ) +    if( ctx->total[0] < (uint32_t) ilen )          ctx->total[1]++;      if( left && ilen >= fill ) @@ -292,16 +293,16 @@ static const unsigned char sha2_padding[64] =   */  static void sha2_finish( sha2_context *ctx, unsigned char output[32] )  { -    unsigned long last, padn; -    unsigned long high, low; +    uint32_t last, padn; +    uint32_t high, low;      unsigned char msglen[8];      high = ( ctx->total[0] >> 29 )           | ( ctx->total[1] <<  3 );      low  = ( ctx->total[0] <<  3 ); -    PUT_ULONG_BE( high, msglen, 0 ); -    PUT_ULONG_BE( low,  msglen, 4 ); +    PUT_U32_BE( high, msglen, 0 ); +    PUT_U32_BE( low,  msglen, 4 );      last = ctx->total[0] & 0x3F;      padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); @@ -309,16 +310,16 @@ static void sha2_finish( sha2_context *ctx, unsigned char output[32] )      sha2_update( ctx, (unsigned char *) sha2_padding, padn );      sha2_update( ctx, msglen, 8 ); -    PUT_ULONG_BE( ctx->state[0], output,  0 ); -    PUT_ULONG_BE( ctx->state[1], output,  4 ); -    PUT_ULONG_BE( ctx->state[2], output,  8 ); -    PUT_ULONG_BE( ctx->state[3], output, 12 ); -    PUT_ULONG_BE( ctx->state[4], output, 16 ); -    PUT_ULONG_BE( ctx->state[5], output, 20 ); -    PUT_ULONG_BE( ctx->state[6], output, 24 ); +    PUT_U32_BE( ctx->state[0], output,  0 ); +    PUT_U32_BE( ctx->state[1], output,  4 ); +    PUT_U32_BE( ctx->state[2], output,  8 ); +    PUT_U32_BE( ctx->state[3], output, 12 ); +    PUT_U32_BE( ctx->state[4], output, 16 ); +    PUT_U32_BE( ctx->state[5], output, 20 ); +    PUT_U32_BE( ctx->state[6], output, 24 );      if( ctx->is224 == 0 ) -        PUT_ULONG_BE( ctx->state[7], output, 28 ); +        PUT_U32_BE( ctx->state[7], output, 28 );  }  /* diff --git a/lib/libalpm/signing.c b/lib/libalpm/signing.c index fc8dd5bb..018b1cca 100644 --- a/lib/libalpm/signing.c +++ b/lib/libalpm/signing.c @@ -17,8 +17,6 @@   *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include "config.h" -  #include <stdlib.h>  #include <stdio.h>  #include <string.h> @@ -292,11 +290,34 @@ static int key_search(alpm_handle_t *handle, const char *fpr,  	pgpkey->email = key->uids->email;  	pgpkey->created = key->subkeys->timestamp;  	pgpkey->expires = key->subkeys->expires; -	gpgme_release(ctx); -	return 1; +	pgpkey->length = key->subkeys->length; +	pgpkey->revoked = key->subkeys->revoked; + +	switch (key->subkeys->pubkey_algo) { +		case GPGME_PK_RSA: +		case GPGME_PK_RSA_E: +		case GPGME_PK_RSA_S: +			pgpkey->pubkey_algo = 'R'; +			break; + +		case GPGME_PK_DSA: +			pgpkey->pubkey_algo = 'D'; +			break; + +		case GPGME_PK_ELG_E: +		case GPGME_PK_ELG: +		case GPGME_PK_ECDSA: +		case GPGME_PK_ECDH: +			pgpkey->pubkey_algo = 'E'; +			break; +	} + +	ret = 1;  error: -	_alpm_log(handle, ALPM_LOG_DEBUG, "gpg error: %s\n", gpgme_strerror(err)); +	if(ret != 1) { +		_alpm_log(handle, ALPM_LOG_DEBUG, "gpg error: %s\n", gpgme_strerror(err)); +	}  	free(full_fpr);  	gpgme_release(ctx);  	return ret; @@ -418,8 +439,13 @@ int _alpm_gpgme_checksig(alpm_handle_t *handle, const char *path,  	if(!base64_sig) {  		sigpath = _alpm_sigpath(handle, path); -		/* this will just help debugging */ -		_alpm_access(handle, NULL, sigpath, R_OK); +		if(_alpm_access(handle, NULL, sigpath, R_OK) != 0 +				|| (sigfile = fopen(sigpath, "rb")) == NULL) { +			_alpm_log(handle, ALPM_LOG_DEBUG, "sig path %s could not be opened\n", +					sigpath); +			handle->pm_errno = ALPM_ERR_SIG_MISSING; +			goto error; +		}  	}  	/* does the file we are verifying exist? */ @@ -429,17 +455,6 @@ int _alpm_gpgme_checksig(alpm_handle_t *handle, const char *path,  		goto error;  	} -	/* does the sig file exist (if we didn't get the data directly)? */ -	if(!base64_sig) { -		sigfile = fopen(sigpath, "rb"); -		if(sigfile == NULL) { -			_alpm_log(handle, ALPM_LOG_DEBUG, "sig path %s could not be opened\n", -					sigpath); -			handle->pm_errno = ALPM_ERR_SIG_MISSING; -			goto error; -		} -	} -  	if(init_gpgme(handle)) {  		/* pm_errno was set in gpgme_init() */  		goto error; diff --git a/lib/libalpm/signing.h b/lib/libalpm/signing.h index 315d6059..19ffef27 100644 --- a/lib/libalpm/signing.h +++ b/lib/libalpm/signing.h @@ -1,7 +1,7 @@  /*   *  signing.h   * - *  Copyright (c) 2008-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2008-2012 Pacman Development Team <pacman-dev@archlinux.org>   *   *  This program is free software; you can redistribute it and/or modify   *  it under the terms of the GNU General Public License as published by diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c index e660d8e7..b43a61b7 100644 --- a/lib/libalpm/sync.c +++ b/lib/libalpm/sync.c @@ -1,7 +1,7 @@  /*   *  sync.c   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>   *  Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>   *  Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu> @@ -21,8 +21,6 @@   *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include "config.h" -  #include <sys/types.h> /* off_t */  #include <stdlib.h>  #include <stdio.h> @@ -250,7 +248,7 @@ alpm_list_t SYMEXPORT *alpm_find_group_pkgs(alpm_list_t *dbs,  	for(i = dbs; i; i = i->next) {  		alpm_db_t *db = i->data; -		alpm_group_t *grp = alpm_db_readgroup(db, name); +		alpm_group_t *grp = alpm_db_get_group(db, name);  		if(!grp)  			continue; @@ -320,13 +318,13 @@ static int compute_download_size(alpm_pkg_t *newpkg)  		/* tell the caller that we have a partial */  		ret = 1; -	} else if(handle->usedelta) { +	} else if(handle->deltaratio > 0.0) {  		off_t dltsize;  		dltsize = _alpm_shortest_delta_path(handle, newpkg->deltas,  				newpkg->filename, &newpkg->delta_path); -		if(newpkg->delta_path && (dltsize < newpkg->size * MAX_DELTA_RATIO)) { +		if(newpkg->delta_path && (dltsize < newpkg->size * handle->deltaratio)) {  			_alpm_log(handle, ALPM_LOG_DEBUG, "using delta size\n");  			size = dltsize;  		} else { @@ -423,7 +421,7 @@ int _alpm_sync_prepare(alpm_handle_t *handle, alpm_list_t **data)  		   see if they'd like to ignore them rather than failing the sync */  		if(unresolvable != NULL) {  			int remove_unresolvable = 0; -			enum _alpm_errno_t saved_err = handle->pm_errno; +			alpm_errno_t saved_err = handle->pm_errno;  			QUESTION(handle, ALPM_QUESTION_REMOVE_PKGS, unresolvable,  					NULL, NULL, &remove_unresolvable);  			if(remove_unresolvable) { @@ -695,11 +693,11 @@ static int apply_deltas(alpm_handle_t *handle)  			} else {  				/* len = cachedir len + from len + '/' + null */  				len = strlen(cachedir) + strlen(d->from) + 2; -				CALLOC(from, len, sizeof(char), RET_ERR(handle, ALPM_ERR_MEMORY, 1)); +				MALLOC(from, len, RET_ERR(handle, ALPM_ERR_MEMORY, 1));  				snprintf(from, len, "%s/%s", cachedir, d->from);  			}  			len = strlen(cachedir) + strlen(d->to) + 2; -			CALLOC(to, len, sizeof(char), RET_ERR(handle, ALPM_ERR_MEMORY, 1)); +			MALLOC(to, len, RET_ERR(handle, ALPM_ERR_MEMORY, 1));  			snprintf(to, len, "%s/%s", cachedir, d->to);  			/* build the patch command */ @@ -757,7 +755,7 @@ static int apply_deltas(alpm_handle_t *handle)   * @return 1 if file was removed, 0 otherwise   */  static int prompt_to_delete(alpm_handle_t *handle, const char *filepath, -		enum _alpm_errno_t reason) +		alpm_errno_t reason)  {  	int doremove = 0;  	QUESTION(handle, ALPM_QUESTION_CORRUPTED_PKG, (char *)filepath, @@ -782,7 +780,7 @@ static int validate_deltas(alpm_handle_t *handle, alpm_list_t *deltas)  		alpm_delta_t *d = i->data;  		char *filepath = _alpm_filecache_find(handle, d->delta); -		if(_alpm_test_checksum(filepath, d->delta_md5, ALPM_CSUM_MD5)) { +		if(_alpm_test_checksum(filepath, d->delta_md5, ALPM_PKG_VALIDATION_MD5SUM)) {  			errors = alpm_list_add(errors, filepath);  		} else {  			FREE(filepath); @@ -803,11 +801,96 @@ static int validate_deltas(alpm_handle_t *handle, alpm_list_t *deltas)  	return 0;  } +static struct dload_payload *build_payload(alpm_handle_t *handle, +		const char *filename, size_t size, alpm_list_t *servers) +{ +		struct dload_payload *payload; + +		CALLOC(payload, 1, sizeof(*payload), RET_ERR(handle, ALPM_ERR_MEMORY, NULL)); +		STRDUP(payload->remote_name, filename, RET_ERR(handle, ALPM_ERR_MEMORY, NULL)); +		payload->max_size = size; +		payload->servers = servers; +		return payload; +} + +static int find_dl_candidates(alpm_db_t *repo, alpm_list_t **files, alpm_list_t **deltas) +{ +	alpm_list_t *i; +	alpm_handle_t *handle = repo->handle; + +	for(i = handle->trans->add; i; i = i->next) { +		alpm_pkg_t *spkg = i->data; + +		if(spkg->origin != PKG_FROM_FILE && repo == spkg->origin_data.db) { +			alpm_list_t *delta_path = spkg->delta_path; + +			if(!repo->servers) { +				handle->pm_errno = ALPM_ERR_SERVER_NONE; +				_alpm_log(handle, ALPM_LOG_ERROR, "%s: %s\n", +						alpm_strerror(handle->pm_errno), repo->treename); +				return 1; +			} + +			if(delta_path) { +				/* using deltas */ +				alpm_list_t *dlts; +				for(dlts = delta_path; dlts; dlts = dlts->next) { +					alpm_delta_t *delta = dlts->data; +					if(delta->download_size != 0) { +						struct dload_payload *payload = build_payload( +								handle, delta->delta, delta->delta_size, repo->servers); +						ASSERT(payload, return -1); +						*files = alpm_list_add(*files, payload); +					} +					/* keep a list of all the delta files for md5sums */ +					*deltas = alpm_list_add(*deltas, delta); +				} + +			} else if(spkg->download_size != 0) { +				struct dload_payload *payload; +				ASSERT(spkg->filename != NULL, RET_ERR(handle, ALPM_ERR_PKG_INVALID_NAME, -1)); +				payload = build_payload(handle, spkg->filename, spkg->size, repo->servers); +				ASSERT(payload, return -1); +				*files = alpm_list_add(*files, payload); +			} +		} +	} + +	return 0; +} + +static int download_single_file(alpm_handle_t *handle, struct dload_payload *payload, +		const char *cachedir) +{ +	const alpm_list_t *server; + +	payload->handle = handle; +	payload->allow_resume = 1; + +	for(server = payload->servers; server; server = server->next) { +		const char *server_url = server->data; +		size_t len; + +		/* print server + filename into a buffer */ +		len = strlen(server_url) + strlen(payload->remote_name) + 2; +		MALLOC(payload->fileurl, len, RET_ERR(handle, ALPM_ERR_MEMORY, -1)); +		snprintf(payload->fileurl, len, "%s/%s", server_url, payload->remote_name); + +		if(_alpm_download(payload, cachedir, NULL) != -1) { +			return 0; +		} + +		FREE(payload->fileurl); +		payload->unlink_on_fail = 0; +	} + +	return -1; +} +  static int download_files(alpm_handle_t *handle, alpm_list_t **deltas)  {  	const char *cachedir; -	alpm_list_t *i, *j; -	alpm_list_t *files = NULL; +	alpm_list_t *i, *files = NULL;  	int errors = 0;  	cachedir = _alpm_filecache_setup(handle); @@ -826,93 +909,53 @@ static int download_files(alpm_handle_t *handle, alpm_list_t **deltas)  		handle->totaldlcb(total_size);  	} -	/* group sync records by repository and download */  	for(i = handle->dbs_sync; i; i = i->next) { -		alpm_db_t *current = i->data; - -		for(j = handle->trans->add; j; j = j->next) { -			alpm_pkg_t *spkg = j->data; - -			if(spkg->origin != PKG_FROM_FILE && current == spkg->origin_data.db) { -				alpm_list_t *delta_path = spkg->delta_path; -				if(delta_path) { -					/* using deltas */ -					alpm_list_t *dlts; -					for(dlts = delta_path; dlts; dlts = dlts->next) { -						alpm_delta_t *delta = dlts->data; -						if(delta->download_size != 0) { -							struct dload_payload *dpayload; - -							CALLOC(dpayload, 1, sizeof(*dpayload), RET_ERR(handle, ALPM_ERR_MEMORY, -1)); -							STRDUP(dpayload->remote_name, delta->delta, RET_ERR(handle, ALPM_ERR_MEMORY, -1)); -							dpayload->max_size = delta->delta_size; - -							files = alpm_list_add(files, dpayload); -						} -						/* keep a list of all the delta files for md5sums */ -						*deltas = alpm_list_add(*deltas, delta); -					} +		errors += find_dl_candidates(i->data, &files, deltas); +	} -				} else if(spkg->download_size != 0) { -					struct dload_payload *payload; +	if(files) { +		/* check for necessary disk space for download */ +		if(handle->checkspace) { +			off_t *file_sizes; +			size_t idx, num_files; +			int ret; -					ASSERT(spkg->filename != NULL, RET_ERR(handle, ALPM_ERR_PKG_INVALID_NAME, -1)); -					CALLOC(payload, 1, sizeof(*payload), RET_ERR(handle, ALPM_ERR_MEMORY, -1)); -					STRDUP(payload->remote_name, spkg->filename, RET_ERR(handle, ALPM_ERR_MEMORY, -1)); -					payload->max_size = spkg->size; +			_alpm_log(handle, ALPM_LOG_DEBUG, "checking available disk space for download\n"); -					files = alpm_list_add(files, payload); -				} +			num_files = alpm_list_count(files); +			CALLOC(file_sizes, num_files, sizeof(off_t), goto finish); +			for(i = files, idx = 0; i; i = i->next, idx++) { +				const struct dload_payload *payload = i->data; +				file_sizes[idx] = payload->max_size;  			} -		} -		if(files) { -			if(!current->servers) { -				handle->pm_errno = ALPM_ERR_SERVER_NONE; -				_alpm_log(handle, ALPM_LOG_ERROR, "%s: %s\n", -						alpm_strerror(handle->pm_errno), current->treename); +			ret = _alpm_check_downloadspace(handle, cachedir, num_files, file_sizes); +			free(file_sizes); + +			if(ret != 0) {  				errors++; -				continue; +				goto finish;  			} +		} -			EVENT(handle, ALPM_EVENT_RETRIEVE_START, current->treename, NULL); -			for(j = files; j; j = j->next) { -				struct dload_payload *payload = j->data; -				alpm_list_t *server; -				int ret = -1; -				for(server = current->servers; server; server = server->next) { -					const char *server_url = server->data; -					size_t len; - -					/* print server + filename into a buffer */ -					len = strlen(server_url) + strlen(payload->remote_name) + 2; -					MALLOC(payload->fileurl, len, RET_ERR(handle, ALPM_ERR_MEMORY, -1)); -					snprintf(payload->fileurl, len, "%s/%s", server_url, payload->remote_name); -					payload->handle = handle; -					payload->allow_resume = 1; - -					ret = _alpm_download(payload, cachedir, NULL); -					if(ret != -1) { -						break; -					} -					FREE(payload->fileurl); -					payload->unlink_on_fail = 0; -				} -				if(ret == -1) { -					errors++; -					_alpm_log(handle, ALPM_LOG_WARNING, _("failed to retrieve some files from %s\n"), -							current->treename); -				} +		EVENT(handle, ALPM_EVENT_RETRIEVE_START, NULL, NULL); +		for(i = files; i; i = i->next) { +			if(download_single_file(handle, i->data, cachedir) == -1) { +				errors++; +				_alpm_log(handle, ALPM_LOG_WARNING, _("failed to retrieve some files\n"));  			} - -			alpm_list_free_inner(files, (alpm_list_fn_free)_alpm_dload_payload_reset); -			FREELIST(files);  		}  	} -	for(j = handle->trans->add; j; j = j->next) { -		alpm_pkg_t *pkg = j->data; +finish: +	if(files) { +		alpm_list_free_inner(files, (alpm_list_fn_free)_alpm_dload_payload_reset); +		FREELIST(files); +	} + +	for(i = handle->trans->add; i; i = i->next) { +		alpm_pkg_t *pkg = i->data;  		pkg->infolevel &= ~INFRQ_DSIZE;  		pkg->download_size = 0;  	} @@ -933,7 +976,8 @@ static int check_validity(alpm_handle_t *handle,  		char *path;  		alpm_siglist_t *siglist;  		alpm_siglevel_t level; -		enum _alpm_errno_t error; +		alpm_pkgvalidation_t validation; +		alpm_errno_t error;  	};  	size_t current = 0, current_bytes = 0;  	alpm_list_t *i, *errors = NULL; @@ -942,7 +986,7 @@ static int check_validity(alpm_handle_t *handle,  	EVENT(handle, ALPM_EVENT_INTEGRITY_START, NULL, NULL);  	for(i = handle->trans->add; i; i = i->next, current++) { -		struct validity v = { i->data, NULL, NULL, 0, 0 }; +		struct validity v = { i->data, NULL, NULL, 0, 0, 0 };  		int percent = (int)(((double)current_bytes / total_bytes) * 100);  		PROGRESS(handle, ALPM_PROGRESS_INTEGRITY_START, "", percent, @@ -956,7 +1000,7 @@ static int check_validity(alpm_handle_t *handle,  		v.level = alpm_db_get_siglevel(alpm_pkg_get_db(v.pkg));  		if(_alpm_pkg_validate_internal(handle, v.path, v.pkg, -					v.level, &v.siglist) == -1) { +					v.level, &v.siglist, &v.validation) == -1) {  			v.error = handle->pm_errno;  			struct validity *invalid = malloc(sizeof(struct validity));  			memcpy(invalid, &v, sizeof(struct validity)); @@ -965,6 +1009,7 @@ static int check_validity(alpm_handle_t *handle,  			alpm_siglist_cleanup(v.siglist);  			free(v.siglist);  			free(v.path); +			v.pkg->validation = v.validation;  		}  	} @@ -1044,6 +1089,8 @@ static int load_packages(alpm_handle_t *handle, alpm_list_t **data,  		free(filepath);  		/* copy over the install reason */  		pkgfile->reason = spkg->reason; +		/* copy over validation method */ +		pkgfile->validation = spkg->validation;  		i->data = pkgfile;  		/* spkg has been removed from the target list, so we can free the  		 * sync-specific fields */ @@ -1119,7 +1166,7 @@ int _alpm_sync_commit(alpm_handle_t *handle, alpm_list_t **data)  	trans->state = STATE_COMMITING;  	/* fileconflict check */ -	if(!(trans->flags & ALPM_TRANS_FLAG_FORCE)) { +	if(!(trans->flags & (ALPM_TRANS_FLAG_FORCE|ALPM_TRANS_FLAG_DBONLY))) {  		EVENT(handle, ALPM_EVENT_FILECONFLICTS_START, NULL, NULL);  		_alpm_log(handle, ALPM_LOG_DEBUG, "looking for file conflicts\n"); @@ -1144,7 +1191,7 @@ int _alpm_sync_commit(alpm_handle_t *handle, alpm_list_t **data)  		_alpm_log(handle, ALPM_LOG_DEBUG, "checking available disk space\n");  		if(_alpm_check_diskspace(handle) == -1) { -			_alpm_log(handle, ALPM_LOG_ERROR, "%s\n", _("not enough free disk space")); +			_alpm_log(handle, ALPM_LOG_ERROR, _("not enough free disk space\n"));  			return -1;  		} diff --git a/lib/libalpm/sync.h b/lib/libalpm/sync.h index 472d1dfc..496f5258 100644 --- a/lib/libalpm/sync.h +++ b/lib/libalpm/sync.h @@ -1,7 +1,7 @@  /*   *  sync.h   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>   *  Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>   *  Copyright (c) 2005, 2006 by Miklos Vajna <vmiklos@frugalware.org> diff --git a/lib/libalpm/trans.c b/lib/libalpm/trans.c index cb97a4aa..fe89e407 100644 --- a/lib/libalpm/trans.c +++ b/lib/libalpm/trans.c @@ -1,7 +1,7 @@  /*   *  trans.c   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>   *  Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>   *  Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu> @@ -21,8 +21,6 @@   *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include "config.h" -  #include <stdlib.h>  #include <stdio.h>  #include <string.h> @@ -279,7 +277,7 @@ int _alpm_runscriptlet(alpm_handle_t *handle, const char *filepath,  		const char *script, const char *ver, const char *oldver, int is_archive)  {  	char cmdline[PATH_MAX]; -	char *argv[] = { "sh", "-c", cmdline, NULL }; +	char *argv[] = { SCRIPTLET_SHELL, "-c", cmdline, NULL };  	char *tmpdir, *scriptfn = NULL, *scriptpath;  	int retval = 0;  	size_t len; diff --git a/lib/libalpm/trans.h b/lib/libalpm/trans.h index ff944b09..acde9219 100644 --- a/lib/libalpm/trans.h +++ b/lib/libalpm/trans.h @@ -1,7 +1,7 @@  /*   *  trans.h   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>   *  Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>   *  Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu> diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c index 0e5e8a00..22e9e359 100644 --- a/lib/libalpm/util.c +++ b/lib/libalpm/util.c @@ -22,24 +22,17 @@   *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include "config.h" - -#include <stdio.h>  #include <stdlib.h> -#include <stdarg.h> -#include <string.h>  #include <unistd.h>  #include <ctype.h>  #include <dirent.h> -#include <fcntl.h>  #include <time.h>  #include <syslog.h>  #include <errno.h>  #include <limits.h> -#include <sys/types.h> -#include <sys/stat.h>  #include <sys/wait.h>  #include <locale.h> /* setlocale */ +#include <fnmatch.h>  /* libarchive */  #include <archive.h> @@ -62,8 +55,16 @@  #include "trans.h"  #ifndef HAVE_STRSEP -/* This is a replacement for strsep which is not portable (missing on Solaris). - * Copyright (c) 2001 by François Gouget <fgouget_at_codeweavers.com> */ +/** Extracts tokens from a string. + * Replaces strset which is not portable (missing on Solaris). + * Copyright (c) 2001 by François Gouget <fgouget_at_codeweavers.com> + * Modifies str to point to the first character after the token if one is + * found, or NULL if one is not. + * @param str string containing delimited tokens to parse + * @param delim character delimiting tokens in str + * @return pointer to the first token in str if str is not NULL, NULL if + * str is NULL + */  char* strsep(char** str, const char* delims)  {  	char* token; @@ -93,128 +94,106 @@ int _alpm_makepath(const char *path)  	return _alpm_makepath_mode(path, 0755);  } -/* does the same thing as 'mkdir -p' */ +/** Creates a directory, including parents if needed, similar to 'mkdir -p'. + * @param path directory path to create + * @param mode permission mode for created directories + * @return 0 on success, 1 on error + */  int _alpm_makepath_mode(const char *path, mode_t mode)  { -	/* A bit of pointer hell here. Descriptions: -	 * orig - a copy of path so we can safely butcher it with strsep -	 * str - the current position in the path string (after the delimiter) -	 * ptr - the original position of str after calling strsep -	 * incr - incrementally generated path for use in stat/mkdir call -	 */ -	char *orig, *str, *ptr, *incr; -	mode_t oldmask = umask(0000); +	char *ptr, *str; +	mode_t oldmask;  	int ret = 0; -	orig = strdup(path); -	incr = calloc(strlen(orig) + 1, sizeof(char)); -	str = orig; -	while((ptr = strsep(&str, "/"))) { -		if(strlen(ptr)) { -			/* we have another path component- append the newest component to -			 * existing string and create one more level of dir structure */ -			strcat(incr, "/"); -			strcat(incr, ptr); -			if(access(incr, F_OK)) { -				if(mkdir(incr, mode)) { -					ret = 1; -					break; -				} -			} -		} -	} -	free(orig); -	free(incr); -	umask(oldmask); -	return ret; -} +	STRDUP(str, path, return 1); -int _alpm_copyfile(const char *src, const char *dest) -{ -	FILE *in, *out; -	size_t len; -	char *buf; -	int ret = 0; +	oldmask = umask(0000); -	in = fopen(src, "rb"); -	if(in == NULL) { -		return 1; -	} -	out = fopen(dest, "wb"); -	if(out == NULL) { -		fclose(in); -		return 1; -	} +	for(ptr = str; *ptr; ptr++) { +		/* detect mid-path condition and zero length paths */ +		if(*ptr != '/' || ptr == str || ptr[-1] == '/') { +			continue; +		} -	MALLOC(buf, (size_t)ALPM_BUFFER_SIZE, ret = 1; goto cleanup); +		/* temporarily mask the end of the path */ +		*ptr = '\0'; -	/* do the actual file copy */ -	while((len = fread(buf, 1, ALPM_BUFFER_SIZE, in))) { -		size_t nwritten = 0; -		nwritten = fwrite(buf, 1, len, out); -		if((nwritten != len) || ferror(out)) { -			ret = -1; -			goto cleanup; +		if(mkdir(str, mode) < 0 && errno != EEXIST) { +			ret = 1; +			goto done;  		} + +		/* restore path separator */ +		*ptr = '/';  	} -	/* chmod dest to permissions of src, as long as it is not a symlink */ -	struct stat statbuf; -	if(!stat(src, &statbuf)) { -		if(! S_ISLNK(statbuf.st_mode)) { -			fchmod(fileno(out), statbuf.st_mode); -		} -	} else { -		/* stat was unsuccessful */ +	/* end of the string. add the full path. It will already exist when the path +	 * passed in has a trailing slash. */ +	if(mkdir(str, mode) < 0 && errno != EEXIST) {  		ret = 1;  	} -cleanup: -	fclose(in); -	fclose(out); -	free(buf); +done: +	umask(oldmask); +	free(str);  	return ret;  } -/* Trim whitespace and newlines from a string -*/ -char *_alpm_strtrim(char *str) +/** Copies a file. + * @param src file path to copy from + * @param dest file path to copy to + * @return 0 on success, 1 on error  + */ +int _alpm_copyfile(const char *src, const char *dest)  { -	char *pch = str; +	char *buf; +	int in, out, ret = 1; +	ssize_t nread; +	struct stat st; -	if(*str == '\0') { -		/* string is empty, so we're done. */ -		return str; +	MALLOC(buf, (size_t)ALPM_BUFFER_SIZE, return 1); + +	OPEN(in, src, O_RDONLY); +	do { +		out = open(dest, O_WRONLY | O_CREAT, 0000); +	} while(out == -1 && errno == EINTR); +	if(in < 0 || out < 0) { +		goto cleanup;  	} -	while(isspace((unsigned char)*pch)) { -		pch++; +	if(fstat(in, &st) || fchmod(out, st.st_mode)) { +		goto cleanup;  	} -	if(pch != str) { -		size_t len = strlen(pch); -		if(len) { -			memmove(str, pch, len + 1); -		} else { -			*str = '\0'; + +	/* do the actual file copy */ +	while((nread = read(in, buf, ALPM_BUFFER_SIZE)) > 0 || errno == EINTR) { +		ssize_t nwrite = 0; +		if(nread < 0) { +			continue;  		} +		do { +			nwrite = write(out, buf + nwrite, nread); +			if(nwrite >= 0) { +				nread -= nwrite; +			} else if(errno != EINTR) { +				goto cleanup; +			} +		} while(nread > 0);  	} +	ret = 0; -	/* check if there wasn't anything but whitespace in the string. */ -	if(*str == '\0') { -		return str; +cleanup: +	free(buf); +	if(in >= 0) { +		CLOSE(in);  	} - -	pch = (str + (strlen(str) - 1)); -	while(isspace((unsigned char)*pch)) { -		pch--; +	if(out >= 0) { +		CLOSE(out);  	} -	*++pch = '\0'; - -	return str; +	return ret;  } -/** - * Trim trailing newline from a string (if one exists). +/** Trim trailing newlines from a string (if any exist).   * @param str a single line of text   * @return the length of the trimmed string   */ @@ -235,9 +214,70 @@ size_t _alpm_strip_newline(char *str)  /* Compression functions */ -/** - * @brief Unpack a specific file in an archive. - * +/** Open an archive for reading and perform the necessary boilerplate. + * This takes care of creating the libarchive 'archive' struct, setting up + * compression and format options, opening a file descriptor, setting up the + * buffer size, and performing a stat on the path once opened. + * On error, no file descriptor is opened, and the archive pointer returned + * will be set to NULL. + * @param handle the context handle + * @param path the path of the archive to open + * @param buf space for a stat buffer for the given path + * @param archive pointer to place the created archive object + * @param error error code to set on failure to open archive + * @return -1 on failure, >=0 file descriptor on success + */ +int _alpm_open_archive(alpm_handle_t *handle, const char *path, +		struct stat *buf, struct archive **archive, alpm_errno_t error) +{ +	int fd; +	size_t bufsize = ALPM_BUFFER_SIZE; +	errno = 0; + +	if((*archive = archive_read_new()) == NULL) { +		RET_ERR(handle, ALPM_ERR_LIBARCHIVE, -1); +	} + +	archive_read_support_compression_all(*archive); +	archive_read_support_format_all(*archive); + +	_alpm_log(handle, ALPM_LOG_DEBUG, "opening archive %s\n", path); +	OPEN(fd, path, O_RDONLY); +	if(fd < 0) { +		_alpm_log(handle, ALPM_LOG_ERROR, +				_("could not open file %s: %s\n"), path, strerror(errno)); +		goto error; +	} + +	if(fstat(fd, buf) != 0) { +		_alpm_log(handle, ALPM_LOG_ERROR, +				_("could not stat file %s: %s\n"), path, strerror(errno)); +		goto error; +	} +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE +	if(buf->st_blksize > ALPM_BUFFER_SIZE) { +		bufsize = buf->st_blksize; +	} +#endif + +	if(archive_read_open_fd(*archive, fd, bufsize) != ARCHIVE_OK) { +		_alpm_log(handle, ALPM_LOG_ERROR, _("could not open file %s: %s\n"), +				path, archive_error_string(*archive)); +		goto error; +	} + +	return fd; + +error: +	archive_read_finish(*archive); +	*archive = NULL; +	if(fd >= 0) { +		CLOSE(fd); +	} +	RET_ERR(handle, error, -1); +} + +/** Unpack a specific file in an archive.   * @param handle the context handle   * @param archive the archive to unpack   * @param prefix where to extract the files @@ -258,46 +298,33 @@ int _alpm_unpack_single(alpm_handle_t *handle, const char *archive,  	return ret;  } -/** - * @brief Unpack a list of files in an archive. - * +/** Unpack a list of files in an archive.   * @param handle the context handle - * @param archive the archive to unpack + * @param path 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(alpm_handle_t *handle, const char *archive, const char *prefix, +int _alpm_unpack(alpm_handle_t *handle, const char *path, const char *prefix,  		alpm_list_t *list, int breakfirst)  {  	int ret = 0;  	mode_t oldmask; -	struct archive *_archive; +	struct archive *archive;  	struct archive_entry *entry; -	int cwdfd; - -	if((_archive = archive_read_new()) == NULL) { -		RET_ERR(handle, ALPM_ERR_LIBARCHIVE, 1); -	} - -	archive_read_support_compression_all(_archive); -	archive_read_support_format_all(_archive); +	struct stat buf; +	int fd, cwdfd; -	if(archive_read_open_filename(_archive, archive, -				ALPM_BUFFER_SIZE) != ARCHIVE_OK) { -		_alpm_log(handle, ALPM_LOG_ERROR, _("could not open file %s: %s\n"), archive, -				archive_error_string(_archive)); -		RET_ERR(handle, ALPM_ERR_PKG_OPEN, 1); +	fd = _alpm_open_archive(handle, path, &buf, &archive, ALPM_ERR_PKG_OPEN); +	if(fd < 0) { +		return 1;  	}  	oldmask = umask(0022);  	/* save the cwd so we can restore it later */ -	do { -		cwdfd = open(".", O_RDONLY); -	} while(cwdfd == -1 && errno == EINTR); +	OPEN(cwdfd, ".", O_RDONLY);  	if(cwdfd < 0) {  		_alpm_log(handle, ALPM_LOG_ERROR, _("could not get current working directory\n"));  	} @@ -310,19 +337,12 @@ int _alpm_unpack(alpm_handle_t *handle, const char *archive, const char *prefix,  		goto cleanup;  	} -	while(archive_read_next_header(_archive, &entry) == ARCHIVE_OK) { -		const struct stat *st; -		const char *entryname; /* the name of the file in the archive */ +	while(archive_read_next_header(archive, &entry) == ARCHIVE_OK) { +		const char *entryname; +		mode_t mode; -		st = archive_entry_stat(entry);  		entryname = archive_entry_pathname(entry); -		if(S_ISREG(st->st_mode)) { -			archive_entry_set_perm(entry, 0644); -		} else if(S_ISDIR(st->st_mode)) { -			archive_entry_set_perm(entry, 0755); -		} -  		/* If specific files were requested, skip entries that don't match. */  		if(list) {  			char *entry_prefix = strdup(entryname); @@ -333,7 +353,7 @@ int _alpm_unpack(alpm_handle_t *handle, const char *archive, const char *prefix,  			char *found = alpm_list_find_str(list, entry_prefix);  			free(entry_prefix);  			if(!found) { -				if(archive_read_data_skip(_archive) != ARCHIVE_OK) { +				if(archive_read_data_skip(archive) != ARCHIVE_OK) {  					ret = 1;  					goto cleanup;  				} @@ -343,15 +363,22 @@ int _alpm_unpack(alpm_handle_t *handle, const char *archive, const char *prefix,  			}  		} +		mode = archive_entry_mode(entry); +		if(S_ISREG(mode)) { +			archive_entry_set_perm(entry, 0644); +		} else if(S_ISDIR(mode)) { +			archive_entry_set_perm(entry, 0755); +		} +  		/* Extract the archive entry. */ -		int readret = archive_read_extract(_archive, entry, 0); +		int readret = archive_read_extract(archive, entry, 0);  		if(readret == ARCHIVE_WARN) {  			/* operation succeeded but a non-critical error was encountered */  			_alpm_log(handle, ALPM_LOG_WARNING, _("warning given when extracting %s (%s)\n"), -					entryname, archive_error_string(_archive)); +					entryname, archive_error_string(archive));  		} else if(readret != ARCHIVE_OK) {  			_alpm_log(handle, ALPM_LOG_ERROR, _("could not extract %s (%s)\n"), -					entryname, archive_error_string(_archive)); +					entryname, archive_error_string(archive));  			ret = 1;  			goto cleanup;  		} @@ -363,63 +390,20 @@ int _alpm_unpack(alpm_handle_t *handle, const char *archive, const char *prefix,  cleanup:  	umask(oldmask); -	archive_read_finish(_archive); +	archive_read_finish(archive); +	CLOSE(fd);  	if(cwdfd >= 0) {  		if(fchdir(cwdfd) != 0) {  			_alpm_log(handle, ALPM_LOG_ERROR,  					_("could not restore working directory (%s)\n"), strerror(errno));  		} -		close(cwdfd); +		CLOSE(cwdfd);  	}  	return ret;  } -/* does the same thing as 'rm -rf' */ -int _alpm_rmrf(const char *path) -{ -	int errflag = 0; -	struct dirent *dp; -	DIR *dirp; -	struct stat st; - -	if(_alpm_lstat(path, &st) == 0) { -		if(!S_ISDIR(st.st_mode)) { -			if(!unlink(path)) { -				return 0; -			} else { -				if(errno == ENOENT) { -					return 0; -				} else { -					return 1; -				} -			} -		} else { -			dirp = opendir(path); -			if(!dirp) { -				return 1; -			} -			for(dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { -				if(dp->d_name) { -					if(strcmp(dp->d_name, "..") != 0 && strcmp(dp->d_name, ".") != 0) { -						char name[PATH_MAX]; -						sprintf(name, "%s/%s", path, dp->d_name); -						errflag += _alpm_rmrf(name); -					} -				} -			} -			closedir(dirp); -			if(rmdir(path)) { -				errflag++; -			} -		} -		return errflag; -	} -	return 0; -} - -/** - * Determine if there are files in a directory +/** Determine if there are files in a directory.   * @param handle the context handle   * @param path the full absolute directory path   * @param full_count whether to return an exact count of files @@ -460,6 +444,13 @@ ssize_t _alpm_files_in_directory(alpm_handle_t *handle, const char *path,  	return files;  } +/** Write formatted message to log. + * @param handle the context handle + * @param format formatted string to write out + * @param args formatting arguments + * @return 0 or number of characters written on success, vfprintf return value + * on error + */  int _alpm_logaction(alpm_handle_t *handle, const char *fmt, va_list args)  {  	int ret = 0; @@ -491,16 +482,20 @@ int _alpm_logaction(alpm_handle_t *handle, const char *fmt, va_list args)  	return ret;  } -int _alpm_run_chroot(alpm_handle_t *handle, const char *path, char *const argv[]) +/** Execute a command with arguments in a chroot. + * @param handle the context handle + * @param cmd command to execute + * @param argv arguments to pass to cmd + * @return 0 on success, 1 on error + */ +int _alpm_run_chroot(alpm_handle_t *handle, const char *cmd, char *const argv[])  {  	pid_t pid;  	int pipefd[2], cwdfd;  	int retval = 0;  	/* save the cwd so we can restore it later */ -	do { -		cwdfd = open(".", O_RDONLY); -	} while(cwdfd == -1 && errno == EINTR); +	OPEN(cwdfd, ".", O_RDONLY);  	if(cwdfd < 0) {  		_alpm_log(handle, ALPM_LOG_ERROR, _("could not get current working directory\n"));  	} @@ -513,7 +508,7 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *path, char *const argv[]  	}  	_alpm_log(handle, ALPM_LOG_DEBUG, "executing \"%s\" under chroot \"%s\"\n", -			path, handle->root); +			cmd, handle->root);  	/* Flush open fds before fork() to avoid cloning buffers */  	fflush(NULL); @@ -534,12 +529,12 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *path, char *const argv[]  	if(pid == 0) {  		/* this code runs for the child only (the actual chroot/exec) */ -		close(1); -		close(2); +		CLOSE(1); +		CLOSE(2);  		while(dup2(pipefd[1], 1) == -1 && errno == EINTR);  		while(dup2(pipefd[1], 2) == -1 && errno == EINTR); -		close(pipefd[0]); -		close(pipefd[1]); +		CLOSE(pipefd[0]); +		CLOSE(pipefd[1]);  		/* use fprintf instead of _alpm_log to send output through the parent */  		if(chroot(handle->root) != 0) { @@ -552,7 +547,8 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *path, char *const argv[]  			exit(1);  		}  		umask(0022); -		execv(path, argv); +		execv(cmd, argv); +		/* execv only returns if there was an error */  		fprintf(stderr, _("call to execv failed (%s)\n"), strerror(errno));  		exit(1);  	} else { @@ -560,10 +556,10 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *path, char *const argv[]  		int status;  		FILE *pipe_file; -		close(pipefd[1]); +		CLOSE(pipefd[1]);  		pipe_file = fdopen(pipefd[0], "r");  		if(pipe_file == NULL) { -			close(pipefd[0]); +			CLOSE(pipefd[0]);  			retval = 1;  		} else {  			while(!feof(pipe_file)) { @@ -605,12 +601,16 @@ cleanup:  			_alpm_log(handle, ALPM_LOG_ERROR,  					_("could not restore working directory (%s)\n"), strerror(errno));  		} -		close(cwdfd); +		CLOSE(cwdfd);  	}  	return retval;  } +/** Run ldconfig in a chroot. + * @param handle the context handle + * @return 0 on success, 1 on error + */  int _alpm_ldconfig(alpm_handle_t *handle)  {  	char line[PATH_MAX]; @@ -629,8 +629,13 @@ int _alpm_ldconfig(alpm_handle_t *handle)  	return 0;  } -/* Helper function for comparing strings using the - * alpm "compare func" signature */ +/** Helper function for comparing strings using the alpm "compare func" + * signature. + * @param s1 first string to be compared + * @param s2 second string to be compared + * @return 0 if strings are equal, positive int if first unequal character + * has a greater value in s1, negative if it has a greater value in s2 + */  int _alpm_str_cmp(const void *s1, const void *s2)  {  	return strcmp(s1, s2); @@ -687,7 +692,7 @@ const char *_alpm_filecache_setup(alpm_handle_t *handle)  		} else if(!S_ISDIR(buf.st_mode)) {  			_alpm_log(handle, ALPM_LOG_DEBUG,  					"skipping cachedir, not a directory: %s\n", cachedir); -		} else if(access(cachedir, W_OK) != 0) { +		} else if(_alpm_access(handle, NULL, cachedir, W_OK) != 0) {  			_alpm_log(handle, ALPM_LOG_DEBUG,  					"skipping cachedir, not writable: %s\n", cachedir);  		} else if(!(buf.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH))) { @@ -739,51 +744,64 @@ int _alpm_lstat(const char *path, struct stat *buf)  }  #ifdef HAVE_LIBSSL +/** Compute the MD5 message digest of a file. + * @param path file path of file to compute  MD5 digest of + * @param output string to hold computed MD5 digest + * @return 0 on success, 1 on file open error, 2 on file read error + */  static int md5_file(const char *path, unsigned char output[16])  { -	FILE *f; -	size_t n;  	MD5_CTX ctx;  	unsigned char *buf; +	ssize_t n; +	int fd; -	CALLOC(buf, ALPM_BUFFER_SIZE, sizeof(unsigned char), return 1); +	MALLOC(buf, (size_t)ALPM_BUFFER_SIZE, return 1); -	if((f = fopen(path, "rb")) == NULL) { +	OPEN(fd, path, O_RDONLY); +	if(fd < 0) {  		free(buf);  		return 1;  	}  	MD5_Init(&ctx); -	while((n = fread(buf, 1, ALPM_BUFFER_SIZE, f)) > 0) { +	while((n = read(fd, buf, ALPM_BUFFER_SIZE)) > 0 || errno == EINTR) { +		if(n < 0) { +			continue; +		}  		MD5_Update(&ctx, buf, n);  	} -	MD5_Final(output, &ctx); - -	memset(&ctx, 0, sizeof(MD5_CTX)); +	CLOSE(fd);  	free(buf); -	if(ferror(f) != 0) { -		fclose(f); +	if(n < 0) {  		return 2;  	} -	fclose(f); +	MD5_Final(output, &ctx);  	return 0;  }  /* third param is so we match the PolarSSL definition */ +/** Compute the SHA-224 or SHA-256 message digest of a file. + * @param path file path of file to compute SHA2 digest of + * @param output string to hold computed SHA2 digest + * @param is224 use SHA-224 instead of SHA-256 + * @return 0 on success, 1 on file open error, 2 on file read error + */  static int sha2_file(const char *path, unsigned char output[32], int is224)  { -	FILE *f; -	size_t n;  	SHA256_CTX ctx;  	unsigned char *buf; +	ssize_t n; +	int fd; -	CALLOC(buf, ALPM_BUFFER_SIZE, sizeof(unsigned char), return 1); +	MALLOC(buf, (size_t)ALPM_BUFFER_SIZE, return 1); -	if((f = fopen(path, "rb")) == NULL) { +	OPEN(fd, path, O_RDONLY); +	if(fd < 0) {  		free(buf);  		return 1;  	} @@ -794,7 +812,10 @@ static int sha2_file(const char *path, unsigned char output[32], int is224)  		SHA256_Init(&ctx);  	} -	while((n = fread(buf, 1, ALPM_BUFFER_SIZE, f)) > 0) { +	while((n = read(fd, buf, ALPM_BUFFER_SIZE)) > 0 || errno == EINTR) { +		if(n < 0) { +			continue; +		}  		if(is224) {  			SHA224_Update(&ctx, buf, n);  		} else { @@ -802,24 +823,45 @@ static int sha2_file(const char *path, unsigned char output[32], int is224)  		}  	} +	CLOSE(fd); +	free(buf); + +	if(n < 0) { +		return 2; +	} +  	if(is224) {  		SHA224_Final(output, &ctx);  	} else {  		SHA256_Final(output, &ctx);  	} +	return 0; +} +#endif -	memset(&ctx, 0, sizeof(SHA256_CTX)); -	free(buf); +/** Create a string representing bytes in hexadecimal. + * @param bytes the bytes to represent in hexadecimal + * @param size number of bytes to consider + * @return a NULL terminated string with the hexadecimal representation of + * bytes or NULL on error. This string must be freed. + */ +static char *hex_representation(unsigned char *bytes, size_t size) +{ +	static const char *hex_digits = "0123456789abcdef"; +	char *str; +	size_t i; -	if(ferror(f) != 0) { -		fclose(f); -		return 2; +	MALLOC(str, 2 * size + 1, return NULL); + +	for (i = 0; i < size; i++) { +		str[2 * i] = hex_digits[bytes[i] >> 4]; +		str[2 * i + 1] = hex_digits[bytes[i] & 0x0f];  	} -	fclose(f); -	return 0; +	str[2 * size] = '\0'; + +	return str;  } -#endif  /** Get the md5 sum of file.   * @param filename name of the file @@ -829,28 +871,15 @@ static int sha2_file(const char *path, unsigned char output[32], int is224)  char SYMEXPORT *alpm_compute_md5sum(const char *filename)  {  	unsigned char output[16]; -	char *md5sum; -	int ret, i;  	ASSERT(filename != NULL, return NULL); -	/* allocate 32 chars plus 1 for null */ -	CALLOC(md5sum, 33, sizeof(char), return NULL);  	/* defined above for OpenSSL, otherwise defined in md5.h */ -	ret = md5_file(filename, output); - -	if(ret > 0) { -		free(md5sum); +	if(md5_file(filename, output) > 0) {  		return NULL;  	} -	/* Convert the result to something readable */ -	for (i = 0; i < 16; i++) { -		/* sprintf is acceptable here because we know our output */ -		sprintf(md5sum +(i * 2), "%02x", output[i]); -	} - -	return md5sum; +	return hex_representation(output, 16);  }  /** Get the sha256 sum of file. @@ -861,39 +890,33 @@ char SYMEXPORT *alpm_compute_md5sum(const char *filename)  char SYMEXPORT *alpm_compute_sha256sum(const char *filename)  {  	unsigned char output[32]; -	char *sha256sum; -	int ret, i;  	ASSERT(filename != NULL, return NULL); -	/* allocate 64 chars plus 1 for null */ -	CALLOC(sha256sum, 65, sizeof(char), return NULL);  	/* defined above for OpenSSL, otherwise defined in sha2.h */ -	ret = sha2_file(filename, output, 0); - -	if(ret > 0) { -		free(sha256sum); +	if(sha2_file(filename, output, 0) > 0) {  		return NULL;  	} -	/* Convert the result to something readable */ -	for (i = 0; i < 32; i++) { -		/* sprintf is acceptable here because we know our output */ -		sprintf(sha256sum +(i * 2), "%02x", output[i]); -	} - -	return sha256sum; +	return hex_representation(output, 32);  } +/** Calculates a file's MD5 or SHA2 digest  and compares it to an expected value.  + * @param filepath path of the file to check + * @param expected hash value to compare against + * @param type digest type to use + * @return 0 if file matches the expected hash, 1 if they do not match, -1 on + * error + */  int _alpm_test_checksum(const char *filepath, const char *expected, -		enum _alpm_csum type) +		alpm_pkgvalidation_t type)  {  	char *computed;  	int ret; -	if(type == ALPM_CSUM_MD5) { +	if(type == ALPM_PKG_VALIDATION_MD5SUM) {  		computed = alpm_compute_md5sum(filepath); -	} else if(type == ALPM_CSUM_SHA256) { +	} else if(type == ALPM_PKG_VALIDATION_SHA256SUM) {  		computed = alpm_compute_sha256sum(filepath);  	} else {  		return -1; @@ -912,18 +935,24 @@ int _alpm_test_checksum(const char *filepath, const char *expected,  }  /* Note: does NOT handle sparse files on purpose for speed. */ +/** TODO. + * Does not handle sparse files on purpose for speed. + * @param a + * @param b + * @return  + */  int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b)  { -	char *i = NULL; -	int64_t offset; -	int done = 0; -  	/* ensure we start populating our line buffer at the beginning */  	b->line_offset = b->line;  	while(1) { +		size_t block_remaining; +		char *eol; +  		/* have we processed this entire block? */  		if(b->block + b->block_size == b->block_offset) { +			int64_t offset;  			if(b->ret == ARCHIVE_EOF) {  				/* reached end of archive on the last read, now we are out of data */  				goto cleanup; @@ -933,20 +962,20 @@ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b)  			b->ret = archive_read_data_block(a, (void *)&b->block,  					&b->block_size, &offset);  			b->block_offset = b->block; +			block_remaining = b->block_size;  			/* error, cleanup */  			if(b->ret < ARCHIVE_OK) {  				goto cleanup;  			} +		} else { +			block_remaining = b->block + b->block_size - b->block_offset;  		} -		/* loop through the block looking for EOL characters */ -		for(i = b->block_offset; i < (b->block + b->block_size); i++) { -			/* check if read value was null or newline */ -			if(*i == '\0' || *i == '\n') { -				done = 1; -				break; -			} +		/* look through the block looking for EOL characters */ +		eol = memchr(b->block_offset, '\n', block_remaining); +		if(!eol) { +			eol = memchr(b->block_offset, '\0', block_remaining);  		}  		/* allocate our buffer, or ensure our existing one is big enough */ @@ -956,8 +985,10 @@ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b)  			b->line_size = b->block_size + 1;  			b->line_offset = b->line;  		} else { -			size_t needed = (size_t)((b->line_offset - b->line) -					+ (i - b->block_offset) + 1); +			/* note: we know eol > b->block_offset and b->line_offset > b->line, +			 * so we know the result is unsigned and can fit in size_t */ +			size_t new = eol ? (size_t)(eol - b->block_offset) : block_remaining; +			size_t needed = (size_t)((b->line_offset - b->line) + new + 1);  			if(needed > b->max_line_size) {  				b->ret = -ERANGE;  				goto cleanup; @@ -974,11 +1005,11 @@ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b)  			}  		} -		if(done) { -			size_t len = (size_t)(i - b->block_offset); +		if(eol) { +			size_t len = (size_t)(eol - b->block_offset);  			memcpy(b->line_offset, b->block_offset, len);  			b->line_offset[len] = '\0'; -			b->block_offset = ++i; +			b->block_offset = eol + 1;  			/* this is the main return point; from here you can read b->line */  			return ARCHIVE_OK;  		} else { @@ -986,7 +1017,7 @@ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b)  			size_t len = (size_t)(b->block + b->block_size - b->block_offset);  			memcpy(b->line_offset, b->block_offset, len);  			b->line_offset += len; -			b->block_offset = i; +			b->block_offset = b->block + b->block_size;  			/* there was no new data, return what is left; saved ARCHIVE_EOF will be  			 * returned on next call */  			if(len == 0) { @@ -1005,6 +1036,14 @@ cleanup:  	}  } +/** Parse a full package specifier. + * @param target package specifier to parse, such as: "pacman-4.0.1-2", + * "pacman-4.01-2/", or "pacman-4.0.1-2/desc" + * @param name to hold package name + * @param version to hold package version + * @param name_hash to hold package name hash + * @return 0 on success, -1 on error + */  int _alpm_splitname(const char *target, char **name, char **version,  		unsigned long *name_hash)  { @@ -1057,8 +1096,7 @@ int _alpm_splitname(const char *target, char **name, char **version,  	return 0;  } -/** - * Hash the given string to an unsigned long value. +/** Hash the given string to an unsigned long value.   * This is the standard sdbm hashing algorithm.   * @param str string to hash   * @return the hash value of the given string @@ -1072,12 +1110,17 @@ unsigned long _alpm_hash_sdbm(const char *str)  		return hash;  	}  	while((c = *str++)) { -		hash = c + (hash << 6) + (hash << 16) - hash; +		hash = c + hash * 65599;  	}  	return hash;  } +/** Convert a string to a file offset. + * This parses bare positive integers only. + * @param line string to convert + * @return off_t on success, -1 on error + */  off_t _alpm_strtoofft(const char *line)  {  	char *end; @@ -1089,13 +1132,13 @@ off_t _alpm_strtoofft(const char *line)  		return (off_t)-1;  	}  	result = strtoull(line, &end, 10); -	if (result == 0 && end == line) { +	if(result == 0 && end == line) {  		/* line was not a number */  		return (off_t)-1; -	} else if (result == ULLONG_MAX && errno == ERANGE) { +	} else if(result == ULLONG_MAX && errno == ERANGE) {  		/* line does not fit in unsigned long long */  		return (off_t)-1; -	} else if (*end) { +	} else if(*end) {  		/* line began with a number but has junk left over at the end */  		return (off_t)-1;  	} @@ -1103,8 +1146,16 @@ off_t _alpm_strtoofft(const char *line)  	return (off_t)result;  } -time_t _alpm_parsedate(const char *line) +/** Parses a date into an alpm_time_t struct. + * @param line date to parse + * @return time struct on success, 0 on error + */ +alpm_time_t _alpm_parsedate(const char *line)  { +	char *end; +	long long result; +	errno = 0; +  	if(isalpha((unsigned char)line[0])) {  		/* initialize to null in case of failure */  		struct tm tmp_tm; @@ -1112,13 +1163,27 @@ time_t _alpm_parsedate(const char *line)  		setlocale(LC_TIME, "C");  		strptime(line, "%a %b %e %H:%M:%S %Y", &tmp_tm);  		setlocale(LC_TIME, ""); -		return mktime(&tmp_tm); +		return (alpm_time_t)mktime(&tmp_tm); +	} + +	result = strtoll(line, &end, 10); +	if(result == 0 && end == line) { +		/* line was not a number */ +		errno = EINVAL; +		return 0; +	} else if(errno == ERANGE) { +		/* line does not fit in long long */ +		return 0; +	} else if(*end) { +		/* line began with a number but has junk left over at the end */ +		errno = EINVAL; +		return 0;  	} -	return (time_t)atol(line); + +	return (alpm_time_t)result;  } -/** - * Wrapper around access() which takes a dir and file argument +/** Wrapper around access() which takes a dir and file argument   * separately and generates an appropriate error message.   * If dir is NULL file will be treated as the whole path.   * @param handle an alpm handle @@ -1127,13 +1192,12 @@ time_t _alpm_parsedate(const char *line)   * @param amode access mode as described in access()   * @return int value returned by access()   */ -  int _alpm_access(alpm_handle_t *handle, const char *dir, const char *file, int amode)  {  	size_t len = 0;  	int ret = 0; -	if (dir) { +	if(dir) {  		char *check_path;  		len = strlen(dir) + strlen(file) + 1; @@ -1148,19 +1212,19 @@ int _alpm_access(alpm_handle_t *handle, const char *dir, const char *file, int a  	}  	if(ret != 0) { -		if (amode & R_OK) { +		if(amode & R_OK) {  			_alpm_log(handle, ALPM_LOG_DEBUG, "\"%s%s\" is not readable: %s\n",  					dir, file, strerror(errno));  		} -		if (amode & W_OK) { +		if(amode & W_OK) {  			_alpm_log(handle, ALPM_LOG_DEBUG, "\"%s%s\" is not writable: %s\n",  					dir, file, strerror(errno));  		} -		if (amode & X_OK) { +		if(amode & X_OK) {  			_alpm_log(handle, ALPM_LOG_DEBUG, "\"%s%s\" is not executable: %s\n",  					dir, file, strerror(errno));  		} -		if (amode == F_OK) { +		if(amode == F_OK) {  			_alpm_log(handle, ALPM_LOG_DEBUG, "\"%s%s\" does not exist: %s\n",  					dir, file, strerror(errno));  		} @@ -1168,8 +1232,25 @@ int _alpm_access(alpm_handle_t *handle, const char *dir, const char *file, int a  	return ret;  } +/** Checks whether a string matches a shell wildcard pattern. + * Wrapper around fnmatch. + * @param pattern pattern to match aganist + * @param string string to check against pattern + * @return 0 if string matches pattern, non-zero if they don't match and on + * error + */ +int _alpm_fnmatch(const void *pattern, const void *string) +{ +	return fnmatch(pattern, string, 0); +} +  #ifndef HAVE_STRNDUP  /* A quick and dirty implementation derived from glibc */ +/** Determines the length of a fixed-size string. + * @param s string to be measured + * @param max maximum number of characters to search for the string end + * @return length of s or max, whichever is smaller + */  static size_t strnlen(const char *s, size_t max)  {      register const char *p; @@ -1177,6 +1258,12 @@ static size_t strnlen(const char *s, size_t max)      return (p - s);  } +/** Copies a string. + * Returned string needs to be freed + * @param s string to be copied + * @param n maximum number of characters to copy + * @return pointer to the new string on success, NULL on error + */  char *strndup(const char *s, size_t n)  {    size_t len = strnlen(s, n); diff --git a/lib/libalpm/util.h b/lib/libalpm/util.h index 26fa9044..e6747827 100644 --- a/lib/libalpm/util.h +++ b/lib/libalpm/util.h @@ -1,7 +1,7 @@  /*   *  util.h   * - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *  Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>   *  Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>   *  Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu> @@ -24,8 +24,6 @@  #ifndef _ALPM_UTIL_H  #define _ALPM_UTIL_H -#include "config.h" -  #include "alpm_list.h"  #include "alpm.h"  #include "package.h" /* alpm_pkg_t */ @@ -35,11 +33,13 @@  #include <string.h>  #include <stdarg.h>  #include <stddef.h> /* size_t */ -#include <time.h> +#include <sys/types.h>  #include <sys/stat.h> /* struct stat */ -#include <archive.h> /* struct archive */  #include <math.h> /* fabs */  #include <float.h> /* DBL_EPSILON */ +#include <fcntl.h> /* open, close */ + +#include <archive.h> /* struct archive */  #ifdef ENABLE_NLS  #include <libintl.h> /* here so it doesn't need to be included elsewhere */ @@ -51,8 +51,8 @@  #define ALLOC_FAIL(s) do { fprintf(stderr, "alloc failure: could not allocate %zd bytes\n", s); } while(0) -#define MALLOC(p, s, action) do { p = calloc(1, s); if(p == NULL) { ALLOC_FAIL(s); action; } } while(0) -#define CALLOC(p, l, s, action) do { p = calloc(l, s); if(p == NULL) { ALLOC_FAIL(s); action; } } while(0) +#define MALLOC(p, s, action) do { p = malloc(s); if(p == NULL) { ALLOC_FAIL(s); action; } } while(0) +#define CALLOC(p, l, s, action) do { p = calloc(l, s); if(p == NULL) { ALLOC_FAIL(l * s); action; } } while(0)  /* This strdup macro is NULL safe- copying NULL will yield NULL */  #define STRDUP(r, s, action) do { if(s != NULL) { r = strdup(s); if(r == NULL) { ALLOC_FAIL(strlen(s)); action; } } else { r = NULL; } } while(0)  #define STRNDUP(r, s, l, action) do { if(s != NULL) { r = strndup(s, l); if(r == NULL) { ALLOC_FAIL(strlen(s)); action; } } else { r = NULL; } } while(0) @@ -82,6 +82,13 @@  #define ALPM_BUFFER_SIZE 8192  #endif +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +#define OPEN(fd, path, flags) do { fd = open(path, flags | O_BINARY); } while(fd == -1 && errno == EINTR) +#define CLOSE(fd) do { int ret; do { ret = close(fd); } while(ret == -1 && errno == EINTR); } while(0) +  /**   * Used as a buffer/state holder for _alpm_archive_fgets().   */ @@ -98,39 +105,37 @@ struct archive_read_buffer {  	int ret;  }; -enum _alpm_csum { -	ALPM_CSUM_MD5, -	ALPM_CSUM_SHA256, -}; -  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);  size_t _alpm_strip_newline(char *str); + +int _alpm_open_archive(alpm_handle_t *handle, const char *path, +		struct stat *buf, struct archive **archive, alpm_errno_t error);  int _alpm_unpack_single(alpm_handle_t *handle, const char *archive,  		const char *prefix, const char *filename);  int _alpm_unpack(alpm_handle_t *handle, const char *archive, const char *prefix,  		alpm_list_t *list, int breakfirst); -int _alpm_rmrf(const char *path); +  ssize_t _alpm_files_in_directory(alpm_handle_t *handle, const char *path, int full_count);  int _alpm_logaction(alpm_handle_t *handle, const char *fmt, va_list args); -int _alpm_run_chroot(alpm_handle_t *handle, const char *path, char *const argv[]); +int _alpm_run_chroot(alpm_handle_t *handle, const char *cmd, char *const argv[]);  int _alpm_ldconfig(alpm_handle_t *handle);  int _alpm_str_cmp(const void *s1, const void *s2);  char *_alpm_filecache_find(alpm_handle_t *handle, const char *filename);  const char *_alpm_filecache_setup(alpm_handle_t *handle);  int _alpm_lstat(const char *path, struct stat *buf); -int _alpm_test_checksum(const char *filepath, const char *expected, enum _alpm_csum type); +int _alpm_test_checksum(const char *filepath, const char *expected, alpm_pkgvalidation_t type);  int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b);  int _alpm_splitname(const char *target, char **name, char **version,  		unsigned long *name_hash);  unsigned long _alpm_hash_sdbm(const char *str);  off_t _alpm_strtoofft(const char *line); -time_t _alpm_parsedate(const char *line); +alpm_time_t _alpm_parsedate(const char *line);  int _alpm_raw_cmp(const char *first, const char *second);  int _alpm_raw_ncmp(const char *first, const char *second, size_t max);  int _alpm_access(alpm_handle_t *handle, const char *dir, const char *file, int amode); +int _alpm_fnmatch(const void *pattern, const void *string);  #ifndef HAVE_STRSEP  char *strsep(char **, const char *); diff --git a/lib/libalpm/version.c b/lib/libalpm/version.c index 6b65a413..269a7016 100644 --- a/lib/libalpm/version.c +++ b/lib/libalpm/version.c @@ -1,5 +1,5 @@  /* - *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + *  Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>   *   *  This program is free software; you can redistribute it and/or modify   *  it under the terms of the GNU General Public License as published by @@ -15,8 +15,6 @@   *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include "config.h" -  #include <string.h>  #include <ctype.h> | 
