diff options
Diffstat (limited to 'src/pacman')
| -rw-r--r-- | src/pacman/Makefile.am | 2 | ||||
| -rw-r--r-- | src/pacman/callback.c | 55 | ||||
| -rw-r--r-- | src/pacman/conf.c | 632 | ||||
| -rw-r--r-- | src/pacman/conf.h | 15 | ||||
| -rw-r--r-- | src/pacman/database.c | 11 | ||||
| -rw-r--r-- | src/pacman/deptest.c | 8 | ||||
| -rw-r--r-- | src/pacman/package.c | 77 | ||||
| -rw-r--r-- | src/pacman/package.h | 10 | ||||
| -rw-r--r-- | src/pacman/pacman.c | 651 | ||||
| -rw-r--r-- | src/pacman/pacman.h | 5 | ||||
| -rw-r--r-- | src/pacman/query.c | 84 | ||||
| -rw-r--r-- | src/pacman/remove.c | 16 | ||||
| -rw-r--r-- | src/pacman/sync.c | 135 | ||||
| -rw-r--r-- | src/pacman/upgrade.c | 25 | ||||
| -rw-r--r-- | src/pacman/util.c | 424 | ||||
| -rw-r--r-- | src/pacman/util.h | 2 | 
16 files changed, 1231 insertions, 921 deletions
| diff --git a/src/pacman/Makefile.am b/src/pacman/Makefile.am index 31e8b134..333b8193 100644 --- a/src/pacman/Makefile.am +++ b/src/pacman/Makefile.am @@ -1,6 +1,7 @@  # paths set at make time  conffile  = ${sysconfdir}/pacman.conf  dbpath    = ${localstatedir}/lib/pacman/ +gpgdir    = ${sysconfdir}/pacman.d/gnupg/  cachedir  = ${localstatedir}/cache/pacman/pkg/  logfile   = ${localstatedir}/log/pacman.log @@ -10,6 +11,7 @@ DEFS = -DLOCALEDIR=\"@localedir@\" \         -DCONFFILE=\"$(conffile)\" \         -DROOTDIR=\"$(ROOTDIR)\" \         -DDBPATH=\"$(dbpath)\" \ +       -DGPGDIR=\"$(gpgdir)\" \         -DCACHEDIR=\"$(cachedir)\" \         -DLOGFILE=\"$(logfile)\" \         @DEFS@ diff --git a/src/pacman/callback.c b/src/pacman/callback.c index 5edcc966..d3dc7440 100644 --- a/src/pacman/callback.c +++ b/src/pacman/callback.c @@ -81,7 +81,7 @@ static double get_update_timediff(int first_call)  		}  	} -	return(retval); +	return retval;  }  /* refactored from cb_trans_progress */ @@ -224,10 +224,10 @@ void cb_trans_evt(pmtransevt_t event, void *data1, void *data2)  			printf(_("failed.\n"));  			break;  		case PM_TRANS_EVT_SCRIPTLET_INFO: -			printf("%s", (char*)data1); +			printf("%s", (char *)data1);  			break;  		case PM_TRANS_EVT_RETRIEVE_START: -			printf(_(":: Retrieving packages from %s...\n"), (char*)data1); +			printf(_(":: Retrieving packages from %s...\n"), (char *)data1);  			break;  		case PM_TRANS_EVT_DISKSPACE_START:  			if(config->noprogressbar) { @@ -398,7 +398,7 @@ void cb_trans_progress(pmtransprog_t event, const char *pkgname, int percent,  	}  	infolen = getcols() * 6 / 10; -	if (infolen < 50) { +	if(infolen < 50) {  		infolen = 50;  	} @@ -492,10 +492,11 @@ void cb_dl_progress(const char *filename, off_t file_xfered, off_t file_total)  	int totaldownload = 0;  	off_t xfered, total; -	double rate = 0.0, timediff = 0.0, f_xfered = 0.0; +	double rate = 0.0, timediff = 0.0;  	unsigned int eta_h = 0, eta_m = 0, eta_s = 0; +	double rate_human, xfered_human; +	const char *rate_label, *xfered_label;  	int file_percent = 0, total_percent = 0; -	char rate_size = 'K', xfered_size = 'K';  	if(config->noprogressbar || file_total == -1) {  		if(file_xfered == 0) { @@ -506,7 +507,7 @@ void cb_dl_progress(const char *filename, off_t file_xfered, off_t file_total)  	}  	infolen = getcols() * 6 / 10; -	if (infolen < 50) { +	if(infolen < 50) {  		infolen = 50;  	}  	/* explanation of magic 28 number at the end */ @@ -557,7 +558,7 @@ void cb_dl_progress(const char *filename, off_t file_xfered, off_t file_total)  		diff_sec = current_time.tv_sec - initial_time.tv_sec;  		diff_usec = current_time.tv_usec - initial_time.tv_usec;  		timediff = diff_sec + (diff_usec / 1000000.0); -		rate = xfered / (timediff * 1024.0); +		rate = xfered / timediff;  		/* round elapsed time to the nearest second */  		eta_s = (int)(timediff + 0.5); @@ -569,10 +570,10 @@ void cb_dl_progress(const char *filename, off_t file_xfered, off_t file_total)  			/* return if the calling interval was too short */  			return;  		} -		rate = (xfered - xfered_last) / (timediff * 1024.0); +		rate = (xfered - xfered_last) / timediff;  		/* average rate to reduce jumpiness */  		rate = (rate + 2 * rate_last) / 3; -		eta_s = (total - xfered) / (rate * 1024.0); +		eta_s = (total - xfered) / rate;  		rate_last = rate;  		xfered_last = xfered;  	} @@ -626,37 +627,13 @@ void cb_dl_progress(const char *filename, off_t file_xfered, off_t file_total)  	} -	/* Awesome formatting for progress bar.  We need a mess of Kb->Mb->Gb stuff -	 * here. We'll use limit of 2048 for each until we get some empirical */ -	/* rate_size = 'K'; was set above */ -	if(rate > 2048.0) { -		rate /= 1024.0; -		rate_size = 'M'; -		if(rate > 2048.0) { -			rate /= 1024.0; -			rate_size = 'G'; -			/* we should not go higher than this for a few years (9999.9 Gb/s?)*/ -		} -	} - -	f_xfered = xfered / 1024.0; /* convert to K by default */ -	/* xfered_size = 'K'; was set above */ -	if(f_xfered > 2048.0) { -		f_xfered /= 1024.0; -		xfered_size = 'M'; -		if(f_xfered > 2048.0) { -			f_xfered /= 1024.0; -			xfered_size = 'G'; -			/* I should seriously hope that archlinux packages never break -			 * the 9999.9GB mark... we'd have more serious problems than the progress -			 * bar in pacman */ -		} -	} +	rate_human = humanize_size((off_t)rate, '\0', 0, &rate_label); +	xfered_human = humanize_size(xfered, '\0', 0, &xfered_label);  	/* 1 space + filenamelen + 1 space + 7 for size + 1 + 7 for rate + 2 for /s + 1 space + 8 for eta */ -	printf(" %ls%-*s %6.1f%c %#6.1f%c/s %02u:%02u:%02u", wcfname, -			padwid, "", f_xfered, xfered_size, -			rate, rate_size, eta_h, eta_m, eta_s); +	printf(" %ls%-*s %6.1f%s %#6.1f%s/s %02u:%02u:%02u", wcfname, +			padwid, "", xfered_human, xfered_label, rate_human, rate_label, +			eta_h, eta_m, eta_s);  	free(fname);  	free(wcfname); diff --git a/src/pacman/conf.c b/src/pacman/conf.c index e2a168ee..370ec510 100644 --- a/src/pacman/conf.c +++ b/src/pacman/conf.c @@ -20,13 +20,20 @@  #include "config.h" +#include <errno.h> +#include <glob.h> +#include <limits.h>  #include <stdlib.h>  #include <stdio.h>  #include <string.h> /* strdup */ +#include <sys/stat.h> +#include <sys/utsname.h> /* uname */ +#include <unistd.h>  /* pacman */  #include "conf.h"  #include "util.h" +#include "pacman.h"  /* global config variable */  config_t *config = NULL; @@ -38,7 +45,7 @@ config_t *config_new(void)  			pm_fprintf(stderr, PM_LOG_ERROR,  					_("malloc failure: could not allocate %zd bytes\n"),  					sizeof(config_t)); -			return(NULL); +			return NULL;  	}  	/* defaults which may get overridden later */  	newconfig->op = PM_OP_MAIN; @@ -46,13 +53,13 @@ config_t *config_new(void)  	/* CONFFILE is defined at compile-time */  	newconfig->configfile = strdup(CONFFILE); -	return(newconfig); +	return newconfig;  }  int config_free(config_t *oldconfig)  {  	if(oldconfig == NULL) { -		return(-1); +		return -1;  	}  	FREELIST(oldconfig->holdpkg); @@ -66,7 +73,624 @@ int config_free(config_t *oldconfig)  	free(oldconfig);  	oldconfig = NULL; -	return(0); +	return 0; +} + +/** Helper function for download_with_xfercommand() */ +static char *get_filename(const char *url) { +	char *filename = strrchr(url, '/'); +	if(filename != NULL) { +		filename++; +	} +	return filename; +} + +/** Helper function for download_with_xfercommand() */ +static char *get_destfile(const char *path, const char *filename) { +	char *destfile; +	/* len = localpath len + filename len + null */ +	size_t len = strlen(path) + strlen(filename) + 1; +	destfile = calloc(len, sizeof(char)); +	snprintf(destfile, len, "%s%s", path, filename); + +	return destfile; +} + +/** Helper function for download_with_xfercommand() */ +static char *get_tempfile(const char *path, const char *filename) { +	char *tempfile; +	/* len = localpath len + filename len + '.part' len + null */ +	size_t len = strlen(path) + strlen(filename) + 6; +	tempfile = calloc(len, sizeof(char)); +	snprintf(tempfile, len, "%s%s.part", path, filename); + +	return tempfile; +} + +/** External fetch callback */ +static int download_with_xfercommand(const char *url, const char *localpath, +		int force) { +	int ret = 0; +	int retval; +	int usepart = 0; +	struct stat st; +	char *parsedcmd,*tempcmd; +	char cwd[PATH_MAX]; +	int restore_cwd = 0; +	char *destfile, *tempfile, *filename; + +	if(!config->xfercommand) { +		return -1; +	} + +	filename = get_filename(url); +	if(!filename) { +		return -1; +	} +	destfile = get_destfile(localpath, filename); +	tempfile = get_tempfile(localpath, filename); + +	if(force && stat(tempfile, &st) == 0) { +		unlink(tempfile); +	} +	if(force && stat(destfile, &st) == 0) { +		unlink(destfile); +	} + +	tempcmd = strdup(config->xfercommand); +	/* replace all occurrences of %o with fn.part */ +	if(strstr(tempcmd, "%o")) { +		usepart = 1; +		parsedcmd = strreplace(tempcmd, "%o", tempfile); +		free(tempcmd); +		tempcmd = parsedcmd; +	} +	/* replace all occurrences of %u with the download URL */ +	parsedcmd = strreplace(tempcmd, "%u", url); +	free(tempcmd); + +	/* save the cwd so we can restore it later */ +	if(getcwd(cwd, PATH_MAX) == NULL) { +		pm_printf(PM_LOG_ERROR, _("could not get current working directory\n")); +	} else { +		restore_cwd = 1; +	} + +	/* cwd to the download directory */ +	if(chdir(localpath)) { +		pm_printf(PM_LOG_WARNING, _("could not chdir to download directory %s\n"), localpath); +		ret = -1; +		goto cleanup; +	} +	/* execute the parsed command via /bin/sh -c */ +	pm_printf(PM_LOG_DEBUG, "running command: %s\n", parsedcmd); +	retval = system(parsedcmd); + +	if(retval == -1) { +		pm_printf(PM_LOG_WARNING, _("running XferCommand: fork failed!\n")); +		ret = -1; +	} else if(retval != 0) { +		/* download failed */ +		pm_printf(PM_LOG_DEBUG, "XferCommand command returned non-zero status " +				"code (%d)\n", retval); +		ret = -1; +	} else { +		/* download was successful */ +		if(usepart) { +			rename(tempfile, destfile); +		} +		ret = 0; +	} + +cleanup: +	/* restore the old cwd if we have it */ +	if(restore_cwd && chdir(cwd) != 0) { +		pm_printf(PM_LOG_ERROR, _("could not change directory to %s (%s)\n"), +				cwd, strerror(errno)); +	} + +	if(ret == -1) { +		/* hack to let an user the time to cancel a download */ +		sleep(2); +	} +	free(destfile); +	free(tempfile); +	free(parsedcmd); + +	return ret; +} + + +int config_set_arch(const char *arch) +{ +	if(strcmp(arch, "auto") == 0) { +		struct utsname un; +		uname(&un); +		pm_printf(PM_LOG_DEBUG, "config: Architecture: %s\n", un.machine); +		return alpm_option_set_arch(un.machine); +	} else { +		pm_printf(PM_LOG_DEBUG, "config: Architecture: %s\n", arch); +		return alpm_option_set_arch(arch); +	} +} + +static pgp_verify_t option_verifysig(const char *value) +{ +	pgp_verify_t level; +	if(strcmp(value, "Always") == 0) { +		level = PM_PGP_VERIFY_ALWAYS; +	} else if(strcmp(value, "Optional") == 0) { +		level = PM_PGP_VERIFY_OPTIONAL; +	} else if(strcmp(value, "Never") == 0) { +		level = PM_PGP_VERIFY_NEVER; +	} else { +		level = PM_PGP_VERIFY_UNKNOWN; +	} +	pm_printf(PM_LOG_DEBUG, "config: VerifySig = %s (%d)\n", value, level); +	return level; +} + +/* helper for being used with setrepeatingoption */ +static int option_add_holdpkg(const char *name) { +	config->holdpkg = alpm_list_add(config->holdpkg, strdup(name)); +	return 0; +} + +/* helper for being used with setrepeatingoption */ +static int option_add_syncfirst(const char *name) { +	config->syncfirst = alpm_list_add(config->syncfirst, strdup(name)); +	return 0; +} + +/* helper for being used with setrepeatingoption */ +static int option_add_cleanmethod(const char *value) { +	if(strcmp(value, "KeepInstalled") == 0) { +		config->cleanmethod |= PM_CLEAN_KEEPINST; +	} else if(strcmp(value, "KeepCurrent") == 0) { +		config->cleanmethod |= PM_CLEAN_KEEPCUR; +	} else { +		pm_printf(PM_LOG_ERROR, _("invalid value for 'CleanMethod' : '%s'\n"), +				value); +	} +	return 0; +} + +/** Add repeating options such as NoExtract, NoUpgrade, etc to libalpm + * settings. Refactored out of the parseconfig code since all of them did + * the exact same thing and duplicated code. + * @param ptr a pointer to the start of the multiple options + * @param option the string (friendly) name of the option, used for messages + * @param optionfunc a function pointer to an alpm_option_add_* function + */ +static void setrepeatingoption(char *ptr, const char *option, +		int (*optionfunc)(const char *)) +{ +	char *q; + +	while((q = strchr(ptr, ' '))) { +		*q = '\0'; +		(*optionfunc)(ptr); +		pm_printf(PM_LOG_DEBUG, "config: %s: %s\n", option, ptr); +		ptr = q; +		ptr++; +	} +	(*optionfunc)(ptr); +	pm_printf(PM_LOG_DEBUG, "config: %s: %s\n", option, ptr); +} + +static int _parse_options(const char *key, char *value, +		const char *file, int linenum) +{ +	if(value == NULL) { +		/* options without settings */ +		if(strcmp(key, "UseSyslog") == 0) { +			alpm_option_set_usesyslog(1); +			pm_printf(PM_LOG_DEBUG, "config: usesyslog\n"); +		} else if(strcmp(key, "ILoveCandy") == 0) { +			config->chomp = 1; +			pm_printf(PM_LOG_DEBUG, "config: chomp\n"); +		} else if(strcmp(key, "VerbosePkgLists") == 0) { +			config->verbosepkglists = 1; +			pm_printf(PM_LOG_DEBUG, "config: verbosepkglists\n"); +		} else if(strcmp(key, "UseDelta") == 0) { +			alpm_option_set_usedelta(1); +			pm_printf(PM_LOG_DEBUG, "config: usedelta\n"); +		} else if(strcmp(key, "TotalDownload") == 0) { +			config->totaldownload = 1; +			pm_printf(PM_LOG_DEBUG, "config: totaldownload\n"); +		} else if(strcmp(key, "CheckSpace") == 0) { +			alpm_option_set_checkspace(1); +		} else { +			pm_printf(PM_LOG_WARNING, +					_("config file %s, line %d: directive '%s' in section '%s' not recognized.\n"), +					file, linenum, key, "options"); +		} +	} else { +		/* options with settings */ +		if(strcmp(key, "NoUpgrade") == 0) { +			setrepeatingoption(value, "NoUpgrade", alpm_option_add_noupgrade); +		} else if(strcmp(key, "NoExtract") == 0) { +			setrepeatingoption(value, "NoExtract", alpm_option_add_noextract); +		} else if(strcmp(key, "IgnorePkg") == 0) { +			setrepeatingoption(value, "IgnorePkg", alpm_option_add_ignorepkg); +		} else if(strcmp(key, "IgnoreGroup") == 0) { +			setrepeatingoption(value, "IgnoreGroup", alpm_option_add_ignoregrp); +		} else if(strcmp(key, "HoldPkg") == 0) { +			setrepeatingoption(value, "HoldPkg", option_add_holdpkg); +		} else if(strcmp(key, "SyncFirst") == 0) { +			setrepeatingoption(value, "SyncFirst", option_add_syncfirst); +		} else if(strcmp(key, "Architecture") == 0) { +			if(!alpm_option_get_arch()) { +				config_set_arch(value); +			} +		} else if(strcmp(key, "DBPath") == 0) { +			/* don't overwrite a path specified on the command line */ +			if(!config->dbpath) { +				config->dbpath = strdup(value); +				pm_printf(PM_LOG_DEBUG, "config: dbpath: %s\n", value); +			} +		} else if(strcmp(key, "CacheDir") == 0) { +			if(alpm_option_add_cachedir(value) != 0) { +				pm_printf(PM_LOG_ERROR, _("problem adding cachedir '%s' (%s)\n"), +						value, alpm_strerrorlast()); +				return 1; +			} +			pm_printf(PM_LOG_DEBUG, "config: cachedir: %s\n", value); +		} else if(strcmp(key, "RootDir") == 0) { +			/* don't overwrite a path specified on the command line */ +			if(!config->rootdir) { +				config->rootdir = strdup(value); +				pm_printf(PM_LOG_DEBUG, "config: rootdir: %s\n", value); +			} +		} else if(strcmp(key, "GPGDir") == 0) { +			if(!config->gpgdir) { +				config->gpgdir = strdup(value); +				pm_printf(PM_LOG_DEBUG, "config: gpgdir: %s\n", value); +			} +		} else if(strcmp(key, "LogFile") == 0) { +			if(!config->logfile) { +				config->logfile = strdup(value); +				pm_printf(PM_LOG_DEBUG, "config: logfile: %s\n", value); +			} +		} else if(strcmp(key, "XferCommand") == 0) { +			config->xfercommand = strdup(value); +			alpm_option_set_fetchcb(download_with_xfercommand); +			pm_printf(PM_LOG_DEBUG, "config: xfercommand: %s\n", value); +		} else if(strcmp(key, "CleanMethod") == 0) { +			setrepeatingoption(value, "CleanMethod", option_add_cleanmethod); +		} else if(strcmp(key, "VerifySig") == 0) { +			pgp_verify_t level = option_verifysig(value); +			if(level != PM_PGP_VERIFY_UNKNOWN) { +				alpm_option_set_default_sigverify(level); +			} else { +				pm_printf(PM_LOG_ERROR, +						_("config file %s, line %d: directive '%s' has invalid value '%s'\n"), +						file, linenum, key, value); +				return 1; +			} +		} else { +			pm_printf(PM_LOG_WARNING, +					_("config file %s, line %d: directive '%s' in section '%s' not recognized.\n"), +					file, linenum, key, "options"); +		} + +	} +	return 0; +} + +static int _add_mirror(pmdb_t *db, char *value) +{ +	const char *dbname = alpm_db_get_name(db); +	/* let's attempt a replacement for the current repo */ +	char *temp = strreplace(value, "$repo", dbname); +	/* let's attempt a replacement for the arch */ +	const char *arch = alpm_option_get_arch(); +	char *server; +	if(arch) { +		server = strreplace(temp, "$arch", arch); +		free(temp); +	} else { +		if(strstr(temp, "$arch")) { +			free(temp); +			pm_printf(PM_LOG_ERROR, _("The mirror '%s' contains the $arch" +						" variable, but no Architecture is defined.\n"), value); +			return 1; +		} +		server = temp; +	} + +	if(alpm_db_add_server(db, server) != 0) { +		/* pm_errno is set by alpm_db_setserver */ +		pm_printf(PM_LOG_ERROR, _("could not add server URL to database '%s': %s (%s)\n"), +				dbname, server, alpm_strerrorlast()); +		free(server); +		return 1; +	} + +	free(server); +	return 0; +} + +/** Sets all libalpm required paths in one go. Called after the command line + * and inital config file parsing. Once this is complete, we can see if any + * paths were defined. If a rootdir was defined and nothing else, we want all + * of our paths to live under the rootdir that was specified. Safe to call + * multiple times (will only do anything the first time). + */ +static int setlibpaths(void) +{ +	int ret = 0; + +	pm_printf(PM_LOG_DEBUG, "setlibpaths() called\n"); +	/* Configure root path first. If it is set and dbpath/logfile were not +	 * set, then set those as well to reside under the root. */ +	if(config->rootdir) { +		char path[PATH_MAX]; +		ret = alpm_option_set_root(config->rootdir); +		if(ret != 0) { +			pm_printf(PM_LOG_ERROR, _("problem setting rootdir '%s' (%s)\n"), +					config->rootdir, alpm_strerrorlast()); +			return ret; +		} +		if(!config->dbpath) { +			/* omit leading slash from our static DBPATH, root handles it */ +			snprintf(path, PATH_MAX, "%s%s", alpm_option_get_root(), DBPATH + 1); +			config->dbpath = strdup(path); +		} +		if(!config->logfile) { +			/* omit leading slash from our static LOGFILE path, root handles it */ +			snprintf(path, PATH_MAX, "%s%s", alpm_option_get_root(), LOGFILE + 1); +			config->logfile = strdup(path); +		} +	} +	/* Set other paths if they were configured. Note that unless rootdir +	 * was left undefined, these two paths (dbpath and logfile) will have +	 * been set locally above, so the if cases below will now trigger. */ +	if(config->dbpath) { +		ret = alpm_option_set_dbpath(config->dbpath); +		if(ret != 0) { +			pm_printf(PM_LOG_ERROR, _("problem setting dbpath '%s' (%s)\n"), +					config->dbpath, alpm_strerrorlast()); +			return ret; +		} +	} +	if(config->logfile) { +		ret = alpm_option_set_logfile(config->logfile); +		if(ret != 0) { +			pm_printf(PM_LOG_ERROR, _("problem setting logfile '%s' (%s)\n"), +					config->logfile, alpm_strerrorlast()); +			return ret; +		} +	} + +	/* Set GnuPG's home directory.  This is not relative to rootdir, even if +	 * rootdir is defined. Reasoning: gpgdir contains configuration data. */ +	if(config->gpgdir) { +		ret = alpm_option_set_signaturedir(config->gpgdir); +		if(ret != 0) { +			pm_printf(PM_LOG_ERROR, _("problem setting gpgdir '%s' (%s)\n"), +					config->gpgdir, alpm_strerrorlast()); +			return ret; +		} +	} + +	/* add a default cachedir if one wasn't specified */ +	if(alpm_option_get_cachedirs() == NULL) { +		alpm_option_add_cachedir(CACHEDIR); +	} +	return 0; +} + + +/* The real parseconfig. Called with a null section argument by the publicly + * visible parseconfig so we can recall from within ourself on an include */ +static int _parseconfig(const char *file, int parse_options, +		char **section, pmdb_t *db) +{ +	FILE *fp = NULL; +	char line[PATH_MAX+1]; +	int linenum = 0; +	char *ptr; +	int ret = 0; + +	pm_printf(PM_LOG_DEBUG, "config: attempting to read file %s\n", file); +	fp = fopen(file, "r"); +	if(fp == NULL) { +		pm_printf(PM_LOG_ERROR, _("config file %s could not be read.\n"), file); +		return 1; +	} + +	while(fgets(line, PATH_MAX, fp)) { +		char *key, *value; + +		linenum++; +		strtrim(line); + +		/* ignore whole line and end of line comments */ +		if(strlen(line) == 0 || line[0] == '#') { +			continue; +		} +		if((ptr = strchr(line, '#'))) { +			*ptr = '\0'; +		} + +		/* sanity check */ +		if(parse_options && db) { +			pm_printf(PM_LOG_ERROR, _("config file %s, line %d: parsing options but have a database.\n"), +						file, linenum); +			ret = 1; +			goto cleanup; +		} + +		if(line[0] == '[' && line[strlen(line)-1] == ']') { +			char *name; +			/* new config section, skip the '[' */ +			ptr = line; +			ptr++; +			name = strdup(ptr); +			name[strlen(name)-1] = '\0'; +			if(!strlen(name)) { +				pm_printf(PM_LOG_ERROR, _("config file %s, line %d: bad section name.\n"), +						file, linenum); +				ret = 1; +				goto cleanup; +			} +			pm_printf(PM_LOG_DEBUG, "config: new section '%s'\n", name); +			/* if we are not looking at the options section, register a db */ +			if(!parse_options && strcmp(name, "options") != 0) { +				db = alpm_db_register_sync(name); +				if(db == NULL) { +					pm_printf(PM_LOG_ERROR, _("could not register '%s' database (%s)\n"), +							name, alpm_strerrorlast()); +					ret = 1; +					goto cleanup; +				} +			} +			if(*section) { +				free(*section); +			} +			*section = name; +			continue; +		} + +		/* directive */ +		/* strsep modifies the 'line' string: 'key \0 value' */ +		key = line; +		value = line; +		strsep(&value, "="); +		strtrim(key); +		strtrim(value); + +		if(key == NULL) { +			pm_printf(PM_LOG_ERROR, _("config file %s, line %d: syntax error in config file- missing key.\n"), +					file, linenum); +			ret = 1; +			goto cleanup; +		} +		/* For each directive, compare to the camelcase string. */ +		if(*section == NULL) { +			pm_printf(PM_LOG_ERROR, _("config file %s, line %d: All directives must belong to a section.\n"), +					file, linenum); +			ret = 1; +			goto cleanup; +		} +		/* Include is allowed in both options and repo sections */ +		if(strcmp(key, "Include") == 0) { +			glob_t globbuf; +			int globret; +			size_t gindex; + +			if(value == NULL) { +				pm_printf(PM_LOG_ERROR, _("config file %s, line %d: directive '%s' needs a value\n"), +						file, linenum, key); +				ret = 1; +				goto cleanup; +			} +			/* Ignore include failures... assume non-critical */ +			globret = glob(value, GLOB_NOCHECK, NULL, &globbuf); +			switch(globret) { +				case GLOB_NOSPACE: +					pm_printf(PM_LOG_DEBUG, +							"config file %s, line %d: include globbing out of space\n", +							file, linenum); +				break; +				case GLOB_ABORTED: +					pm_printf(PM_LOG_DEBUG, +							"config file %s, line %d: include globbing read error for %s\n", +							file, linenum, value); +				break; +				case GLOB_NOMATCH: +					pm_printf(PM_LOG_DEBUG, +							"config file %s, line %d: no include found for %s\n", +							file, linenum, value); +				break; +				default: +					for(gindex = 0; gindex < globbuf.gl_pathc; gindex++) { +						pm_printf(PM_LOG_DEBUG, "config file %s, line %d: including %s\n", +								file, linenum, globbuf.gl_pathv[gindex]); +						_parseconfig(globbuf.gl_pathv[gindex], parse_options, section, db); +					} +				break; +			} +			globfree(&globbuf); +			continue; +		} +		if(parse_options && strcmp(*section, "options") == 0) { +			/* we are either in options ... */ +			if((ret = _parse_options(key, value, file, linenum)) != 0) { +				goto cleanup; +			} +		} else if (!parse_options && strcmp(*section, "options") != 0) { +			/* ... or in a repo section */ +			if(strcmp(key, "Server") == 0) { +				if(value == NULL) { +					pm_printf(PM_LOG_ERROR, _("config file %s, line %d: directive '%s' needs a value\n"), +							file, linenum, key); +					ret = 1; +					goto cleanup; +				} +				if(_add_mirror(db, value) != 0) { +					ret = 1; +					goto cleanup; +				} +			} else if(strcmp(key, "VerifySig") == 0) { +				pgp_verify_t level = option_verifysig(value); +				if(level != PM_PGP_VERIFY_UNKNOWN) { +					ret = alpm_db_set_pgp_verify(db, level); +					if(ret != 0) { +						pm_printf(PM_LOG_ERROR, _("could not add set verify option for database '%s': %s (%s)\n"), +								alpm_db_get_name(db), value, alpm_strerrorlast()); +						goto cleanup; +					} +				} else { +					pm_printf(PM_LOG_ERROR, +							_("config file %s, line %d: directive '%s' has invalid value '%s'\n"), +							file, linenum, key, value); +					ret = 1; +					goto cleanup; +				} +			} else { +				pm_printf(PM_LOG_WARNING, +						_("config file %s, line %d: directive '%s' in section '%s' not recognized.\n"), +						file, linenum, key, *section); +			} +		} +	} + +cleanup: +	fclose(fp); +	pm_printf(PM_LOG_DEBUG, "config: finished parsing %s\n", file); +	return ret; +} + +/** Parse a configuration file. + * @param file path to the config file. + * @return 0 on success, non-zero on error + */ +int parseconfig(const char *file) +{ +	int ret; +	char *section = NULL; +	/* the config parse is a two-pass affair. We first parse the entire thing for +	 * the [options] section so we can get all default and path options set. +	 * Next, we go back and parse everything but [options]. */ + +	/* call the real parseconfig function with a null section & db argument */ +	pm_printf(PM_LOG_DEBUG, "parseconfig: options pass\n"); +	if((ret = _parseconfig(file, 1, §ion, NULL))) { +		free(section); +		return ret; +	} +	free(section); +	/* call setlibpaths here to ensure we have called it at least once */ +	if((ret = setlibpaths())) { +		return ret; +	} +	/* second pass, repo section parsing */ +	section = NULL; +	pm_printf(PM_LOG_DEBUG, "parseconfig: repo pass\n"); +	return _parseconfig(file, 0, §ion, NULL); +	free(section);  }  /* vim: set ts=2 sw=2 noet: */ diff --git a/src/pacman/conf.h b/src/pacman/conf.h index 92c379fc..76c76cf5 100644 --- a/src/pacman/conf.h +++ b/src/pacman/conf.h @@ -40,6 +40,7 @@ typedef struct __config_t {  	char *rootdir;  	char *dbpath;  	char *logfile; +	char *gpgdir;  	/* TODO how to handle cachedirs? */  	unsigned short op_q_isfile; @@ -68,12 +69,15 @@ typedef struct __config_t {  	unsigned int ask;  	/* conf file options */ -	unsigned short chomp; /* I Love Candy! */ -	unsigned short showsize; /* show individual package sizes */ +	/* I Love Candy! */ +	unsigned short chomp; +	/* format target pkg lists as table */ +	unsigned short verbosepkglists;  	/* When downloading, display the amount downloaded, rate, ETA, and percent  	 * downloaded of the total download list */  	unsigned short totaldownload; -	unsigned short cleanmethod; /* select -Sc behavior */ +	/* select -Sc behavior */ +	unsigned short cleanmethod;  	alpm_list_t *holdpkg;  	alpm_list_t *syncfirst;  	char *xfercommand; @@ -106,7 +110,8 @@ enum {  	OP_NEEDED,  	OP_ASEXPLICIT,  	OP_ARCH, -	OP_PRINTFORMAT +	OP_PRINTFORMAT, +	OP_GPGDIR  };  /* clean method */ @@ -121,6 +126,8 @@ extern config_t *config;  config_t *config_new(void);  int config_free(config_t *oldconfig); +int config_set_arch(const char *arch); +int parseconfig(const char *file);  #endif /* _PM_CONF_H */  /* vim: set ts=2 sw=2 noet: */ diff --git a/src/pacman/database.c b/src/pacman/database.c index 36433f33..123f72d2 100644 --- a/src/pacman/database.c +++ b/src/pacman/database.c @@ -20,7 +20,6 @@  #include "config.h" -#include <stdlib.h>  #include <stdio.h>  #include <alpm.h> @@ -47,7 +46,7 @@ int pacman_database(alpm_list_t *targets)  	if(targets == NULL) {  		pm_printf(PM_LOG_ERROR, _("no targets specified (use -h for help)\n")); -		return(1); +		return 1;  	}  	if(config->flags & PM_TRANS_FLAG_ALLDEPS) { /* --asdeps */ @@ -56,12 +55,12 @@ int pacman_database(alpm_list_t *targets)  		reason = PM_PKG_REASON_EXPLICIT;  	} else {  		pm_printf(PM_LOG_ERROR, _("no install reason specified (use -h for help)\n")); -		return(1); +		return 1;  	}  	/* Lock database */  	if(trans_init(0) == -1) { -		return(1); +		return 1;  	}  	db_local = alpm_option_get_localdb(); @@ -82,9 +81,9 @@ int pacman_database(alpm_list_t *targets)  	/* Unlock database */  	if(trans_release() == -1) { -		return(1); +		return 1;  	} -	return(retval); +	return retval;  }  /* vim: set ts=2 sw=2 noet: */ diff --git a/src/pacman/deptest.c b/src/pacman/deptest.c index 8895b487..19e4da4a 100644 --- a/src/pacman/deptest.c +++ b/src/pacman/deptest.c @@ -20,17 +20,13 @@  #include "config.h" -#include <stdlib.h>  #include <stdio.h> -#include <string.h>  #include <alpm.h>  #include <alpm_list.h>  /* pacman */  #include "pacman.h" -#include "util.h" -#include "conf.h"  int pacman_deptest(alpm_list_t *targets)  { @@ -47,7 +43,7 @@ int pacman_deptest(alpm_list_t *targets)  	}  	if(deps == NULL) { -		return(0); +		return 0;  	}  	for(i = deps; i; i = alpm_list_next(i)) { @@ -56,7 +52,7 @@ int pacman_deptest(alpm_list_t *targets)  		printf("%s\n", dep);  	}  	alpm_list_free(deps); -	return(127); +	return 127;  }  /* vim: set ts=2 sw=2 noet: */ diff --git a/src/pacman/package.c b/src/pacman/package.c index 77a5ee72..e256dda5 100644 --- a/src/pacman/package.c +++ b/src/pacman/package.c @@ -26,7 +26,6 @@  #include <unistd.h>  #include <limits.h>  #include <errno.h> -#include <wchar.h>  #include <alpm.h>  #include <alpm_list.h> @@ -37,20 +36,21 @@  #define CLBUF_SIZE 4096 -/* Display the content of a package - * - * levels: - *       <-1 - sync package, extra information (required by) [-Sii] - *        -1 - sync package, normal level [-Si] - *        =0 - file query [-Qip] - *         1 - localdb query, normal level [-Qi] - *        >1 - localdb query, extra information (backup files) [-Qii] +/** + * Display the details of a package. + * Extra information entails 'required by' info for sync packages and backup + * files info for local packages. + * @param pkg package to display information for + * @param from the type of package we are dealing with + * @param extra should we show extra information   */ -void dump_pkg_full(pmpkg_t *pkg, int level) +void dump_pkg_full(pmpkg_t *pkg, enum pkg_from from, int extra)  {  	const char *reason;  	time_t bdate, idate;  	char bdatestr[50] = "", idatestr[50] = ""; +	const char *label; +	double size;  	const alpm_list_t *i;  	alpm_list_t *requiredby = NULL, *depstrings = NULL; @@ -82,16 +82,20 @@ void dump_pkg_full(pmpkg_t *pkg, int level)  	/* turn depends list into a text list */  	for(i = alpm_pkg_get_depends(pkg); i; i = alpm_list_next(i)) { -		pmdepend_t *dep = (pmdepend_t*)alpm_list_getdata(i); +		pmdepend_t *dep = (pmdepend_t *)alpm_list_getdata(i);  		depstrings = alpm_list_add(depstrings, alpm_dep_compute_string(dep));  	} -	if(level > 0 || level < -1) { +	if(extra || from == PKG_FROM_LOCALDB) {  		/* compute this here so we don't get a pause in the middle of output */  		requiredby = alpm_pkg_compute_requiredby(pkg);  	}  	/* actual output */ +	if(from == PKG_FROM_SYNCDB) { +		string_display(_("Repository     :"), +				alpm_db_get_name(alpm_pkg_get_db(pkg))); +	}  	string_display(_("Name           :"), alpm_pkg_get_name(pkg));  	string_display(_("Version        :"), alpm_pkg_get_version(pkg));  	string_display(_("URL            :"), alpm_pkg_get_url(pkg)); @@ -100,42 +104,41 @@ void dump_pkg_full(pmpkg_t *pkg, int level)  	list_display(_("Provides       :"), alpm_pkg_get_provides(pkg));  	list_display(_("Depends On     :"), depstrings);  	list_display_linebreak(_("Optional Deps  :"), alpm_pkg_get_optdepends(pkg)); -	if(level > 0 || level < -1) { +	if(extra || from == PKG_FROM_LOCALDB) {  		list_display(_("Required By    :"), requiredby);  	}  	list_display(_("Conflicts With :"), alpm_pkg_get_conflicts(pkg));  	list_display(_("Replaces       :"), alpm_pkg_get_replaces(pkg)); -	if(level < 0) { -		printf(_("Download Size  : %6.2f K\n"), -			(double)alpm_pkg_get_size(pkg) / 1024.0); -	} -	if(level == 0) { -		printf(_("Compressed Size: %6.2f K\n"), -			(double)alpm_pkg_get_size(pkg) / 1024.0); + +	size = humanize_size(alpm_pkg_get_size(pkg), 'K', 1, &label); +	if(from == PKG_FROM_SYNCDB) { +		printf(_("Download Size  : %6.2f %s\n"), size, label); +	} else if(from == PKG_FROM_FILE) { +		printf(_("Compressed Size: %6.2f %s\n"), size, label);  	} -	printf(_("Installed Size : %6.2f K\n"), -			(double)alpm_pkg_get_isize(pkg) / 1024.0); +	size = humanize_size(alpm_pkg_get_isize(pkg), 'K', 1, &label); +	printf(_("Installed Size : %6.2f %s\n"), size, label); +  	string_display(_("Packager       :"), alpm_pkg_get_packager(pkg));  	string_display(_("Architecture   :"), alpm_pkg_get_arch(pkg));  	string_display(_("Build Date     :"), bdatestr); -	if(level > 0) { +	if(from == PKG_FROM_LOCALDB) {  		string_display(_("Install Date   :"), idatestr);  		string_display(_("Install Reason :"), reason);  	} -	if(level >= 0) { +	if(from == PKG_FROM_FILE || from == PKG_FROM_LOCALDB) {  		string_display(_("Install Script :"),  				alpm_pkg_has_scriptlet(pkg) ?  _("Yes") : _("No"));  	} -	/* MD5 Sum for sync package */ -	if(level < 0) { +	if(from == PKG_FROM_SYNCDB) {  		string_display(_("MD5 Sum        :"), alpm_pkg_get_md5sum(pkg));  	}  	string_display(_("Description    :"), alpm_pkg_get_desc(pkg));  	/* Print additional package info if info flag passed more than once */ -	if(level > 1) { +	if(from == PKG_FROM_LOCALDB && extra) {  		dump_pkg_backups(pkg);  	} @@ -146,23 +149,11 @@ void dump_pkg_full(pmpkg_t *pkg, int level)  	FREELIST(requiredby);  } -/* Display the content of a sync package - */ -void dump_pkg_sync(pmpkg_t *pkg, const char *treename, int level) -{ -	if(pkg == NULL) { -		return; -	} -	string_display(_("Repository     :"), treename); -	/* invert the level since we are a sync package */ -	dump_pkg_full(pkg, -level); -} -  static const char *get_backup_file_status(const char *root,  		const char *filename, const char *expected_md5)  {  	char path[PATH_MAX]; -	char *ret; +	const char *ret;  	snprintf(path, PATH_MAX, "%s%s", root, filename); @@ -173,11 +164,11 @@ static const char *get_backup_file_status(const char *root,  		if(md5sum == NULL) {  			pm_fprintf(stderr, PM_LOG_ERROR,  					_("could not calculate checksums for %s\n"), path); -			return(NULL); +			return NULL;  		}  		/* if checksums don't match, file has been modified */ -		if (strcmp(md5sum, expected_md5) != 0) { +		if(strcmp(md5sum, expected_md5) != 0) {  			ret = "MODIFIED";  		} else {  			ret = "UNMODIFIED"; @@ -195,7 +186,7 @@ static const char *get_backup_file_status(const char *root,  				ret = "UNKNOWN";  		}  	} -	return(ret); +	return ret;  }  /* Display list of backup files and their modification states diff --git a/src/pacman/package.h b/src/pacman/package.h index 26333c5a..7a5e5853 100644 --- a/src/pacman/package.h +++ b/src/pacman/package.h @@ -22,8 +22,14 @@  #include <alpm.h> -void dump_pkg_full(pmpkg_t *pkg, int level); -void dump_pkg_sync(pmpkg_t *pkg, const char *treename, int level); +/* TODO it would be nice if we didn't duplicate a backend type */ +enum pkg_from { +	PKG_FROM_FILE = 1, +	PKG_FROM_LOCALDB, +	PKG_FROM_SYNCDB +}; + +void dump_pkg_full(pmpkg_t *pkg, enum pkg_from from, int extra);  void dump_pkg_backups(pmpkg_t *pkg);  void dump_pkg_files(pmpkg_t *pkg, int quiet); diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c index 347d8af9..8458c976 100644 --- a/src/pacman/pacman.c +++ b/src/pacman/pacman.c @@ -36,12 +36,9 @@  #include <signal.h>  #include <unistd.h>  #include <sys/types.h> -#include <sys/stat.h>  #include <sys/utsname.h> /* uname */  #include <locale.h> /* setlocale */ -#include <time.h> /* time_t */  #include <errno.h> -#include <glob.h>  #if defined(PACMAN_DEBUG) && defined(HAVE_MCHECK_H)  #include <mcheck.h> /* debug tracing (mtrace) */  #endif @@ -55,7 +52,6 @@  #include "util.h"  #include "callback.h"  #include "conf.h" -#include "package.h"  /* list of targets specified on command line */  static alpm_list_t *pm_targets; @@ -66,9 +62,9 @@ static int options_cmp(const void *p1, const void *p2)  	const char *s1 = p1;  	const char *s2 = p2; -	if(s1 == s2) return(0); -	if(!s1) return(-1); -	if(!s2) return(1); +	if(s1 == s2) return 0; +	if(!s1) return -1; +	if(!s2) return 1;  	/* First skip all spaces in both strings */  	while(isspace((unsigned char)*s1)) {  		s1++; @@ -87,15 +83,15 @@ static int options_cmp(const void *p1, const void *p2)  			s2++;  		} else if(*s2 == '-') {  			/* s1 short, s2 long */ -			return(-1); +			return -1;  		} else if(*s1 == '-') {  			/* s1 long, s2 short */ -			return(1); +			return 1;  		}  		/* two short -> strcmp */  	} -	return(strcmp(s1, s2)); +	return strcmp(s1, s2);  }  /** Display usage/syntax for the specified operation. @@ -170,7 +166,7 @@ static void usage(int op, const char * const myname)  			addlist(_("  -w, --downloadonly   download packages but do not install/upgrade anything\n"));  			addlist(_("  -y, --refresh        download fresh package databases from the server\n"));  			addlist(_("      --needed         don't reinstall up to date packages\n")); -		} else if (op == PM_OP_DATABASE) { +		} else if(op == PM_OP_DATABASE) {  			printf("%s:  %s {-D --database} <%s> <%s>\n", str_usg, myname, str_opt, str_pkg);  			printf("%s:\n", str_opt);  			addlist(_("      --asdeps         mark packages as non-explicitly installed\n")); @@ -207,6 +203,7 @@ static void usage(int op, const char * const myname)  		addlist(_("      --cachedir <dir> set an alternate package cache location\n"));  		addlist(_("      --config <path>  set an alternate configuration file\n"));  		addlist(_("      --debug          display debug messages\n")); +		addlist(_("      --gpgdir <path>  set an alternate home directory for GnuPG\n"));  		addlist(_("      --logfile <path> set an alternate log file\n"));  		addlist(_("      --noconfirm      do not ask for any confirmation\n"));  	} @@ -239,7 +236,7 @@ static void version(void)  static void localize(void)  {  	static int init = 0; -	if (!init) { +	if(!init) {  		setlocale(LC_ALL, "");  		bindtextdomain(PACKAGE, LOCALEDIR);  		textdomain(PACKAGE); @@ -261,19 +258,6 @@ static void setuseragent(void)  	setenv("HTTP_USER_AGENT", agent, 0);  } -static void setarch(const char *arch) -{ -	if (strcmp(arch, "auto") == 0) { -		struct utsname un; -		uname(&un); -		pm_printf(PM_LOG_DEBUG, "config: Architecture: %s\n", un.machine); -		alpm_option_set_arch(un.machine); -	} else { -		pm_printf(PM_LOG_DEBUG, "config: Architecture: %s\n", arch); -		alpm_option_set_arch(arch); -	} -} -  /** Free the resources.   *   * @param ret the return value @@ -302,7 +286,7 @@ static ssize_t xwrite(int fd, const void *buf, size_t count)  	do {  		ret = write(fd, buf, count);  	} while(ret == -1 && errno == EINTR); -	return(ret); +	return ret;  }  /** Catches thrown signals. Performs necessary cleanup to ensure database is @@ -321,7 +305,7 @@ static void handler(int signum)  		xwrite(out, msg1, strlen(msg1));  		xwrite(err, msg2, strlen(msg2));  		exit(signum); -	} else if((signum == SIGINT)) { +	} else if(signum == SIGINT) {  		const char *msg = "\nInterrupt signal received\n";  		xwrite(err, msg, strlen(msg));  		if(alpm_trans_interrupt() == 0) { @@ -336,71 +320,9 @@ static void handler(int signum)  	cleanup(signum);  } -/** Sets all libalpm required paths in one go. Called after the command line - * and inital config file parsing. Once this is complete, we can see if any - * paths were defined. If a rootdir was defined and nothing else, we want all - * of our paths to live under the rootdir that was specified. Safe to call - * multiple times (will only do anything the first time). - */ -static void setlibpaths(void) -{ -	static int init = 0; -	if (!init) { -		int ret = 0; - -		pm_printf(PM_LOG_DEBUG, "setlibpaths() called\n"); -		/* Configure root path first. If it is set and dbpath/logfile were not -		 * set, then set those as well to reside under the root. */ -		if(config->rootdir) { -			char path[PATH_MAX]; -			ret = alpm_option_set_root(config->rootdir); -			if(ret != 0) { -				pm_printf(PM_LOG_ERROR, _("problem setting rootdir '%s' (%s)\n"), -						config->rootdir, alpm_strerrorlast()); -				cleanup(ret); -			} -			if(!config->dbpath) { -				/* omit leading slash from our static DBPATH, root handles it */ -				snprintf(path, PATH_MAX, "%s%s", alpm_option_get_root(), DBPATH + 1); -				config->dbpath = strdup(path); -			} -			if(!config->logfile) { -				/* omit leading slash from our static LOGFILE path, root handles it */ -				snprintf(path, PATH_MAX, "%s%s", alpm_option_get_root(), LOGFILE + 1); -				config->logfile = strdup(path); -			} -		} -		/* Set other paths if they were configured. Note that unless rootdir -		 * was left undefined, these two paths (dbpath and logfile) will have -		 * been set locally above, so the if cases below will now trigger. */ -		if(config->dbpath) { -			ret = alpm_option_set_dbpath(config->dbpath); -			if(ret != 0) { -				pm_printf(PM_LOG_ERROR, _("problem setting dbpath '%s' (%s)\n"), -						config->dbpath, alpm_strerrorlast()); -				cleanup(ret); -			} -		} -		if(config->logfile) { -			ret = alpm_option_set_logfile(config->logfile); -			if(ret != 0) { -				pm_printf(PM_LOG_ERROR, _("problem setting logfile '%s' (%s)\n"), -						config->logfile, alpm_strerrorlast()); -				cleanup(ret); -			} -		} +#define check_optarg() if(!optarg) { return 1; } -		/* add a default cachedir if one wasn't specified */ -		if(alpm_option_get_cachedirs() == NULL) { -			alpm_option_add_cachedir(CACHEDIR); -		} -		init = 1; -	} -} - -#define check_optarg() if(!optarg) { return(1); } - -typedef void (*fn_add) (const char *s); +typedef int (*fn_add) (const char *s);  static int parsearg_util_addlist(fn_add fn)  { @@ -412,7 +334,7 @@ static int parsearg_util_addlist(fn_add fn)  		fn((char *)alpm_list_getdata(item));  	}  	FREELIST(list); -	return(0); +	return 0;  }  /** Helper function for parsing operation from command-line arguments. @@ -449,9 +371,9 @@ static int parsearg_op(int opt, int dryrun)  			if(dryrun) break;  			config->help = 1; break;  		default: -			return(1); +			return 1;  	} -	return(0); +	return 0;  }  /** Helper functions for parsing command-line arguments. @@ -461,7 +383,10 @@ static int parsearg_op(int opt, int dryrun)  static int parsearg_global(int opt)  {  	switch(opt) { -		case OP_ARCH: check_optarg(); setarch(optarg); break; +		case OP_ARCH: +			check_optarg(); +			config_set_arch(optarg); +			break;  		case OP_ASK:  			check_optarg();  			config->noask = 1; @@ -472,7 +397,7 @@ static int parsearg_global(int opt)  			if(alpm_option_add_cachedir(optarg) != 0) {  				pm_printf(PM_LOG_ERROR, _("problem adding cachedir '%s' (%s)\n"),  						optarg, alpm_strerrorlast()); -				return(1); +				return 1;  			}  			break;  		case OP_CONFIG: @@ -497,7 +422,7 @@ static int parsearg_global(int opt)  					default:  						pm_printf(PM_LOG_ERROR, _("'%s' is not a valid debug level\n"),  								optarg); -						return(1); +						return 1;  				}  			} else {  				config->logmask |= PM_LOG_DEBUG; @@ -505,6 +430,9 @@ static int parsearg_global(int opt)  			/* progress bars get wonky with debug on, shut them off */  			config->noprogressbar = 1;  			break; +		case OP_GPGDIR: +			config->gpgdir = strdup(optarg); +			break;  		case OP_LOGFILE:  			check_optarg();  			config->logfile = strndup(optarg, PATH_MAX); @@ -516,9 +444,9 @@ static int parsearg_global(int opt)  			break;  		case 'r': check_optarg(); config->rootdir = strdup(optarg); break;  		case 'v': (config->verbose)++; break; -		default: return(1); +		default: return 1;  	} -	return(0); +	return 0;  }  static int parsearg_database(int opt) @@ -526,9 +454,9 @@ static int parsearg_database(int opt)  	switch(opt) {  		case OP_ASDEPS: config->flags |= PM_TRANS_FLAG_ALLDEPS; break;  		case OP_ASEXPLICIT: config->flags |= PM_TRANS_FLAG_ALLEXPLICIT; break; -		default: return(1); +		default: return 1;  	} -	return(0); +	return 0;  }  static int parsearg_query(int opt) @@ -548,9 +476,9 @@ static int parsearg_query(int opt)  		case 's': config->op_q_search = 1; break;  		case 't': config->op_q_unrequired = 1; break;  		case 'u': config->op_q_upgrade = 1; break; -		default: return(1); +		default: return 1;  	} -	return(0); +	return 0;  }  /* options common to -S -R -U */ @@ -572,15 +500,15 @@ static int parsearg_trans(int opt)  			check_optarg();  			config->print_format = strdup(optarg);  			break; -		default: return(1); +		default: return 1;  	} -	return(0); +	return 0;  }  static int parsearg_remove(int opt)  { -	if (parsearg_trans(opt) == 0) -		return(0); +	if(parsearg_trans(opt) == 0) +		return 0;  	switch(opt) {  		case 'c': config->flags |= PM_TRANS_FLAG_CASCADE; break;  		case 'n': config->flags |= PM_TRANS_FLAG_NOSAVE; break; @@ -592,16 +520,16 @@ static int parsearg_remove(int opt)  			}  			break;  		case 'u': config->flags |= PM_TRANS_FLAG_UNNEEDED; break; -		default: return(1); +		default: return 1;  	} -	return(0); +	return 0;  }  /* options common to -S -U */  static int parsearg_upgrade(int opt)  { -	if (parsearg_trans(opt) == 0) -		return(0); +	if(parsearg_trans(opt) == 0) +		return 0;  	switch(opt) {  		case 'f': config->flags |= PM_TRANS_FLAG_FORCE; break;  		case OP_ASDEPS: config->flags |= PM_TRANS_FLAG_ALLDEPS; break; @@ -612,15 +540,15 @@ static int parsearg_upgrade(int opt)  		case OP_IGNOREGROUP:  			parsearg_util_addlist(alpm_option_add_ignoregrp);  			break; -		default: return(1); +		default: return 1;  	} -	return(0); +	return 0;  }  static int parsearg_sync(int opt)  { -	if (parsearg_upgrade(opt) == 0) -		return(0); +	if(parsearg_upgrade(opt) == 0) +		return 0;  	switch(opt) {  		case OP_NEEDED: config->flags |= PM_TRANS_FLAG_NEEDED; break;  		case 'c': (config->op_s_clean)++; break; @@ -636,9 +564,9 @@ static int parsearg_sync(int opt)  			config->flags |= PM_TRANS_FLAG_NOCONFLICTS;  			break;  		case 'y': (config->op_s_sync)++; break; -		default: return(1); +		default: return 1;  	} -	return(0); +	return 0;  }  /** Parse command-line arguments for each operation. @@ -706,6 +634,7 @@ static int parseargs(int argc, char *argv[])  		{"asexplicit",     no_argument,   0, OP_ASEXPLICIT},  		{"arch",       required_argument, 0, OP_ARCH},  		{"print-format", required_argument, 0, OP_PRINTFORMAT}, +		{"gpgdir",     required_argument, 0, OP_GPGDIR},  		{0, 0, 0, 0}  	}; @@ -717,22 +646,22 @@ static int parseargs(int argc, char *argv[])  			continue;  		} else if(opt == '?') {  			/* unknown option, getopt printed an error */ -			return(1); +			return 1;  		}  		parsearg_op(opt, 0);  	}  	if(config->op == 0) {  		pm_printf(PM_LOG_ERROR, _("only one operation may be used at a time\n")); -		return(1); +		return 1;  	}  	if(config->help) {  		usage(config->op, mbasename(argv[0])); -		return(2); +		return 2;  	}  	if(config->version) {  		version(); -		return(2); +		return 2;  	}  	/* parse all other options */ @@ -744,7 +673,7 @@ static int parseargs(int argc, char *argv[])  			continue;  		} else if(opt == '?') {  			/* this should have failed during first pass already */ -			return(1); +			return 1;  		} else if(parsearg_op(opt, 1) == 0) {  			/* opt is an operation */  			continue; @@ -771,7 +700,7 @@ static int parseargs(int argc, char *argv[])  				result = 1;  				break;  		} -		if (result == 0) { +		if(result == 0) {  			continue;  		} @@ -780,7 +709,7 @@ static int parseargs(int argc, char *argv[])  		if(result != 0) {  			/* global option parsing failed, abort */  			pm_printf(PM_LOG_ERROR, _("invalid option\n")); -			return(result); +			return result;  		}  	} @@ -790,469 +719,7 @@ static int parseargs(int argc, char *argv[])  		optind++;  	} -	return(0); -} - -/* helper for being used with setrepeatingoption */ -static void option_add_holdpkg(const char *name) { -	config->holdpkg = alpm_list_add(config->holdpkg, strdup(name)); -} - -/* helper for being used with setrepeatingoption */ -static void option_add_syncfirst(const char *name) { -	config->syncfirst = alpm_list_add(config->syncfirst, strdup(name)); -} - -/* helper for being used with setrepeatingoption */ -static void option_add_cleanmethod(const char *value) { -	if (strcmp(value, "KeepInstalled") == 0) { -		config->cleanmethod |= PM_CLEAN_KEEPINST; -	} else if (strcmp(value, "KeepCurrent") == 0) { -		config->cleanmethod |= PM_CLEAN_KEEPCUR; -	} else { -		pm_printf(PM_LOG_ERROR, _("invalid value for 'CleanMethod' : '%s'\n"), -				value); -	} -} - -/** Add repeating options such as NoExtract, NoUpgrade, etc to libalpm - * settings. Refactored out of the parseconfig code since all of them did - * the exact same thing and duplicated code. - * @param ptr a pointer to the start of the multiple options - * @param option the string (friendly) name of the option, used for messages - * @param optionfunc a function pointer to an alpm_option_add_* function - */ -static void setrepeatingoption(char *ptr, const char *option, -		void (*optionfunc)(const char*)) -{ -	char *q; - -	while((q = strchr(ptr, ' '))) { -		*q = '\0'; -		(*optionfunc)(ptr); -		pm_printf(PM_LOG_DEBUG, "config: %s: %s\n", option, ptr); -		ptr = q; -		ptr++; -	} -	(*optionfunc)(ptr); -	pm_printf(PM_LOG_DEBUG, "config: %s: %s\n", option, ptr); -} - -static char *get_filename(const char *url) { -	char *filename = strrchr(url, '/'); -	if(filename != NULL) { -		filename++; -	} -	return(filename); -} - -static char *get_destfile(const char *path, const char *filename) { -	char *destfile; -	/* len = localpath len + filename len + null */ -	size_t len = strlen(path) + strlen(filename) + 1; -	destfile = calloc(len, sizeof(char)); -	snprintf(destfile, len, "%s%s", path, filename); - -	return(destfile); -} - -static char *get_tempfile(const char *path, const char *filename) { -	char *tempfile; -	/* len = localpath len + filename len + '.part' len + null */ -	size_t len = strlen(path) + strlen(filename) + 6; -	tempfile = calloc(len, sizeof(char)); -	snprintf(tempfile, len, "%s%s.part", path, filename); - -	return(tempfile); -} - -/** External fetch callback */ -static int download_with_xfercommand(const char *url, const char *localpath, -		int force) { -	int ret = 0; -	int retval; -	int usepart = 0; -	struct stat st; -	char *parsedcmd,*tempcmd; -	char cwd[PATH_MAX]; -	int restore_cwd = 0; -	char *destfile, *tempfile, *filename; - -	if(!config->xfercommand) { -		return -1; -	} - -	filename = get_filename(url); -	if(!filename) { -		return -1; -	} -	destfile = get_destfile(localpath, filename); -	tempfile = get_tempfile(localpath, filename); - -	if(force && stat(tempfile, &st) == 0) { -		unlink(tempfile); -	} -	if(force && stat(destfile, &st) == 0) { -		unlink(destfile); -	} - -	tempcmd = strdup(config->xfercommand); -	/* replace all occurrences of %o with fn.part */ -	if(strstr(tempcmd, "%o")) { -		usepart = 1; -		parsedcmd = strreplace(tempcmd, "%o", tempfile); -		free(tempcmd); -		tempcmd = parsedcmd; -	} -	/* replace all occurrences of %u with the download URL */ -	parsedcmd = strreplace(tempcmd, "%u", url); -	free(tempcmd); - -	/* save the cwd so we can restore it later */ -	if(getcwd(cwd, PATH_MAX) == NULL) { -		pm_printf(PM_LOG_ERROR, _("could not get current working directory\n")); -	} else { -		restore_cwd = 1; -	} - -	/* cwd to the download directory */ -	if(chdir(localpath)) { -		pm_printf(PM_LOG_WARNING, _("could not chdir to download directory %s\n"), localpath); -		ret = -1; -		goto cleanup; -	} -	/* execute the parsed command via /bin/sh -c */ -	pm_printf(PM_LOG_DEBUG, "running command: %s\n", parsedcmd); -	retval = system(parsedcmd); - -	if(retval == -1) { -		pm_printf(PM_LOG_WARNING, _("running XferCommand: fork failed!\n")); -		ret = -1; -	} else if(retval != 0) { -		/* download failed */ -		pm_printf(PM_LOG_DEBUG, "XferCommand command returned non-zero status " -				"code (%d)\n", retval); -		ret = -1; -	} else { -		/* download was successful */ -		if(usepart) { -			rename(tempfile, destfile); -		} -		ret = 0; -	} - -cleanup: -	/* restore the old cwd if we have it */ -	if(restore_cwd && chdir(cwd) != 0) { -		pm_printf(PM_LOG_ERROR, _("could not change directory to %s (%s)\n"), cwd, strerror(errno)); -	} - -	if(ret == -1) { -		/* hack to let an user the time to cancel a download */ -		sleep(2); -	} -	free(destfile); -	free(tempfile); -	free(parsedcmd); - -	return(ret); -} - -static int _parse_options(const char *key, char *value, -		const char *file, int linenum) -{ -	if(value == NULL) { -		/* options without settings */ -		if(strcmp(key, "UseSyslog") == 0) { -			alpm_option_set_usesyslog(1); -			pm_printf(PM_LOG_DEBUG, "config: usesyslog\n"); -		} else if(strcmp(key, "ILoveCandy") == 0) { -			config->chomp = 1; -			pm_printf(PM_LOG_DEBUG, "config: chomp\n"); -		} else if(strcmp(key, "ShowSize") == 0) { -			config->showsize = 1; -			pm_printf(PM_LOG_DEBUG, "config: showsize\n"); -		} else if(strcmp(key, "UseDelta") == 0) { -			alpm_option_set_usedelta(1); -			pm_printf(PM_LOG_DEBUG, "config: usedelta\n"); -		} else if(strcmp(key, "TotalDownload") == 0) { -			config->totaldownload = 1; -			pm_printf(PM_LOG_DEBUG, "config: totaldownload\n"); -		} else if(strcmp(key, "CheckSpace") == 0) { -			alpm_option_set_checkspace(1); -		} else { -			pm_printf(PM_LOG_WARNING, -					_("config file %s, line %d: directive '%s' in section '%s' not recognized.\n"), -					file, linenum, key, "options"); -		} -	} else { -		/* options with settings */ -		if(strcmp(key, "NoUpgrade") == 0) { -			setrepeatingoption(value, "NoUpgrade", alpm_option_add_noupgrade); -		} else if(strcmp(key, "NoExtract") == 0) { -			setrepeatingoption(value, "NoExtract", alpm_option_add_noextract); -		} else if(strcmp(key, "IgnorePkg") == 0) { -			setrepeatingoption(value, "IgnorePkg", alpm_option_add_ignorepkg); -		} else if(strcmp(key, "IgnoreGroup") == 0) { -			setrepeatingoption(value, "IgnoreGroup", alpm_option_add_ignoregrp); -		} else if(strcmp(key, "HoldPkg") == 0) { -			setrepeatingoption(value, "HoldPkg", option_add_holdpkg); -		} else if(strcmp(key, "SyncFirst") == 0) { -			setrepeatingoption(value, "SyncFirst", option_add_syncfirst); -		} else if(strcmp(key, "Architecture") == 0) { -			if(!alpm_option_get_arch()) { -				setarch(value); -			} -		} else if(strcmp(key, "DBPath") == 0) { -			/* don't overwrite a path specified on the command line */ -			if(!config->dbpath) { -				config->dbpath = strdup(value); -				pm_printf(PM_LOG_DEBUG, "config: dbpath: %s\n", value); -			} -		} else if(strcmp(key, "CacheDir") == 0) { -			if(alpm_option_add_cachedir(value) != 0) { -				pm_printf(PM_LOG_ERROR, _("problem adding cachedir '%s' (%s)\n"), -						value, alpm_strerrorlast()); -				return(1); -			} -			pm_printf(PM_LOG_DEBUG, "config: cachedir: %s\n", value); -		} else if(strcmp(key, "RootDir") == 0) { -			/* don't overwrite a path specified on the command line */ -			if(!config->rootdir) { -				config->rootdir = strdup(value); -				pm_printf(PM_LOG_DEBUG, "config: rootdir: %s\n", value); -			} -		} else if (strcmp(key, "LogFile") == 0) { -			if(!config->logfile) { -				config->logfile = strdup(value); -				pm_printf(PM_LOG_DEBUG, "config: logfile: %s\n", value); -			} -		} else if (strcmp(key, "XferCommand") == 0) { -			config->xfercommand = strdup(value); -			alpm_option_set_fetchcb(download_with_xfercommand); -			pm_printf(PM_LOG_DEBUG, "config: xfercommand: %s\n", value); -		} else if (strcmp(key, "CleanMethod") == 0) { -			setrepeatingoption(value, "CleanMethod", option_add_cleanmethod); -		} else { - -			pm_printf(PM_LOG_WARNING, -					_("config file %s, line %d: directive '%s' in section '%s' not recognized.\n"), -					file, linenum, key, "options"); -		} - -	} -	return(0); -} - -static int _add_mirror(pmdb_t *db, char *value) -{ -	const char *dbname = alpm_db_get_name(db); -	/* let's attempt a replacement for the current repo */ -	char *temp = strreplace(value, "$repo", dbname); -	/* let's attempt a replacement for the arch */ -	const char *arch = alpm_option_get_arch(); -	char *server; -	if(arch) { -		server = strreplace(temp, "$arch", arch); -		free(temp); -	} else { -		if(strstr(temp, "$arch")) { -			free(temp); -			pm_printf(PM_LOG_ERROR, _("The mirror '%s' contains the $arch" -						" variable, but no Architecture is defined.\n"), value); -			return(1); -		} -		server = temp; -	} - -	if(alpm_db_setserver(db, server) != 0) { -		/* pm_errno is set by alpm_db_setserver */ -		pm_printf(PM_LOG_ERROR, _("could not add server URL to database '%s': %s (%s)\n"), -				dbname, server, alpm_strerrorlast()); -		free(server); -		return(1); -	} - -	free(server); -	return(0); -} - -/* The real parseconfig. Called with a null section argument by the publicly - * visible parseconfig so we can recall from within ourself on an include */ -static int _parseconfig(const char *file, const char *givensection, -                        pmdb_t * const givendb) -{ -	FILE *fp = NULL; -	char line[PATH_MAX+1]; -	int linenum = 0; -	char *ptr, *section = NULL; -	pmdb_t *db = NULL; -	int ret = 0; - -	pm_printf(PM_LOG_DEBUG, "config: attempting to read file %s\n", file); -	fp = fopen(file, "r"); -	if(fp == NULL) { -		pm_printf(PM_LOG_ERROR, _("config file %s could not be read.\n"), file); -		return(1); -	} - -	/* if we are passed a section, use it as our starting point */ -	if(givensection != NULL) { -		section = strdup(givensection); -	} -	/* if we are passed a db, use it as our starting point */ -	if(givendb != NULL) { -		db = givendb; -	} - -	while(fgets(line, PATH_MAX, fp)) { -		linenum++; -		strtrim(line); - -		/* ignore whole line and end of line comments */ -		if(strlen(line) == 0 || line[0] == '#') { -			continue; -		} -		if((ptr = strchr(line, '#'))) { -			*ptr = '\0'; -		} - -		if(line[0] == '[' && line[strlen(line)-1] == ']') { -			/* new config section, skip the '[' */ -			ptr = line; -			ptr++; -			if(section) { -				free(section); -			} -			section = strdup(ptr); -			section[strlen(section)-1] = '\0'; -			pm_printf(PM_LOG_DEBUG, "config: new section '%s'\n", section); -			if(!strlen(section)) { -				pm_printf(PM_LOG_ERROR, _("config file %s, line %d: bad section name.\n"), -						file, linenum); -				ret = 1; -				goto cleanup; -			} -			/* if we are not looking at the options section, register a db */ -			if(strcmp(section, "options") != 0) { -				db = alpm_db_register_sync(section); -				if(db == NULL) { -					pm_printf(PM_LOG_ERROR, _("could not register '%s' database (%s)\n"), -							section, alpm_strerrorlast()); -					ret = 1; -					goto cleanup; -				} -			} -			continue; -		} - -		/* directive */ -		char *key, *value; -		/* strsep modifies the 'line' string: 'key \0 value' */ -		key = line; -		value = line; -		strsep(&value, "="); -		strtrim(key); -		strtrim(value); - -		if(key == NULL) { -			pm_printf(PM_LOG_ERROR, _("config file %s, line %d: syntax error in config file- missing key.\n"), -					file, linenum); -			ret = 1; -			goto cleanup; -		} -		/* For each directive, compare to the camelcase string. */ -		if(section == NULL) { -			pm_printf(PM_LOG_ERROR, _("config file %s, line %d: All directives must belong to a section.\n"), -					file, linenum); -			ret = 1; -			goto cleanup; -		} -		/* Include is allowed in both options and repo sections */ -		if(strcmp(key, "Include") == 0) { -			if(value == NULL) { -				pm_printf(PM_LOG_ERROR, _("config file %s, line %d: directive '%s' needs a value\n"), -						file, linenum, key); -				ret = 1; -				goto cleanup; -			} -			/* Ignore include failures... assume non-critical */ -			int globret; -			glob_t globbuf; -			globret = glob(value, GLOB_NOCHECK, NULL, &globbuf); -			switch(globret) { -				case GLOB_NOSPACE: -					pm_printf(PM_LOG_DEBUG, -							"config file %s, line %d: include globbing out of space\n", -							file, linenum); -				break; -				case GLOB_ABORTED: -					pm_printf(PM_LOG_DEBUG, -							"config file %s, line %d: include globbing read error for %s\n", -							file, linenum, value); -				break; -				case GLOB_NOMATCH: -					pm_printf(PM_LOG_DEBUG, -							"config file %s, line %d: no include found for %s\n", -							file, linenum, value); -				break; -				default: -					for(size_t gindex = 0; gindex < globbuf.gl_pathc; gindex++) { -						pm_printf(PM_LOG_DEBUG, "config file %s, line %d: including %s\n", -								file, linenum, globbuf.gl_pathv[gindex]); -						_parseconfig(globbuf.gl_pathv[gindex], section, db); -					} -				break; -			} -			globfree(&globbuf); -			continue; -		} -		if(strcmp(section, "options") == 0) { -			/* we are either in options ... */ -			if((ret = _parse_options(key, value, file, linenum)) != 0) { -				goto cleanup; -			} -		} else { -			/* ... or in a repo section */ -			if(strcmp(key, "Server") == 0) { -				if(value == NULL) { -					pm_printf(PM_LOG_ERROR, _("config file %s, line %d: directive '%s' needs a value\n"), -							file, linenum, key); -					ret = 1; -					goto cleanup; -				} -				if(_add_mirror(db, value) != 0) { -					ret = 1; -					goto cleanup; -				} -			} else { -				pm_printf(PM_LOG_WARNING, -						_("config file %s, line %d: directive '%s' in section '%s' not recognized.\n"), -						file, linenum, key, section); -			} -		} - -	} - -cleanup: -	fclose(fp); -	if(section){ -		free(section); -	} -	/* call setlibpaths here to ensure we have called it at least once */ -	setlibpaths(); -	pm_printf(PM_LOG_DEBUG, "config: finished parsing %s\n", file); -	return(ret); -} - -/** Parse a configuration file. - * @param file path to the config file. - * @return 0 on success, non-zero on error - */ -static int parseconfig(const char *file) -{ -	/* call the real parseconfig function with a null section & db argument */ -	return(_parseconfig(file, NULL, NULL)); +	return 0;  }  /** print commandline to logfile @@ -1346,6 +813,7 @@ int main(int argc, char *argv[])  	/* define paths to reasonable defaults */  	alpm_option_set_root(ROOTDIR);  	alpm_option_set_dbpath(DBPATH); +	alpm_option_set_signaturedir(GPGDIR);  	alpm_option_set_logfile(LOGFILE);  	/* Priority of options: @@ -1384,7 +852,7 @@ int main(int argc, char *argv[])  			}  		}  		/* check for buffer overflow */ -		if (i >= PATH_MAX) { +		if(i >= PATH_MAX) {  			pm_printf(PM_LOG_ERROR, _("buffer overflow detected in arg parsing\n"));  			cleanup(EXIT_FAILURE);  		} @@ -1394,7 +862,7 @@ int main(int argc, char *argv[])  			line[i] = '\0';  			pm_targets = alpm_list_add(pm_targets, strdup(line));  		} -		if (!freopen(ctermid(NULL), "r", stdin)) { +		if(!freopen(ctermid(NULL), "r", stdin)) {  			pm_printf(PM_LOG_ERROR, _("failed to reopen stdin for reading: (%s)\n"),  					strerror(errno));  		} @@ -1440,11 +908,12 @@ int main(int argc, char *argv[])  		printf("DB Path   : %s\n", alpm_option_get_dbpath());  		printf("Cache Dirs: ");  		for(i = alpm_option_get_cachedirs(); i; i = alpm_list_next(i)) { -			printf("%s  ", (char*)alpm_list_getdata(i)); +			printf("%s  ", (char *)alpm_list_getdata(i));  		}  		printf("\n");  		printf("Lock File : %s\n", alpm_option_get_lockfile());  		printf("Log File  : %s\n", alpm_option_get_logfile()); +		printf("GPG Dir   : %s\n", alpm_option_get_signaturedir());  		list_display("Targets   :", pm_targets);  	} @@ -1480,7 +949,7 @@ int main(int argc, char *argv[])  	cleanup(ret);  	/* not reached */ -	return(EXIT_SUCCESS); +	return EXIT_SUCCESS;  }  /* vim: set ts=2 sw=2 noet: */ diff --git a/src/pacman/pacman.h b/src/pacman/pacman.h index f5b972bb..762e112d 100644 --- a/src/pacman/pacman.h +++ b/src/pacman/pacman.h @@ -24,6 +24,8 @@  /* database.c */  int pacman_database(alpm_list_t *targets); +/* deptest.c */ +int pacman_deptest(alpm_list_t *targets);  /* query.c */  int pacman_query(alpm_list_t *targets);  /* remove.c */ @@ -33,9 +35,6 @@ int pacman_sync(alpm_list_t *targets);  /* upgrade.c */  int pacman_upgrade(alpm_list_t *targets); -/* deptest.c */ -int pacman_deptest(alpm_list_t *targets); -  #endif /* _PM_PACMAN_H */  /* vim: set ts=2 sw=2 noet: */ diff --git a/src/pacman/query.c b/src/pacman/query.c index 6c63774f..d1105b4a 100644 --- a/src/pacman/query.c +++ b/src/pacman/query.c @@ -26,7 +26,6 @@  #include <string.h>  #include <sys/stat.h>  #include <errno.h> -#include <unistd.h>  #include <alpm.h>  #include <alpm_list.h> @@ -43,15 +42,15 @@ static char *resolve_path(const char *file)  	str = calloc(PATH_MAX + 1, sizeof(char));  	if(!str) { -		return(NULL); +		return NULL;  	}  	if(!realpath(file, str)) {  		free(str); -		return(NULL); +		return NULL;  	} -	return(str); +	return str;  }  /* check if filename exists in PATH */ @@ -61,10 +60,10 @@ static int search_path(char **filename, struct stat *bufptr)  	size_t flen;  	if((envpath = getenv("PATH")) == NULL) { -		return(-1); +		return -1;  	}  	if((envpath = envpathsplit = strdup(envpath)) == NULL) { -		return(-1); +		return -1;  	}  	flen = strlen(*filename); @@ -88,12 +87,12 @@ static int search_path(char **filename, struct stat *bufptr)  			free(*filename);  			*filename = fullname;  			free(envpath); -			return(0); +			return 0;  		}  		free(fullname);  	}  	free(envpath); -	return(-1); +	return -1;  }  static void print_query_fileowner(const char *filename, pmpkg_t *info) @@ -119,7 +118,7 @@ static int query_fileowner(alpm_list_t *targets)  	/* This code is here for safety only */  	if(targets == NULL) {  		pm_fprintf(stderr, PM_LOG_ERROR, _("no file was specified for --owns\n")); -		return(1); +		return 1;  	}  	/* Set up our root path buffer. We only need to copy the location of root in @@ -171,7 +170,7 @@ static int query_fileowner(alpm_list_t *targets)  		bname = mbasename(filename);  		dname = mdirname(filename);  		/* for files in '/', there is no directory name to match */ -		if (strcmp(dname, "") == 0) { +		if(strcmp(dname, "") == 0) {  			rpath = NULL;  		} else {  			rpath = resolve_path(dname); @@ -252,29 +251,21 @@ static int query_search(alpm_list_t *targets)  		freelist = 0;  	}  	if(searchlist == NULL) { -		return(1); +		return 1;  	}  	for(i = searchlist; i; i = alpm_list_next(i)) {  		alpm_list_t *grp;  		pmpkg_t *pkg = alpm_list_getdata(i); -		if (!config->quiet) { +		if(!config->quiet) {  			printf("local/%s %s", alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg));  		} else {  			printf("%s", alpm_pkg_get_name(pkg));  		} -		/* print the package size with the output if ShowSize option set */ -		if(!config->quiet && config->showsize) { -			/* Convert byte size to MB */ -			double mbsize = (double)alpm_pkg_get_size(pkg) / (1024.0 * 1024.0); -			printf(" [%.2f MB]", mbsize); -		} - - -		if (!config->quiet) { +		if(!config->quiet) {  			if((grp = alpm_pkg_get_groups(pkg)) != NULL) {  				alpm_list_t *k;  				printf(" ("); @@ -300,7 +291,7 @@ static int query_search(alpm_list_t *targets)  	if(freelist) {  		alpm_list_free(searchlist);  	} -	return(0); +	return 0;  }  static int query_group(alpm_list_t *targets) @@ -363,19 +354,19 @@ static int is_foreign(pmpkg_t *pkg)  		}  	}  	if(match == 0) { -		return(1); +		return 1;  	} -	return(0); +	return 0;  }  static int is_unrequired(pmpkg_t *pkg)  {  	alpm_list_t *requiredby = alpm_pkg_compute_requiredby(pkg);  	if(requiredby == NULL) { -		return(1); +		return 1;  	}  	FREELIST(requiredby); -	return(0); +	return 0;  }  static int filter(pmpkg_t *pkg) @@ -383,26 +374,26 @@ static int filter(pmpkg_t *pkg)  	/* check if this package was explicitly installed */  	if(config->op_q_explicit &&  			alpm_pkg_get_reason(pkg) != PM_PKG_REASON_EXPLICIT) { -		return(0); +		return 0;  	}  	/* check if this package was installed as a dependency */  	if(config->op_q_deps &&  			alpm_pkg_get_reason(pkg) != PM_PKG_REASON_DEPEND) { -		return(0); +		return 0;  	}  	/* check if this pkg isn't in a sync DB */  	if(config->op_q_foreign && !is_foreign(pkg)) { -		return(0); +		return 0;  	}  	/* check if this pkg is unrequired */  	if(config->op_q_unrequired && !is_unrequired(pkg)) { -		return(0); +		return 0;  	}  	/* check if this pkg is outdated */  	if(config->op_q_upgrade && (alpm_sync_newversion(pkg, alpm_option_get_syncdbs()) == NULL)) { -		return(0); +		return 0;  	} -	return(1); +	return 1;  }  /* Loop through the packages. For each package, @@ -420,7 +411,7 @@ static int check(pmpkg_t *pkg)  	if(rootlen + 1 > PATH_MAX) {  		/* we are in trouble here */  		pm_fprintf(stderr, PM_LOG_ERROR, _("path too long: %s%s\n"), root, ""); -		return(1); +		return 1;  	}  	strcpy(f, root); @@ -454,7 +445,7 @@ static int check(pmpkg_t *pkg)  					(unsigned long)errors), errors);  	} -	return(errors != 0 ? 1 : 0); +	return (errors != 0 ? 1 : 0);  }  static int display(pmpkg_t *pkg) @@ -463,10 +454,9 @@ static int display(pmpkg_t *pkg)  	if(config->op_q_info) {  		if(config->op_q_isfile) { -			/* omit info that isn't applicable for a file package */ -			dump_pkg_full(pkg, 0); +			dump_pkg_full(pkg, PKG_FROM_FILE, 0);  		} else { -			dump_pkg_full(pkg, config->op_q_info); +			dump_pkg_full(pkg, PKG_FROM_LOCALDB, config->op_q_info > 1);  		}  	}  	if(config->op_q_list) { @@ -480,13 +470,13 @@ static int display(pmpkg_t *pkg)  	}  	if(!config->op_q_info && !config->op_q_list  			&& !config->op_q_changelog && !config->op_q_check) { -		if (!config->quiet) { +		if(!config->quiet) {  			printf("%s %s\n", alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg));  		} else {  			printf("%s\n", alpm_pkg_get_name(pkg));  		}  	} -	return(ret); +	return ret;  }  int pacman_query(alpm_list_t *targets) @@ -502,13 +492,13 @@ int pacman_query(alpm_list_t *targets)  	/* search for a package */  	if(config->op_q_search) {  		ret = query_search(targets); -		return(ret); +		return ret;  	}  	/* looking for groups */  	if(config->group) {  		ret = query_group(targets); -		return(ret); +		return ret;  	}  	if(config->op_q_foreign) { @@ -516,7 +506,7 @@ int pacman_query(alpm_list_t *targets)  		alpm_list_t *sync_dbs = alpm_option_get_syncdbs();  		if(sync_dbs == NULL || alpm_list_count(sync_dbs) == 0) {  			pm_printf(PM_LOG_ERROR, _("no usable package repositories configured.\n")); -			return(1); +			return 1;  		}  	} @@ -528,7 +518,7 @@ int pacman_query(alpm_list_t *targets)  	if(targets == NULL) {  		if(config->op_q_isfile || config->op_q_owns) {  			pm_printf(PM_LOG_ERROR, _("no targets specified (use -h for help)\n")); -			return(1); +			return 1;  		}  		for(i = alpm_db_get_pkgcache(db_local); i; i = alpm_list_next(i)) { @@ -544,7 +534,7 @@ int pacman_query(alpm_list_t *targets)  		if(!match) {  			ret = 1;  		} -		return(ret); +		return ret;  	}  	/* Second: operations that require target(s) */ @@ -552,7 +542,7 @@ int pacman_query(alpm_list_t *targets)  	/* determine the owner of a file */  	if(config->op_q_owns) {  		ret = query_fileowner(targets); -		return(ret); +		return ret;  	}  	/* operations on named packages in the local DB @@ -561,7 +551,7 @@ int pacman_query(alpm_list_t *targets)  		char *strname = alpm_list_getdata(i);  		if(config->op_q_isfile) { -			alpm_pkg_load(strname, 1, &pkg); +			alpm_pkg_load(strname, 1, PM_PGP_VERIFY_OPTIONAL, &pkg);  		} else {  			pkg = alpm_db_get_pkg(db_local, strname);  		} @@ -590,7 +580,7 @@ int pacman_query(alpm_list_t *targets)  		ret = 1;  	} -	return(ret); +	return ret;  }  /* vim: set ts=2 sw=2 noet: */ diff --git a/src/pacman/remove.c b/src/pacman/remove.c index fb02e242..58e6edd5 100644 --- a/src/pacman/remove.c +++ b/src/pacman/remove.c @@ -40,25 +40,25 @@ static int remove_target(char *target)  	if((info = alpm_db_get_pkg(db_local, target)) != NULL) {  		if(alpm_remove_pkg(info) == -1) {  			pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", target, alpm_strerrorlast()); -			return(-1); +			return -1;  		} -		return(0); +		return 0;  	}  		/* fallback to group */  	pmgrp_t *grp = alpm_db_readgrp(db_local, target);  	if(grp == NULL) {  		pm_fprintf(stderr, PM_LOG_ERROR, "'%s': target not found\n", target); -		return(-1); +		return -1;  	}  	for(p = alpm_grp_get_pkgs(grp); p; p = alpm_list_next(p)) {  		pmpkg_t *pkg = alpm_list_getdata(p);  		if(alpm_remove_pkg(pkg) == -1) {  			pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", target, alpm_strerrorlast()); -			return(-1); +			return -1;  		}  	} -	return(0); +	return 0;  }  /** @@ -75,12 +75,12 @@ int pacman_remove(alpm_list_t *targets)  	if(targets == NULL) {  		pm_printf(PM_LOG_ERROR, _("no targets specified (use -h for help)\n")); -		return(1); +		return 1;  	}  	/* Step 0: create a new transaction */  	if(trans_init(config->flags) == -1) { -		return(1); +		return 1;  	}  	/* Step 1: add targets to the created transaction */ @@ -173,7 +173,7 @@ cleanup:  	if(trans_release() == -1) {  		retval = 1;  	} -	return(retval); +	return retval;  }  /* vim: set ts=2 sw=2 noet: */ diff --git a/src/pacman/sync.c b/src/pacman/sync.c index c56934b6..884504f3 100644 --- a/src/pacman/sync.c +++ b/src/pacman/sync.c @@ -39,7 +39,8 @@  /* if keep_used != 0, then the db files which match an used syncdb   * will be kept  */ -static int sync_cleandb(const char *dbpath, int keep_used) { +static int sync_cleandb(const char *dbpath, int keep_used) +{  	DIR *dir;  	struct dirent *ent;  	alpm_list_t *syncdbs; @@ -47,7 +48,7 @@ static int sync_cleandb(const char *dbpath, int keep_used) {  	dir = opendir(dbpath);  	if(dir == NULL) {  		pm_fprintf(stderr, PM_LOG_ERROR, _("could not access database directory\n")); -		return(1); +		return 1;  	}  	syncdbs = alpm_option_get_syncdbs(); @@ -84,7 +85,7 @@ static int sync_cleandb(const char *dbpath, int keep_used) {  				pm_fprintf(stderr, PM_LOG_ERROR,  					_("could not remove %s\n"), path);  				closedir(dir); -				return(1); +				return 1;  			}  			continue;  		} @@ -110,15 +111,16 @@ static int sync_cleandb(const char *dbpath, int keep_used) {  				pm_fprintf(stderr, PM_LOG_ERROR,  					_("could not remove %s\n"), path);  				closedir(dir); -				return(1); +				return 1;  			}  		}  	}  	closedir(dir); -	return(0); +	return 0;  } -static int sync_cleandb_all(void) { +static int sync_cleandb_all(void) +{  	const char *dbpath;  	char newdbpath[PATH_MAX];  	int ret = 0; @@ -126,7 +128,7 @@ static int sync_cleandb_all(void) {  	dbpath = alpm_option_get_dbpath();  	printf(_("Database directory: %s\n"), dbpath);  	if(!yesno(_("Do you want to remove unused repositories?"))) { -		return(0); +		return 0;  	}  	/* The sync dbs were previously put in dbpath/ but are now in dbpath/sync/.  	 * We will clean everything in dbpath/ except local/, sync/ and db.lck, and @@ -137,7 +139,7 @@ static int sync_cleandb_all(void) {  	ret += sync_cleandb(newdbpath, 1);  	printf(_("Database directory cleaned up\n")); -	return(ret); +	return ret;  }  static int sync_cleancache(int level) @@ -148,7 +150,7 @@ static int sync_cleancache(int level)  	int ret = 0;  	for(i = alpm_option_get_cachedirs(); i; i = alpm_list_next(i)) { -		printf(_("Cache directory: %s\n"), (char*)alpm_list_getdata(i)); +		printf(_("Cache directory: %s\n"), (char *)alpm_list_getdata(i));  	}  	if(!config->cleanmethod) { @@ -165,12 +167,12 @@ static int sync_cleancache(int level)  			printf(_("  All current sync database packages\n"));  		}  		if(!yesno(_("Do you want to remove all other packages from cache?"))) { -			return(0); +			return 0;  		}  		printf(_("removing old packages from cache...\n"));  	} else {  		if(!noyes(_("Do you want to remove ALL files from cache?"))) { -			return(0); +			return 0;  		}  		printf(_("removing all files from cache...\n"));  	} @@ -191,10 +193,10 @@ static int sync_cleancache(int level)  		/* step through the directory one file at a time */  		while((ent = readdir(dir)) != NULL) {  			char path[PATH_MAX]; +			size_t pathlen;  			int delete = 1;  			pmpkg_t *localpkg = NULL, *pkg = NULL;  			const char *local_name, *local_version; -			alpm_list_t *j;  			if(strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) {  				continue; @@ -208,11 +210,19 @@ static int sync_cleancache(int level)  				continue;  			} +			/* we handle .sig files with packages, not separately */ +			pathlen = strlen(path); +			if(strcmp(path + pathlen - 4, ".sig") == 0) { +				continue; +			} +  			/* attempt to load the package, prompt removal on failures as we may have  			 * files here that aren't valid packages. we also don't need a full  			 * load of the package, just the metadata. */ -			if(alpm_pkg_load(path, 0, &localpkg) != 0 || localpkg == NULL) { -				if(yesno(_("File %s does not seem to be a valid package, remove it?"), path)) { +			if(alpm_pkg_load(path, 0, PM_PGP_VERIFY_NEVER, &localpkg) != 0 +					|| localpkg == NULL) { +				if(yesno(_("File %s does not seem to be a valid package, remove it?"), +							path)) {  					if(localpkg) {  						alpm_pkg_free(localpkg);  					} @@ -235,6 +245,7 @@ static int sync_cleancache(int level)  				}  			}  			if(config->cleanmethod & PM_CLEAN_KEEPCUR) { +				alpm_list_t *j;  				/* check if this package is in a sync DB */  				for(j = sync_dbs; j && delete; j = alpm_list_next(j)) {  					pmdb_t *db = alpm_list_getdata(j); @@ -253,12 +264,17 @@ static int sync_cleancache(int level)  			if(delete) {  				unlink(path); +				/* unlink a signature file if present too */ +				if(PATH_MAX - 5 >= pathlen) { +					strcpy(path + pathlen, ".sig"); +					unlink(path); +				}  			}  		}  		closedir(dir);  	} -	return(ret); +	return ret;  }  static int sync_synctree(int level, alpm_list_t *syncs) @@ -267,7 +283,7 @@ static int sync_synctree(int level, alpm_list_t *syncs)  	int success = 0, ret;  	if(trans_init(0) == -1) { -		return(0); +		return 0;  	}  	for(i = syncs; i; i = alpm_list_next(i)) { @@ -286,7 +302,7 @@ static int sync_synctree(int level, alpm_list_t *syncs)  	}  	if(trans_release() == -1) { -		return(0); +		return 0;  	}  	/* We should always succeed if at least one DB was upgraded - we may possibly  	 * fail later with unresolved deps, but that should be rare, and would be @@ -295,7 +311,7 @@ static int sync_synctree(int level, alpm_list_t *syncs)  	if(!success) {  		pm_fprintf(stderr, PM_LOG_ERROR, _("failed to synchronize any databases\n"));  	} -	return(success > 0); +	return (success > 0);  }  static void print_installed(pmdb_t *db_local, pmpkg_t *pkg) @@ -340,22 +356,14 @@ static int sync_search(alpm_list_t *syncs, alpm_list_t *targets)  			alpm_list_t *grp;  			pmpkg_t *pkg = alpm_list_getdata(j); -			if (!config->quiet) { +			if(!config->quiet) {  				printf("%s/%s %s", alpm_db_get_name(db), alpm_pkg_get_name(pkg),  							 alpm_pkg_get_version(pkg));  			} else {  				printf("%s", alpm_pkg_get_name(pkg));  			} -			/* print the package size with the output if ShowSize option set */ -			if(!config->quiet && config->showsize) { -				/* Convert byte size to MB */ -				double mbsize = (double)alpm_pkg_get_size(pkg) / (1024.0 * 1024.0); - -				printf(" [%.2f MB]", mbsize); -			} - -			if (!config->quiet) { +			if(!config->quiet) {  				if((grp = alpm_pkg_get_groups(pkg)) != NULL) {  					alpm_list_t *k;  					printf(" ("); @@ -384,7 +392,7 @@ static int sync_search(alpm_list_t *syncs, alpm_list_t *targets)  		}  	} -	return(!found); +	return !found;  }  static int sync_group(int level, alpm_list_t *syncs, alpm_list_t *targets) @@ -432,7 +440,7 @@ static int sync_group(int level, alpm_list_t *syncs, alpm_list_t *targets)  		}  	} -	return(0); +	return 0;  }  static int sync_info(alpm_list_t *syncs, alpm_list_t *targets) @@ -466,14 +474,14 @@ static int sync_info(alpm_list_t *syncs, alpm_list_t *targets)  				if(!db) {  					pm_fprintf(stderr, PM_LOG_ERROR,  						_("repository '%s' does not exist\n"), repo); -					return(1); +					return 1;  				}  				for(k = alpm_db_get_pkgcache(db); k; k = alpm_list_next(k)) {  					pmpkg_t *pkg = alpm_list_getdata(k);  					if(strcmp(alpm_pkg_get_name(pkg), pkgstr) == 0) { -						dump_pkg_sync(pkg, alpm_db_get_name(db), config->op_s_info); +						dump_pkg_full(pkg, PKG_FROM_SYNCDB, config->op_s_info > 1);  						foundpkg = 1;  						break;  					} @@ -494,7 +502,7 @@ static int sync_info(alpm_list_t *syncs, alpm_list_t *targets)  						pmpkg_t *pkg = alpm_list_getdata(k);  						if(strcmp(alpm_pkg_get_name(pkg), pkgstr) == 0) { -							dump_pkg_sync(pkg, alpm_db_get_name(db), config->op_s_info); +							dump_pkg_full(pkg, PKG_FROM_SYNCDB, config->op_s_info > 1);  							foundpkg = 1;  							break;  						} @@ -512,12 +520,13 @@ static int sync_info(alpm_list_t *syncs, alpm_list_t *targets)  			pmdb_t *db = alpm_list_getdata(i);  			for(j = alpm_db_get_pkgcache(db); j; j = alpm_list_next(j)) { -				dump_pkg_sync(alpm_list_getdata(j), alpm_db_get_name(db), config->op_s_info); +				pmpkg_t *pkg = alpm_list_getdata(j); +				dump_pkg_full(pkg, PKG_FROM_SYNCDB, config->op_s_info > 1);  			}  		}  	} -	return(ret); +	return ret;  }  static int sync_list(alpm_list_t *syncs, alpm_list_t *targets) @@ -543,7 +552,7 @@ static int sync_list(alpm_list_t *syncs, alpm_list_t *targets)  				pm_fprintf(stderr, PM_LOG_ERROR,  					_("repository \"%s\" was not found.\n"),repo);  				alpm_list_free(ls); -				return(1); +				return 1;  			}  			ls = alpm_list_add(ls, db); @@ -558,7 +567,7 @@ static int sync_list(alpm_list_t *syncs, alpm_list_t *targets)  		for(j = alpm_db_get_pkgcache(db); j; j = alpm_list_next(j)) {  			pmpkg_t *pkg = alpm_list_getdata(j); -			if (!config->quiet) { +			if(!config->quiet) {  				printf("%s %s %s", alpm_db_get_name(db), alpm_pkg_get_name(pkg),  						alpm_pkg_get_version(pkg));  				print_installed(db_local, pkg); @@ -573,7 +582,7 @@ static int sync_list(alpm_list_t *syncs, alpm_list_t *targets)  		alpm_list_free(ls);  	} -	return(0); +	return 0;  }  static alpm_list_t *syncfirst(void) { @@ -592,7 +601,7 @@ static alpm_list_t *syncfirst(void) {  		}  	} -	return(res); +	return res;  }  static pmdb_t *get_db(const char *dbname) @@ -601,10 +610,10 @@ static pmdb_t *get_db(const char *dbname)  	for(i = alpm_option_get_syncdbs(); i; i = i->next) {  		pmdb_t *db = i->data;  		if(strcmp(alpm_db_get_name(db), dbname) == 0) { -			return(db); +			return db;  		}  	} -	return(NULL); +	return NULL;  }  static int process_pkg(pmpkg_t *pkg) @@ -616,14 +625,14 @@ static int process_pkg(pmpkg_t *pkg)  				|| pm_errno == PM_ERR_PKG_IGNORED) {  			/* just skip duplicate or ignored targets */  			pm_printf(PM_LOG_WARNING, _("skipping target: %s\n"), alpm_pkg_get_name(pkg)); -			return(0); +			return 0;  		} else {  			pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", alpm_pkg_get_name(pkg),  					alpm_strerrorlast()); -			return(1); +			return 1;  		}  	} -	return(0); +	return 0;  }  static int process_group(alpm_list_t *dbs, char *group) @@ -635,7 +644,7 @@ static int process_group(alpm_list_t *dbs, char *group)  	if(!count) {  		pm_fprintf(stderr, PM_LOG_ERROR, _("target not found: %s\n"), group); -		return(1); +		return 1;  	} @@ -669,7 +678,7 @@ static int process_group(alpm_list_t *dbs, char *group)  	}  cleanup:  	alpm_list_free(pkgs); -	return(ret); +	return ret;  }  static int process_targname(alpm_list_t *dblist, char *targname) @@ -680,14 +689,14 @@ static int process_targname(alpm_list_t *dblist, char *targname)  	if(pm_errno == PM_ERR_PKG_IGNORED) {  			pm_printf(PM_LOG_WARNING, _("skipping target: %s\n"), targname);  			pm_errno = 0; -			return(0); +			return 0;  	}  	if(pkg) { -		return(process_pkg(pkg)); +		return process_pkg(pkg);  	}  	/* fallback on group */ -	return(process_group(dblist, targname)); +	return process_group(dblist, targname);  }  static int process_target(char *target) @@ -722,7 +731,7 @@ static int process_target(char *target)  	}  cleanup:  	free(targstring); -	return(ret); +	return ret;  }  static int sync_trans(alpm_list_t *targets) @@ -734,7 +743,7 @@ static int sync_trans(alpm_list_t *targets)  	/* Step 1: create a new transaction... */  	if(trans_init(config->flags) == -1) { -		return(1); +		return 1;  	}  	/* process targets */ @@ -874,7 +883,7 @@ cleanup:  		retval = 1;  	} -	return(retval); +	return retval;  }  int pacman_sync(alpm_list_t *targets) @@ -886,7 +895,7 @@ int pacman_sync(alpm_list_t *targets)  		int ret = 0;  		if(trans_init(0) == -1) { -			return(1); +			return 1;  		}  		ret += sync_cleancache(config->op_s_clean); @@ -897,14 +906,14 @@ int pacman_sync(alpm_list_t *targets)  			ret++;  		} -		return(ret); +		return ret;  	}  	/* ensure we have at least one valid sync db set up */  	sync_dbs = alpm_option_get_syncdbs();  	if(sync_dbs == NULL || alpm_list_count(sync_dbs) == 0) {  		pm_printf(PM_LOG_ERROR, _("no usable package repositories configured.\n")); -		return(1); +		return 1;  	}  	if(config->op_s_sync) { @@ -912,40 +921,40 @@ int pacman_sync(alpm_list_t *targets)  		printf(_(":: Synchronizing package databases...\n"));  		alpm_logaction("synchronizing package lists\n");  		if(!sync_synctree(config->op_s_sync, sync_dbs)) { -			return(1); +			return 1;  		}  	}  	/* search for a package */  	if(config->op_s_search) { -		return(sync_search(sync_dbs, targets)); +		return sync_search(sync_dbs, targets);  	}  	/* look for groups */  	if(config->group) { -		return(sync_group(config->group, sync_dbs, targets)); +		return sync_group(config->group, sync_dbs, targets);  	}  	/* get package info */  	if(config->op_s_info) { -		return(sync_info(sync_dbs, targets)); +		return sync_info(sync_dbs, targets);  	}  	/* get a listing of files in sync DBs */  	if(config->op_q_list) { -		return(sync_list(sync_dbs, targets)); +		return sync_list(sync_dbs, targets);  	}  	if(targets == NULL) {  		if(config->op_s_upgrade) {  			/* proceed */  		} else if(config->op_s_sync) { -			return(0); +			return 0;  		} else {  			/* don't proceed here unless we have an operation that doesn't require a  			 * target list */  			pm_printf(PM_LOG_ERROR, _("no targets specified (use -h for help)\n")); -			return(1); +			return 1;  		}  	} @@ -980,7 +989,7 @@ int pacman_sync(alpm_list_t *targets)  	int ret = sync_trans(targs);  	FREELIST(targs); -	return(ret); +	return ret;  }  /* vim: set ts=2 sw=2 noet: */ diff --git a/src/pacman/upgrade.c b/src/pacman/upgrade.c index 8cd29da0..0ffc94c4 100644 --- a/src/pacman/upgrade.c +++ b/src/pacman/upgrade.c @@ -42,11 +42,12 @@  int pacman_upgrade(alpm_list_t *targets)  {  	alpm_list_t *i, *data = NULL; +	pgp_verify_t check_sig = alpm_option_get_default_sigverify();  	int retval = 0;  	if(targets == NULL) {  		pm_printf(PM_LOG_ERROR, _("no targets specified (use -h for help)\n")); -		return(1); +		return 1;  	}  	/* Check for URL targets and process them @@ -57,7 +58,7 @@ int pacman_upgrade(alpm_list_t *targets)  			if(str == NULL) {  				pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n",  						(char *)i->data, alpm_strerrorlast()); -				return(1); +				return 1;  			} else {  				free(i->data);  				i->data = str; @@ -67,7 +68,7 @@ int pacman_upgrade(alpm_list_t *targets)  	/* Step 1: create a new transaction */  	if(trans_init(config->flags) == -1) { -		return(1); +		return 1;  	}  	/* add targets to the created transaction */ @@ -75,18 +76,18 @@ int pacman_upgrade(alpm_list_t *targets)  		char *targ = alpm_list_getdata(i);  		pmpkg_t *pkg; -		if(alpm_pkg_load(targ, 1, &pkg) != 0) { +		if(alpm_pkg_load(targ, 1, check_sig, &pkg) != 0) {  			pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n",  					targ, alpm_strerrorlast());  			trans_release(); -			return(1); +			return 1;  		}  		if(alpm_add_pkg(pkg) == -1) {  			pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n",  					targ, alpm_strerrorlast());  			alpm_pkg_free(pkg);  			trans_release(); -			return(1); +			return 1;  		}  	} @@ -135,7 +136,7 @@ int pacman_upgrade(alpm_list_t *targets)  		}  		trans_release();  		FREELIST(data); -		return(1); +		return 1;  	}  	/* Step 3: perform the installation */ @@ -143,7 +144,7 @@ int pacman_upgrade(alpm_list_t *targets)  	if(config->print) {  		print_packages(alpm_trans_get_add());  		trans_release(); -		return(0); +		return 0;  	}  	/* print targets and ask user confirmation */ @@ -151,7 +152,7 @@ int pacman_upgrade(alpm_list_t *targets)  	if(packages == NULL) { /* we are done */  		printf(_(" there is nothing to do\n"));  		trans_release(); -		return(retval); +		return retval;  	}  	display_targets(alpm_trans_get_remove(), 0);  	display_targets(alpm_trans_get_add(), 1); @@ -159,7 +160,7 @@ int pacman_upgrade(alpm_list_t *targets)  	int confirm = yesno(_("Proceed with installation?"));  	if(!confirm) {  		trans_release(); -		return(retval); +		return retval;  	}  	if(alpm_trans_commit(&data) == -1) { @@ -197,13 +198,13 @@ int pacman_upgrade(alpm_list_t *targets)  		}  		FREELIST(data);  		trans_release(); -		return(1); +		return 1;  	}  	if(trans_release() == -1) {  		retval = 1;  	} -	return(retval); +	return retval;  }  /* vim: set ts=2 sw=2 noet: */ diff --git a/src/pacman/util.c b/src/pacman/util.c index 3d268031..8631075f 100644 --- a/src/pacman/util.c +++ b/src/pacman/util.c @@ -31,12 +31,14 @@  #include <stdint.h> /* intmax_t */  #include <string.h>  #include <errno.h> -#include <fcntl.h>  #include <ctype.h>  #include <dirent.h>  #include <unistd.h>  #include <limits.h>  #include <wchar.h> +#ifdef HAVE_TERMIOS_H +#include <termios.h> /* tcflush */ +#endif  #include <alpm.h>  #include <alpm_list.h> @@ -68,9 +70,9 @@ int trans_init(pmtransflag_t flags)  			fprintf(stderr, _("  try running pacman-db-upgrade\n"));  		} -		return(-1); +		return -1;  	} -	return(0); +	return 0;  }  int trans_release(void) @@ -78,28 +80,40 @@ int trans_release(void)  	if(alpm_trans_release() == -1) {  		pm_fprintf(stderr, PM_LOG_ERROR, _("failed to release transaction (%s)\n"),  				alpm_strerrorlast()); -		return(-1); +		return -1;  	} -	return(0); +	return 0;  }  int needs_root(void)  {  	switch(config->op) {  		case PM_OP_DATABASE: -			return(1); +			return 1;  		case PM_OP_UPGRADE:  		case PM_OP_REMOVE: -			return(!config->print); +			return !config->print;  		case PM_OP_SYNC: -			return(config->op_s_clean || config->op_s_sync || +			return (config->op_s_clean || config->op_s_sync ||  					(!config->group && !config->op_s_info && !config->op_q_list &&  					 !config->op_s_search && !config->print));  		default: -			return(0); +			return 0;  	}  } +/* discard unhandled input on the terminal's input buffer */ +static int flush_term_input(void) { +#ifdef HAVE_TCFLUSH +	if(isatty(fileno(stdin))) { +		return(tcflush(fileno(stdin), TCIFLUSH)); +	} +#endif + +	/* fail silently */ +	return 0; +} +  /* gets the current screen column width */  int getcols(void)  { @@ -125,24 +139,24 @@ int rmrf(const char *path)  	DIR *dirp;  	if(!unlink(path)) { -		return(0); +		return 0;  	} else {  		if(errno == ENOENT) { -			return(0); +			return 0;  		} else if(errno == EPERM) {  			/* fallthrough */  		} else if(errno == EISDIR) {  			/* fallthrough */  		} else if(errno == ENOTDIR) { -			return(1); +			return 1;  		} else {  			/* not a directory */ -			return(1); +			return 1;  		}  		dirp = opendir(path);  		if(!dirp) { -			return(1); +			return 1;  		}  		for(dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {  			if(dp->d_ino) { @@ -157,7 +171,7 @@ int rmrf(const char *path)  		if(rmdir(path)) {  			errflag++;  		} -		return(errflag); +		return errflag;  	}  } @@ -170,9 +184,9 @@ const char *mbasename(const char *path)  {  	const char *last = strrchr(path, '/');  	if(last) { -		return(last + 1); +		return last + 1;  	} -	return(path); +	return path;  }  /** Parse the dirname of a program from a path. @@ -187,7 +201,7 @@ char *mdirname(const char *path)  	/* null or empty path */  	if(path == NULL || path == '\0') { -		return(strdup(".")); +		return strdup(".");  	}  	ret = strdup(path); @@ -196,11 +210,11 @@ char *mdirname(const char *path)  	if(last != NULL) {  		/* we found a '/', so terminate our string */  		*last = '\0'; -		return(ret); +		return ret;  	}  	/* no slash found */  	free(ret); -	return(strdup(".")); +	return strdup(".");  }  /* output a string, but wrap words properly with a specified indentation @@ -286,7 +300,7 @@ char *strtrim(char *str)  	if(str == NULL || *str == '\0') {  		/* string is empty, so we're done. */ -		return(str); +		return str;  	}  	while(isspace((unsigned char)*pch)) { @@ -298,7 +312,7 @@ char *strtrim(char *str)  	/* check if there wasn't anything but whitespace in the string. */  	if(*str == '\0') { -		return(str); +		return str;  	}  	pch = (str + (strlen(str) - 1)); @@ -307,7 +321,7 @@ char *strtrim(char *str)  	}  	*++pch = '\0'; -	return(str); +	return str;  }  /* Replace all occurances of 'needle' with 'replace' in 'str', returning @@ -321,7 +335,7 @@ char *strreplace(const char *str, const char *needle, const char *replace)  	size_t newsz;  	if(!str) { -		return(NULL); +		return NULL;  	}  	p = str; @@ -334,7 +348,7 @@ char *strreplace(const char *str, const char *needle, const char *replace)  	/* no occurences of needle found */  	if(!list) { -		return(strdup(str)); +		return strdup(str);  	}  	/* size of new string = size of old string + "number of occurences of needle"  	 * x "size difference between replace and needle" */ @@ -342,7 +356,7 @@ char *strreplace(const char *str, const char *needle, const char *replace)  		alpm_list_count(list) * (replacesz - needlesz);  	newstr = malloc(newsz);  	if(!newstr) { -		return(NULL); +		return NULL;  	}  	*newstr = '\0'; @@ -368,7 +382,7 @@ char *strreplace(const char *str, const char *needle, const char *replace)  	}  	*newp = '\0'; -	return(newstr); +	return newstr;  }  /** Splits a string into a list of strings using the chosen character as @@ -388,7 +402,7 @@ alpm_list_t *strsplit(const char *str, const char splitchar)  	while((str = strchr(str, splitchar))) {  		dup = strndup(prev, (size_t)(str - prev));  		if(dup == NULL) { -			return(NULL); +			return NULL;  		}  		list = alpm_list_add(list, dup); @@ -398,11 +412,11 @@ alpm_list_t *strsplit(const char *str, const char splitchar)  	dup = strdup(prev);  	if(dup == NULL) { -		return(NULL); +		return NULL;  	}  	list = alpm_list_add(list, dup); -	return(list); +	return list;  }  static int string_length(const char *s) @@ -411,7 +425,7 @@ static int string_length(const char *s)  	wchar_t *wcstr;  	if(!s) { -		return(0); +		return 0;  	}  	/* len goes from # bytes -> # chars -> # cols */  	len = strlen(s) + 1; @@ -420,7 +434,7 @@ static int string_length(const char *s)  	len = wcswidth(wcstr, len);  	free(wcstr); -	return(len); +	return len;  }  void string_display(const char *title, const char *string) @@ -440,6 +454,117 @@ void string_display(const char *title, const char *string)  	printf("\n");  } +static void table_print_line(const alpm_list_t *line, +		const alpm_list_t *formats) +{ +	const alpm_list_t *curformat = formats; +	const alpm_list_t *curcell = line; + +	while(curcell && curformat) { +		printf(alpm_list_getdata(curformat), alpm_list_getdata(curcell)); +		curcell = alpm_list_next(curcell); +		curformat = alpm_list_next(curformat); +	} + +	printf("\n"); +} + +/* creates format strings by checking max cell lengths in cols */ +static alpm_list_t *table_create_format(const alpm_list_t *header, +		const alpm_list_t *rows) +{ +	alpm_list_t *longest_str, *longest_strs = NULL; +	alpm_list_t *formats = NULL; +	const alpm_list_t *i, *row, *cell; +	char *str, *formatstr; +	const int padding = 2; +	int colwidth, totalwidth = 0; +	int curcol = 0; + +	/* header determines column count and initial values of longest_strs */ +	for(i = header; i; i = alpm_list_next(i)) { +		longest_strs = alpm_list_add(longest_strs, alpm_list_getdata(i)); +	} + +	/* now find the longest string in each column */ +	for(longest_str = longest_strs; longest_str; +			longest_str = alpm_list_next(longest_str), curcol++) { +		for(i = rows; i; i = alpm_list_next(i)) { +			row = alpm_list_getdata(i); +			cell = alpm_list_nth(row, curcol); +			str = alpm_list_getdata(cell); + +			if(strlen(str) > strlen(alpm_list_getdata(longest_str))) { +				longest_str->data = str; +			} +		} +	} + +	/* now use the column width info to generate format strings */ +	for(i = longest_strs; i; i = alpm_list_next(i)) { +		const char *display; +		colwidth = strlen(alpm_list_getdata(i)) + padding; +		totalwidth += colwidth; + +		/* right align the last column for a cleaner table display */ +		display = (alpm_list_next(i) != NULL) ? "%%-%ds" : "%%%ds"; +		pm_asprintf(&formatstr, display, colwidth); + +		formats = alpm_list_add(formats, formatstr); +	} + +	alpm_list_free(longest_strs); + +	/* return NULL if terminal is not wide enough */ +	if(totalwidth > getcols()) { +		fprintf(stderr, _("insufficient columns available for table display\n")); +		FREELIST(formats); +		return(NULL); +	} + +	return(formats); +} + +/** Displays the list in table format + * + * @param title the tables title + * @param header the column headers. column count is determined by the nr + *               of headers + * @param rows the rows to display as a list of lists of strings. the outer + *             list represents the rows, the inner list the cells (= columns) + * + * @return -1 if not enough terminal cols available, else 0 + */ +int table_display(const char *title, const alpm_list_t *header, +		const alpm_list_t *rows) +{ +	const alpm_list_t *i; +	alpm_list_t *formats; + +	if(rows == NULL || header == NULL) { +		return(0); +	} + +	formats = table_create_format(header, rows); +	if(formats == NULL) { +		return(-1); +	} + +	if(title != NULL) { +		printf("%s\n\n", title); +	} + +	table_print_line(header, formats); +	printf("\n"); + +	for(i = rows; i; i = alpm_list_next(i)) { +		table_print_line(alpm_list_getdata(i), formats); +	} + +	FREELIST(formats); +	return(0); +} +  void list_display(const char *title, const alpm_list_t *list)  {  	const alpm_list_t *i; @@ -464,7 +589,7 @@ void list_display(const char *title, const alpm_list_t *list)  				for (j = 1; j <= len; j++) {  					printf(" ");  				} -			} else if (cols != len) { +			} else if(cols != len) {  				/* 2 spaces are added if this is not the first element on a line. */  				printf("  ");  				cols += 2; @@ -503,20 +628,74 @@ void list_display_linebreak(const char *title, const alpm_list_t *list)  		}  	}  } + +/* creates a header row for use with table_display */ +static alpm_list_t *create_verbose_header(int install) +{ +	alpm_list_t *res = NULL; +	char *str; + +	pm_asprintf(&str, "%s", _("Name")); +	res = alpm_list_add(res, str); +	pm_asprintf(&str, "%s", _("Old Version")); +	res = alpm_list_add(res, str); +	if(install) { +		pm_asprintf(&str, "%s", _("New Version")); +		res = alpm_list_add(res, str); +	} +	pm_asprintf(&str, "%s", _("Size")); +	res = alpm_list_add(res, str); + +	return(res); +} + +/* returns package info as list of strings */ +static alpm_list_t *create_verbose_row(pmpkg_t *pkg, int install) +{ +	char *str; +	double size; +	const char *label; +	alpm_list_t *ret = NULL; +	pmdb_t *ldb = alpm_option_get_localdb(); + +	/* a row consists of the package name, */ +	pm_asprintf(&str, "%s", alpm_pkg_get_name(pkg)); +	ret = alpm_list_add(ret, str); + +	/* old and new versions */ +	if(install) { +		pmpkg_t *oldpkg = alpm_db_get_pkg(ldb, alpm_pkg_get_name(pkg)); +		pm_asprintf(&str, "%s", +				oldpkg != NULL ? alpm_pkg_get_version(oldpkg) : ""); +		ret = alpm_list_add(ret, str); +	} + +	pm_asprintf(&str, "%s", alpm_pkg_get_version(pkg)); +	ret = alpm_list_add(ret, str); + +	/* and size */ +	size = humanize_size(alpm_pkg_get_size(pkg), 'M', 1, &label); +	pm_asprintf(&str, "%.2f %s", size, label); +	ret = alpm_list_add(ret, str); + +	return(ret); +} +  /* prepare a list of pkgs to display */  void display_targets(const alpm_list_t *pkgs, int install)  {  	char *str; +	const char *title, *label; +	double size;  	const alpm_list_t *i;  	off_t isize = 0, dlsize = 0; -	double mbisize = 0.0, mbdlsize = 0.0; -	alpm_list_t *targets = NULL; +	alpm_list_t *j, *lp, *header = NULL, *targets = NULL;  	if(!pkgs) {  		return;  	} -	printf("\n"); +	/* gather pkg infos */  	for(i = pkgs; i; i = alpm_list_next(i)) {  		pmpkg_t *pkg = alpm_list_getdata(i); @@ -525,54 +704,69 @@ void display_targets(const alpm_list_t *pkgs, int install)  		}  		isize += alpm_pkg_get_isize(pkg); -		/* print the package size with the output if ShowSize option set */ -		if(config->showsize) { -			double mbsize = (double)alpm_pkg_get_size(pkg) / (1024.0 * 1024.0); - -			pm_asprintf(&str, "%s-%s [%.2f MB]", alpm_pkg_get_name(pkg), -					alpm_pkg_get_version(pkg), mbsize); +		if(config->verbosepkglists) { +			targets = alpm_list_add(targets, create_verbose_row(pkg, install));  		} else {  			pm_asprintf(&str, "%s-%s", alpm_pkg_get_name(pkg),  					alpm_pkg_get_version(pkg)); +			targets = alpm_list_add(targets, str);  		} -		targets = alpm_list_add(targets, str);  	} -	/* Convert byte sizes to MB */ -	mbdlsize = (double)dlsize / (1024.0 * 1024.0); -	mbisize = (double)isize / (1024.0 * 1024.0); +	/* print to screen */ +	title = install ? _("Targets (%d):") : _("Remove (%d):"); +	pm_asprintf(&str, title, alpm_list_count(pkgs)); -	if(install) { -		pm_asprintf(&str, _("Targets (%d):"), alpm_list_count(targets)); +	printf("\n"); +	if(config->verbosepkglists) { +		header = create_verbose_header(install); +		if(table_display(str, header, targets) != 0) { +			config->verbosepkglists = 0; +			display_targets(pkgs, install); +			goto out; +		} +	} else {  		list_display(str, targets); -		free(str); -		printf("\n"); +	} +	printf("\n"); -		printf(_("Total Download Size:    %.2f MB\n"), mbdlsize); +	if(install) { +		size = humanize_size(dlsize, 'M', 1, &label); +		printf(_("Total Download Size:    %.2f %s\n"), size, label);  		if(!(config->flags & PM_TRANS_FLAG_DOWNLOADONLY)) { -			printf(_("Total Installed Size:   %.2f MB\n"), mbisize); +			size = humanize_size(isize, 'M', 1, &label); +			printf(_("Total Installed Size:   %.2f %s\n"), size, label);  		}  	} else { -		pm_asprintf(&str, _("Remove (%d):"), alpm_list_count(targets)); -		list_display(str, targets); -		free(str); -		printf("\n"); - -		printf(_("Total Removed Size:   %.2f MB\n"), mbisize); +		size = humanize_size(isize, 'M', 1, &label); +		printf(_("Total Removed Size:   %.2f %s\n"), size, label);  	} -	FREELIST(targets); +out: +	/* cleanup */ +	if(config->verbosepkglists) { +		/* targets is a list of lists of strings, free inner lists here */ +		for(j = alpm_list_first(targets); j; j = alpm_list_next(j)) { +			lp = alpm_list_getdata(j); +			FREELIST(lp); +		} +		alpm_list_free(targets); +		FREELIST(header); +	} else { +		FREELIST(targets); +	} +	free(str);  }  static off_t pkg_get_size(pmpkg_t *pkg)  {  	switch(config->op) {  		case PM_OP_SYNC: -			return(alpm_pkg_download_size(pkg)); +			return alpm_pkg_download_size(pkg);  		case PM_OP_UPGRADE: -			return(alpm_pkg_get_size(pkg)); +			return alpm_pkg_get_size(pkg);  		default: -			return(alpm_pkg_get_isize(pkg)); +			return alpm_pkg_get_isize(pkg);  	}  } @@ -588,17 +782,55 @@ static char *pkg_get_location(pmpkg_t *pkg)  			if(dburl) {  				char *pkgurl = NULL;  				pm_asprintf(&pkgurl, "%s/%s", dburl, alpm_pkg_get_filename(pkg)); -				return(pkgurl); +				return pkgurl;  			}  		case PM_OP_UPGRADE: -			return(strdup(alpm_pkg_get_filename(pkg))); +			return strdup(alpm_pkg_get_filename(pkg));  		default:  			string = NULL;  			pm_asprintf(&string, "%s-%s", alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg)); -			return(string); +			return string;  	}  } +/** Converts sizes in bytes into human readable units. + * + * @param bytes the size in bytes + * @param target_unit '\0' or a short label. If equal to one of the short unit + * labels ('B', 'K', ...) bytes is converted to target_unit; if '\0', the first + * unit which will bring the value to below a threshold of 2048 will be chosen. + * @param long_labels whether to use short ("K") or long ("KiB") unit labels + * @param label will be set to the appropriate unit label + * + * @return the size in the appropriate unit + */ +double humanize_size(off_t bytes, const char target_unit, int long_labels, +		const char **label) +{ +	static const char *shortlabels[] = {"B", "K", "M", "G", "T", "P"}; +	static const char *longlabels[] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB"}; +	static const int unitcount = sizeof(shortlabels) / sizeof(shortlabels[0]); + +	const char **labels = long_labels ? longlabels : shortlabels; +	double val = (double)bytes; +	int index; + +	for(index = 0; index < unitcount - 1; index++) { +		if(target_unit != '\0' && shortlabels[index][0] == target_unit) { +			break; +		} else if(target_unit == '\0' && val <= 2048.0) { +			break; +		} +		val /= 1024.0; +	} + +	if(label) { +		*label = labels[index]; +	} + +	return(val); +} +  void print_packages(const alpm_list_t *packages)  {  	const alpm_list_t *i; @@ -657,7 +889,7 @@ void print_packages(const alpm_list_t *packages)   * alpm "compare func" signature */  int str_cmp(const void *s1, const void *s2)  { -	return(strcmp(s1, s2)); +	return strcmp(s1, s2);  }  void display_new_optdepends(pmpkg_t *oldpkg, pmpkg_t *newpkg) @@ -726,13 +958,13 @@ static int parseindex(char *s, int *val, int min, int max)  		if(n < min || n > max) {  			fprintf(stderr, _("Invalid value: %d is not between %d and %d\n"),  					n, min, max); -			return(-1); +			return -1;  		}  		*val = n; -		return(0); +		return 0;  	} else {  		fprintf(stderr, _("Invalid number: %s\n"), s); -		return(-1); +		return -1;  	}  } @@ -746,7 +978,7 @@ static int multiselect_parse(char *array, int count, char *response)  		char *ends = NULL;  		char *starts = strtok_r(str, " ", &saveptr); -		if (starts == NULL) { +		if(starts == NULL) {  			break;  		}  		strtrim(starts); @@ -754,7 +986,7 @@ static int multiselect_parse(char *array, int count, char *response)  		if(len == 0)  			continue; -		if (*starts == '^') { +		if(*starts == '^') {  			starts++;  			len--;  			include = 0; @@ -773,14 +1005,14 @@ static int multiselect_parse(char *array, int count, char *response)  		}  		if(parseindex(starts, &start, 1, count) != 0) -			return(-1); +			return -1;  		if(!ends) {  			array[start-1] = include;  		} else {  			int d;  			if(parseindex(ends, &end, start, count) != 0) { -				return(-1); +				return -1;  			}  			for(d = start; d <= end; d++) {  				array[d-1] = include; @@ -788,7 +1020,7 @@ static int multiselect_parse(char *array, int count, char *response)  		}  	} -	return(0); +	return 0;  }  int multiselect_question(char *array, int count) @@ -815,6 +1047,8 @@ int multiselect_question(char *array, int count)  			break;  		} +		flush_term_input(); +  		if(fgets(response, sizeof(response), stdin)) {  			strtrim(response);  			if(strlen(response) > 0) { @@ -826,7 +1060,7 @@ int multiselect_question(char *array, int count)  		}  		break;  	} -	return(0); +	return 0;  }  int select_question(int count) @@ -852,19 +1086,21 @@ int select_question(int count)  			break;  		} +		flush_term_input(); +  		if(fgets(response, sizeof(response), stdin)) {  			strtrim(response);  			if(strlen(response) > 0) {  				int n;  				if(parseindex(response, &n, 1, count) != 0)  					continue; -				return(n-1); +				return (n - 1);  			}  		}  		break;  	} -	return(preset-1); +	return (preset - 1);  } @@ -895,23 +1131,25 @@ static int question(short preset, char *fmt, va_list args)  	if(config->noconfirm) {  		fprintf(stream, "\n"); -		return(preset); +		return preset;  	}  	fflush(stream); +	flush_term_input(); +  	if(fgets(response, sizeof(response), stdin)) {  		strtrim(response);  		if(strlen(response) == 0) { -			return(preset); +			return preset;  		}  		if(strcasecmp(response, _("Y")) == 0 || strcasecmp(response, _("YES")) == 0) { -			return(1); -		} else if (strcasecmp(response, _("N")) == 0 || strcasecmp(response, _("NO")) == 0) { -			return(0); +			return 1; +		} else if(strcasecmp(response, _("N")) == 0 || strcasecmp(response, _("NO")) == 0) { +			return 0;  		}  	} -	return(0); +	return 0;  }  int yesno(char *fmt, ...) @@ -923,7 +1161,7 @@ int yesno(char *fmt, ...)  	ret = question(1, fmt, args);  	va_end(args); -	return(ret); +	return ret;  }  int noyes(char *fmt, ...) @@ -935,7 +1173,7 @@ int noyes(char *fmt, ...)  	ret = question(0, fmt, args);  	va_end(args); -	return(ret); +	return ret;  }  int pm_printf(pmloglevel_t level, const char *format, ...) @@ -948,7 +1186,7 @@ int pm_printf(pmloglevel_t level, const char *format, ...)  	ret = pm_vfprintf(stdout, level, format, args);  	va_end(args); -	return(ret); +	return ret;  }  int pm_fprintf(FILE *stream, pmloglevel_t level, const char *format, ...) @@ -961,7 +1199,7 @@ int pm_fprintf(FILE *stream, pmloglevel_t level, const char *format, ...)  	ret = pm_vfprintf(stream, level, format, args);  	va_end(args); -	return(ret); +	return ret;  }  int pm_asprintf(char **string, const char *format, ...) @@ -977,7 +1215,7 @@ int pm_asprintf(char **string, const char *format, ...)  	}  	va_end(args); -	return(ret); +	return ret;  }  int pm_vasprintf(char **string, pmloglevel_t level, const char *format, va_list args) @@ -1013,7 +1251,7 @@ int pm_vasprintf(char **string, pmloglevel_t level, const char *format, va_list  	}  	free(msg); -	return(ret); +	return ret;  }  int pm_vfprintf(FILE *stream, pmloglevel_t level, const char *format, va_list args) @@ -1061,7 +1299,7 @@ int pm_vfprintf(FILE *stream, pmloglevel_t level, const char *format, va_list ar  	/* print the message using va_arg list */  	ret = vfprintf(stream, format, args); -	return(ret); +	return ret;  }  #ifndef HAVE_STRNDUP @@ -1070,7 +1308,7 @@ static size_t strnlen(const char *s, size_t max)  {      register const char *p;      for(p = s; *p && max--; ++p); -    return(p - s); +    return (p - s);  }  char *strndup(const char *s, size_t n) @@ -1078,11 +1316,11 @@ char *strndup(const char *s, size_t n)    size_t len = strnlen(s, n);    char *new = (char *) malloc(len + 1); -  if (new == NULL) +  if(new == NULL)      return NULL;    new[len] = '\0'; -  return (char *) memcpy(new, s, len); +  return (char *)memcpy(new, s, len);  }  #endif diff --git a/src/pacman/util.h b/src/pacman/util.h index 234a631d..d8ae7d80 100644 --- a/src/pacman/util.h +++ b/src/pacman/util.h @@ -52,6 +52,8 @@ char *strtrim(char *str);  char *strreplace(const char *str, const char *needle, const char *replace);  alpm_list_t *strsplit(const char *str, const char splitchar);  void string_display(const char *title, const char *string); +double humanize_size(off_t bytes, const char target_unit, int long_labels, const char **label); +int table_display(const char *title, const alpm_list_t *header, const alpm_list_t *rows);  void list_display(const char *title, const alpm_list_t *list);  void list_display_linebreak(const char *title, const alpm_list_t *list);  void display_targets(const alpm_list_t *pkgs, int install); | 
