summaryrefslogtreecommitdiff
path: root/src/pacman
diff options
context:
space:
mode:
Diffstat (limited to 'src/pacman')
-rw-r--r--src/pacman/callback.c26
-rw-r--r--src/pacman/conf.h20
-rw-r--r--src/pacman/pacman.c465
-rw-r--r--src/pacman/remove.c85
-rw-r--r--src/pacman/sync.c216
-rw-r--r--src/pacman/upgrade.c82
-rw-r--r--src/pacman/util.c222
-rw-r--r--src/pacman/util.h4
8 files changed, 611 insertions, 509 deletions
diff --git a/src/pacman/callback.c b/src/pacman/callback.c
index 1cdb1153..858bfdf4 100644
--- a/src/pacman/callback.c
+++ b/src/pacman/callback.c
@@ -259,10 +259,20 @@ void cb_trans_conv(pmtransconv_t event, void *data1, void *data2,
alpm_pkg_get_name(data2));
break;
case PM_TRANS_CONV_CONFLICT_PKG:
- *response = yesno(_(":: %s conflicts with %s. Remove %s?"),
- (char *)data1,
- (char *)data2,
- (char *)data2);
+ /* data parameters: target package, local package, conflict (strings) */
+ /* print conflict only if it contains new information */
+ if(!strcmp(data1, data3) || !strcmp(data2, data3)) {
+ *response = noyes(_(":: %s and %s are in conflict. Remove %s?"),
+ (char *)data1,
+ (char *)data2,
+ (char *)data2);
+ } else {
+ *response = noyes(_(":: %s and %s are in conflict (%s). Remove %s?"),
+ (char *)data1,
+ (char *)data2,
+ (char *)data3,
+ (char *)data2);
+ }
break;
case PM_TRANS_CONV_REMOVE_PKGS:
{
@@ -275,7 +285,7 @@ void cb_trans_conv(pmtransconv_t event, void *data1, void *data2,
printf(_(":: the following package(s) cannot be upgraded due to "
"unresolvable dependencies:\n"));
list_display(" ", namelist);
- *response = yesno(_("\nDo you want to skip the above "
+ *response = noyes(_("\nDo you want to skip the above "
"package(s) for this upgrade?"));
alpm_list_free(namelist);
}
@@ -294,6 +304,12 @@ void cb_trans_conv(pmtransconv_t event, void *data1, void *data2,
(char *)data1);
break;
}
+ if(config->noask) {
+ if(config->ask & event) {
+ /* inverse the default answer */
+ *response = !*response;
+ }
+ }
}
/* callback to handle display of transaction progress */
diff --git a/src/pacman/conf.h b/src/pacman/conf.h
index 2d3de987..c97e5d78 100644
--- a/src/pacman/conf.h
+++ b/src/pacman/conf.h
@@ -63,6 +63,8 @@ typedef struct __config_t {
unsigned short group;
pmtransflag_t flags;
+ unsigned short noask;
+ unsigned int ask;
/* conf file options */
unsigned short chomp; /* I Love Candy! */
@@ -86,6 +88,24 @@ enum {
PM_OP_DEPTEST
};
+/* Long Operations */
+enum {
+ OP_NOCONFIRM = 1000,
+ OP_CONFIG,
+ OP_IGNORE,
+ OP_DEBUG,
+ OP_NOPROGRESSBAR,
+ OP_NOSCRIPTLET,
+ OP_ASK,
+ OP_CACHEDIR,
+ OP_ASDEPS,
+ OP_LOGFILE,
+ OP_IGNOREGROUP,
+ OP_NEEDED,
+ OP_ASEXPLICIT,
+ OP_ARCH
+};
+
/* clean method */
enum {
PM_CLEAN_KEEPINST = 0, /* default */
diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c
index 4c556a7d..0e80fb22 100644
--- a/src/pacman/pacman.c
+++ b/src/pacman/pacman.c
@@ -34,6 +34,7 @@
#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 */
@@ -149,6 +150,7 @@ static void usage(int op, const char * const myname)
printf(_(" -r, --root <path> set an alternate installation root\n"));
printf(_(" -b, --dbpath <path> set an alternate database location\n"));
printf(_(" --cachedir <dir> set an alternate package cache location\n"));
+ printf(_(" --arch <arch> set an alternate architecture\n"));
}
}
@@ -195,6 +197,19 @@ 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
@@ -220,7 +235,9 @@ static void cleanup(int ret) {
static ssize_t xwrite(int fd, const void *buf, size_t count)
{
ssize_t ret;
- while((ret = write(fd, buf, count)) == -1 && errno == EINTR);
+ do {
+ ret = write(fd, buf, count);
+ } while(ret == -1 && errno == EINTR);
return(ret);
}
@@ -317,6 +334,8 @@ static void setlibpaths(void)
}
}
+#define check_optarg() if(!optarg) { return(1); }
+
/** Parse command-line arguments for each operation.
* @param argc argc
* @param argv argv
@@ -364,18 +383,20 @@ static int parseargs(int argc, char *argv[])
{"verbose", no_argument, 0, 'v'},
{"downloadonly", no_argument, 0, 'w'},
{"refresh", no_argument, 0, 'y'},
- {"noconfirm", no_argument, 0, 1000},
- {"config", required_argument, 0, 1001},
- {"ignore", required_argument, 0, 1002},
- {"debug", optional_argument, 0, 1003},
- {"noprogressbar", no_argument, 0, 1004},
- {"noscriptlet", no_argument, 0, 1005},
- {"cachedir", required_argument, 0, 1007},
- {"asdeps", no_argument, 0, 1008},
- {"logfile", required_argument, 0, 1009},
- {"ignoregroup", required_argument, 0, 1010},
- {"needed", no_argument, 0, 1011},
- {"asexplicit", no_argument, 0, 1012},
+ {"noconfirm", no_argument, 0, OP_NOCONFIRM},
+ {"config", required_argument, 0, OP_CONFIG},
+ {"ignore", required_argument, 0, OP_IGNORE},
+ {"debug", optional_argument, 0, OP_DEBUG},
+ {"noprogressbar", no_argument, 0, OP_NOPROGRESSBAR},
+ {"noscriptlet", no_argument, 0, OP_NOSCRIPTLET},
+ {"ask", required_argument, 0, OP_ASK},
+ {"cachedir", required_argument, 0, OP_CACHEDIR},
+ {"asdeps", no_argument, 0, OP_ASDEPS},
+ {"logfile", required_argument, 0, OP_LOGFILE},
+ {"ignoregroup", required_argument, 0, OP_IGNOREGROUP},
+ {"needed", no_argument, 0, OP_NEEDED},
+ {"asexplicit", no_argument, 0, OP_ASEXPLICIT},
+ {"arch", required_argument, 0, OP_ARCH},
{0, 0, 0, 0}
};
@@ -387,21 +408,23 @@ static int parseargs(int argc, char *argv[])
}
switch(opt) {
case 0: break;
- case 1000: config->noconfirm = 1; break;
- case 1001:
+ case OP_NOCONFIRM: config->noconfirm = 1; break;
+ case OP_CONFIG:
+ check_optarg();
if(config->configfile) {
free(config->configfile);
}
config->configfile = strndup(optarg, PATH_MAX);
break;
- case 1002:
+ case OP_IGNORE:
+ check_optarg();
list = strsplit(optarg, ',');
for(item = list; item; item = alpm_list_next(item)) {
alpm_option_add_ignorepkg((char *)alpm_list_getdata(item));
}
FREELIST(list);
break;
- case 1003:
+ case OP_DEBUG:
/* debug levels are made more 'human readable' than using a raw logmask
* here, error and warning are set in config_new, though perhaps a
* --quiet option will remove these later */
@@ -424,32 +447,44 @@ static int parseargs(int argc, char *argv[])
/* progress bars get wonky with debug on, shut them off */
config->noprogressbar = 1;
break;
- case 1004: config->noprogressbar = 1; break;
- case 1005: config->flags |= PM_TRANS_FLAG_NOSCRIPTLET; break;
- case 1007:
+ case OP_NOPROGRESSBAR: config->noprogressbar = 1; break;
+ case OP_NOSCRIPTLET: config->flags |= PM_TRANS_FLAG_NOSCRIPTLET; break;
+ case OP_ASK:
+ check_optarg();
+ config->noask = 1;
+ config->ask = atoi(optarg);
+ break;
+ case OP_CACHEDIR:
+ check_optarg();
if(alpm_option_add_cachedir(optarg) != 0) {
pm_printf(PM_LOG_ERROR, _("problem adding cachedir '%s' (%s)\n"),
optarg, alpm_strerrorlast());
return(1);
}
break;
- case 1008:
+ case OP_ASDEPS:
config->flags |= PM_TRANS_FLAG_ALLDEPS;
break;
- case 1009:
+ case OP_LOGFILE:
+ check_optarg();
config->logfile = strndup(optarg, PATH_MAX);
break;
- case 1010:
+ case OP_IGNOREGROUP:
+ check_optarg();
list = strsplit(optarg, ',');
for(item = list; item; item = alpm_list_next(item)) {
alpm_option_add_ignoregrp((char *)alpm_list_getdata(item));
}
FREELIST(list);
break;
- case 1011: config->flags |= PM_TRANS_FLAG_NEEDED; break;
- case 1012:
+ case OP_NEEDED: config->flags |= PM_TRANS_FLAG_NEEDED; break;
+ case OP_ASEXPLICIT:
config->flags |= PM_TRANS_FLAG_ALLEXPLICIT;
break;
+ case OP_ARCH:
+ check_optarg();
+ setarch(optarg);
+ break;
case 'Q': config->op = (config->op != PM_OP_MAIN ? 0 : PM_OP_QUERY); break;
case 'R': config->op = (config->op != PM_OP_MAIN ? 0 : PM_OP_REMOVE); break;
case 'S': config->op = (config->op != PM_OP_MAIN ? 0 : PM_OP_SYNC); break;
@@ -457,6 +492,7 @@ static int parseargs(int argc, char *argv[])
case 'U': config->op = (config->op != PM_OP_MAIN ? 0 : PM_OP_UPGRADE); break;
case 'V': config->version = 1; break;
case 'b':
+ check_optarg();
config->dbpath = strdup(optarg);
break;
case 'c':
@@ -493,6 +529,7 @@ static int parseargs(int argc, char *argv[])
config->quiet = 1;
break;
case 'r':
+ check_optarg();
config->rootdir = strdup(optarg);
break;
case 's':
@@ -592,7 +629,7 @@ static char *get_filename(const char *url) {
static char *get_destfile(const char *path, const char *filename) {
char *destfile;
/* len = localpath len + filename len + null */
- int len = strlen(path) + strlen(filename) + 1;
+ size_t len = strlen(path) + strlen(filename) + 1;
destfile = calloc(len, sizeof(char));
snprintf(destfile, len, "%s%s", path, filename);
@@ -602,7 +639,7 @@ static char *get_destfile(const char *path, const char *filename) {
static char *get_tempfile(const char *path, const char *filename) {
char *tempfile;
/* len = localpath len + filename len + '.part' len + null */
- int len = strlen(path) + strlen(filename) + 6;
+ size_t len = strlen(path) + strlen(filename) + 6;
tempfile = calloc(len, sizeof(char));
snprintf(tempfile, len, "%s%s.part", path, filename);
@@ -611,13 +648,12 @@ static char *get_tempfile(const char *path, const char *filename) {
/** External fetch callback */
int download_with_xfercommand(const char *url, const char *localpath,
- time_t mtimeold, time_t *mtimenew) {
+ int force) {
int ret = 0;
int retval;
int usepart = 0;
- char *ptr1, *ptr2;
- char origCmd[PATH_MAX];
- char parsedCmd[PATH_MAX] = "";
+ struct stat st;
+ char *parsedcmd,*tempcmd;
char cwd[PATH_MAX];
char *destfile, *tempfile, *filename;
@@ -632,28 +668,25 @@ int download_with_xfercommand(const char *url, const char *localpath,
destfile = get_destfile(localpath, filename);
tempfile = get_tempfile(localpath, filename);
- strncpy(origCmd, config->xfercommand, sizeof(origCmd));
+ 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 */
- ptr1 = origCmd;
- while((ptr2 = strstr(ptr1, "%o"))) {
+ if(strstr(tempcmd, "%o")) {
usepart = 1;
- ptr2[0] = '\0';
- strcat(parsedCmd, ptr1);
- strcat(parsedCmd, tempfile);
- ptr1 = ptr2 + 2;
+ parsedcmd = strreplace(tempcmd, "%o", tempfile);
+ free(tempcmd);
+ tempcmd = parsedcmd;
}
- strcat(parsedCmd, ptr1);
/* replace all occurrences of %u with the download URL */
- strncpy(origCmd, parsedCmd, sizeof(origCmd));
- parsedCmd[0] = '\0';
- ptr1 = origCmd;
- while((ptr2 = strstr(ptr1, "%u"))) {
- ptr2[0] = '\0';
- strcat(parsedCmd, ptr1);
- strcat(parsedCmd, url);
- ptr1 = ptr2 + 2;
- }
- strcat(parsedCmd, ptr1);
+ parsedcmd = strreplace(tempcmd, "%u", url);
+ free(tempcmd);
+
/* cwd to the download directory */
getcwd(cwd, PATH_MAX);
if(chdir(localpath)) {
@@ -662,8 +695,8 @@ int download_with_xfercommand(const char *url, const char *localpath,
goto cleanup;
}
/* execute the parsed command via /bin/sh -c */
- pm_printf(PM_LOG_DEBUG, "running command: %s\n", parsedCmd);
- retval = system(parsedCmd);
+ 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"));
@@ -689,10 +722,132 @@ cleanup:
}
free(destfile);
free(tempfile);
+ free(parsedcmd);
return(ret);
}
+static int _parse_options(char *key, char *value)
+{
+ 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 {
+ pm_printf(PM_LOG_ERROR, _("directive '%s' without value not recognized\n"), key);
+ return(1);
+ }
+ } 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) {
+ 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(1);
+ }
+ pm_printf(PM_LOG_DEBUG, "config: cleanmethod: %s\n", value);
+ } else {
+ pm_printf(PM_LOG_ERROR, _("directive '%s' with a value not recognized\n"), key);
+ return(1);
+ }
+
+ }
+ 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,
@@ -749,11 +904,8 @@ static int _parseconfig(const char *file, const char *givensection,
ret = 1;
goto cleanup;
}
- /* if we are not looking at the options section, register a db and also
- * ensure we have set all of our library paths as the library is too stupid
- * at the moment to do lazy opening of the databases */
+ /* if we are not looking at the options section, register a db */
if(strcmp(section, "options") != 0) {
- setlibpaths();
db = alpm_db_register_sync(section);
if(db == NULL) {
pm_printf(PM_LOG_ERROR, _("could not register '%s' database (%s)\n"),
@@ -762,142 +914,70 @@ static int _parseconfig(const char *file, const char *givensection,
goto cleanup;
}
}
- } else {
- /* directive */
- char *key;
- /* strsep modifies the 'line' string: 'key \0 ptr' */
- key = line;
- ptr = line;
- strsep(&ptr, "=");
- strtrim(key);
- strtrim(ptr);
+ continue;
+ }
- 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"),
+ /* 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;
+ }
+ if(strcmp(section, "options") == 0) {
+ if((ret = _parse_options(key, value)) != 0) {
+ pm_printf(PM_LOG_ERROR, _("config file %s, line %d: problem in options section\n"),
file, linenum);
ret = 1;
goto cleanup;
}
- if(ptr == NULL && strcmp(section, "options") == 0) {
- /* directives without settings, all in [options] */
- if(strcmp(key, "NoPassiveFtp") == 0) {
- alpm_option_set_nopassiveftp(1);
- pm_printf(PM_LOG_DEBUG, "config: nopassiveftp\n");
- } else 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 {
- pm_printf(PM_LOG_ERROR, _("config file %s, line %d: directive '%s' not recognized.\n"),
+ continue;
+ } else {
+ /* we are in a repo section */
+ 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;
}
- } else {
- /* directives with settings */
- if(strcmp(key, "Include") == 0) {
- pm_printf(PM_LOG_DEBUG, "config: including %s\n", ptr);
- _parseconfig(ptr, section, db);
- /* Ignore include failures... assume non-critical */
- } else if(strcmp(section, "options") == 0) {
- if(strcmp(key, "NoUpgrade") == 0) {
- setrepeatingoption(ptr, "NoUpgrade", alpm_option_add_noupgrade);
- } else if(strcmp(key, "NoExtract") == 0) {
- setrepeatingoption(ptr, "NoExtract", alpm_option_add_noextract);
- } else if(strcmp(key, "IgnorePkg") == 0) {
- setrepeatingoption(ptr, "IgnorePkg", alpm_option_add_ignorepkg);
- } else if(strcmp(key, "IgnoreGroup") == 0) {
- setrepeatingoption(ptr, "IgnoreGroup", alpm_option_add_ignoregrp);
- } else if(strcmp(key, "HoldPkg") == 0) {
- setrepeatingoption(ptr, "HoldPkg", option_add_holdpkg);
- } else if(strcmp(key, "SyncFirst") == 0) {
- setrepeatingoption(ptr, "SyncFirst", option_add_syncfirst);
- } else if(strcmp(key, "DBPath") == 0) {
- /* don't overwrite a path specified on the command line */
- if(!config->dbpath) {
- config->dbpath = strdup(ptr);
- pm_printf(PM_LOG_DEBUG, "config: dbpath: %s\n", ptr);
- }
- } else if(strcmp(key, "CacheDir") == 0) {
- if(alpm_option_add_cachedir(ptr) != 0) {
- pm_printf(PM_LOG_ERROR, _("problem adding cachedir '%s' (%s)\n"),
- ptr, alpm_strerrorlast());
- ret = 1;
- goto cleanup;
- }
- pm_printf(PM_LOG_DEBUG, "config: cachedir: %s\n", ptr);
- } else if(strcmp(key, "RootDir") == 0) {
- /* don't overwrite a path specified on the command line */
- if(!config->rootdir) {
- config->rootdir = strdup(ptr);
- pm_printf(PM_LOG_DEBUG, "config: rootdir: %s\n", ptr);
- }
- } else if (strcmp(key, "LogFile") == 0) {
- if(!config->logfile) {
- config->logfile = strdup(ptr);
- pm_printf(PM_LOG_DEBUG, "config: logfile: %s\n", ptr);
- }
- } else if (strcmp(key, "XferCommand") == 0) {
- config->xfercommand = strdup(ptr);
- alpm_option_set_fetchcb(download_with_xfercommand);
- pm_printf(PM_LOG_DEBUG, "config: xfercommand: %s\n", ptr);
- } else if (strcmp(key, "CleanMethod") == 0) {
- if (strcmp(ptr, "KeepInstalled") == 0) {
- config->cleanmethod = PM_CLEAN_KEEPINST;
- } else if (strcmp(ptr, "KeepCurrent") == 0) {
- config->cleanmethod = PM_CLEAN_KEEPCUR;
- } else {
- pm_printf(PM_LOG_ERROR, _("invalid value for 'CleanMethod' : '%s'\n"), ptr);
- ret = 1;
- goto cleanup;
- }
- pm_printf(PM_LOG_DEBUG, "config: cleanmethod: %s\n", ptr);
- } else {
- pm_printf(PM_LOG_ERROR, _("config file %s, line %d: directive '%s' not recognized.\n"),
- file, linenum, key);
- ret = 1;
- goto cleanup;
- }
- } else if(strcmp(key, "Server") == 0) {
- /* let's attempt a replacement for the current repo */
- char *server = strreplace(ptr, "$repo", section);
-
- 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"),
- alpm_db_get_name(db), server, alpm_strerrorlast());
- free(server);
- ret = 1;
- goto cleanup;
- }
-
- free(server);
- } else {
- pm_printf(PM_LOG_ERROR, _("config file %s, line %d: directive '%s' not recognized.\n"),
+ pm_printf(PM_LOG_DEBUG, "config: including %s\n", value);
+ _parseconfig(value, section, db);
+ /* Ignore include failures... assume non-critical */
+ } else 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_ERROR, _("config file %s, line %d: directive '%s' in repository section '%s' not recognized.\n"),
+ file, linenum, key, section);
+ ret = 1;
+ goto cleanup;
}
}
+
}
cleanup:
@@ -923,6 +1003,29 @@ static int parseconfig(const char *file)
return(_parseconfig(file, NULL, NULL));
}
+/** print commandline to logfile
+ */
+static void cl_to_log(int argc, char* argv[])
+{
+ size_t size = 0;
+ int i;
+ for(i = 0; i<argc; i++) {
+ size += strlen(argv[i]) + 1;
+ }
+ char *cl_text = malloc(size);
+ if(!cl_text)
+ return;
+ char *p = cl_text;
+ for(i = 0; i<argc-1; i++) {
+ strcpy(p, argv[i]);
+ p += strlen(argv[i]);
+ *p++ = ' ';
+ }
+ strcpy(p, argv[i]);
+ alpm_logaction("Running '%s'\n", cl_text);
+ free(cl_text);
+}
+
/** Main function.
* @param argc argc
* @param argv argv
@@ -1018,6 +1121,11 @@ int main(int argc, char *argv[])
alpm_option_set_totaldlcb(cb_dl_total);
}
+ /* noask is meant to be non-interactive */
+ if(config->noask) {
+ config->noconfirm = 1;
+ }
+
#if defined(HAVE_GETEUID) && !defined(CYGWIN)
/* check if we have sufficient permission for the requested operation */
if(myuid > 0 && needs_root()) {
@@ -1049,6 +1157,11 @@ int main(int argc, char *argv[])
cleanup(EXIT_FAILURE);
}
+ /* Log commandline */
+ if(needs_root()) {
+ cl_to_log(argc, argv);
+ }
+
/* start the requested operation */
switch(config->op) {
case PM_OP_REMOVE:
diff --git a/src/pacman/remove.c b/src/pacman/remove.c
index 0efbd94e..6d44350b 100644
--- a/src/pacman/remove.c
+++ b/src/pacman/remove.c
@@ -51,50 +51,23 @@ int pacman_remove(alpm_list_t *targets)
}
/* Step 0: create a new transaction */
- if(trans_init(PM_TRANS_TYPE_REMOVE, config->flags) == -1) {
+ if(trans_init(config->flags) == -1) {
return(1);
}
/* Step 1: add targets to the created transaction */
for(i = targets; i; i = alpm_list_next(i)) {
- char *targ = alpm_list_getdata(i);
- if(alpm_trans_addtarget(targ) == -1) {
- if(pm_errno == PM_ERR_PKG_NOT_FOUND) {
- printf(_("%s not found, searching for group...\n"), targ);
- pmgrp_t *grp = alpm_db_readgrp(db_local, targ);
- if(grp == NULL) {
- pm_fprintf(stderr, PM_LOG_ERROR, _("'%s': not found in local db\n"), targ);
- retval = 1;
- goto cleanup;
- } else {
- alpm_list_t *p, *pkgnames = NULL;
- /* convert packages to package names */
- for(p = alpm_grp_get_pkgs(grp); p; p = alpm_list_next(p)) {
- pmpkg_t *pkg = alpm_list_getdata(p);
- pkgnames = alpm_list_add(pkgnames, (void *)alpm_pkg_get_name(pkg));
- }
- printf(_(":: group %s:\n"), targ);
- list_display(" ", pkgnames);
- int all = yesno(_(" Remove whole content?"));
- for(p = pkgnames; p; p = alpm_list_next(p)) {
- char *pkgn = alpm_list_getdata(p);
- if(all || yesno(_(":: Remove %s from group %s?"), pkgn, targ)) {
- if(alpm_trans_addtarget(pkgn) == -1) {
- pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", targ,
- alpm_strerrorlast());
- retval = 1;
- alpm_list_free(pkgnames);
- goto cleanup;
- }
- }
- }
- alpm_list_free(pkgnames);
- }
- } else {
- pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", targ, alpm_strerrorlast());
- retval = 1;
- goto cleanup;
- }
+ char *target = alpm_list_getdata(i);
+ char *targ = strchr(target, '/');
+ if(targ && strncmp(target, "local", 5) == 0) {
+ targ++;
+ } else {
+ targ = target;
+ }
+ if(alpm_remove_target(targ) == -1) {
+ pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", targ, alpm_strerrorlast());
+ retval = 1;
+ goto cleanup;
}
}
@@ -103,6 +76,12 @@ int pacman_remove(alpm_list_t *targets)
pm_fprintf(stderr, PM_LOG_ERROR, _("failed to prepare transaction (%s)\n"),
alpm_strerrorlast());
switch(pm_errno) {
+ case PM_ERR_PKG_INVALID_ARCH:
+ for(i = data; i; i = alpm_list_next(i)) {
+ char *pkg = alpm_list_getdata(i);
+ printf(_(":: package %s does not have a valid architecture\n"), pkg);
+ }
+ break;
case PM_ERR_UNSATISFIED_DEPS:
for(i = data; i; i = alpm_list_next(i)) {
pmdepmissing_t *miss = alpm_list_getdata(i);
@@ -123,7 +102,7 @@ int pacman_remove(alpm_list_t *targets)
/* Search for holdpkg in target list */
int holdpkg = 0;
- for(i = alpm_trans_get_pkgs(); i; i = alpm_list_next(i)) {
+ for(i = alpm_trans_get_remove(); i; i = alpm_list_next(i)) {
pmpkg_t *pkg = alpm_list_getdata(i);
if(alpm_list_find_str(config->holdpkg, alpm_pkg_get_name(pkg))) {
pm_printf(PM_LOG_WARNING, _("%s is designated as a HoldPkg.\n"),
@@ -136,23 +115,19 @@ int pacman_remove(alpm_list_t *targets)
goto cleanup;
}
- /* Warn user in case of dangerous operation */
- if(config->flags & PM_TRANS_FLAG_RECURSE ||
- config->flags & PM_TRANS_FLAG_CASCADE) {
- /* list transaction targets */
- alpm_list_t *pkglist = alpm_trans_get_pkgs();
-
- display_targets(pkglist, 0);
- printf("\n");
-
- /* get confirmation */
- if(yesno(_("Do you want to remove these packages?")) == 0) {
- retval = 1;
- goto cleanup;
- }
+ /* Step 3: actually perform the removal */
+ alpm_list_t *pkglist = alpm_trans_get_remove();
+ if(pkglist == NULL) {
+ goto cleanup; /* we are done */
+ }
+ /* print targets and ask user confirmation */
+ display_targets(pkglist, 0);
+ printf("\n");
+ if(yesno(_("Do you want to remove these packages?")) == 0) {
+ retval = 1;
+ goto cleanup;
}
- /* Step 3: actually perform the removal */
if(alpm_trans_commit(NULL) == -1) {
pm_fprintf(stderr, PM_LOG_ERROR, _("failed to commit transaction (%s)\n"),
alpm_strerrorlast());
diff --git a/src/pacman/sync.c b/src/pacman/sync.c
index 12f67df2..a2ef616d 100644
--- a/src/pacman/sync.c
+++ b/src/pacman/sync.c
@@ -93,18 +93,21 @@ static int sync_cleandb(const char *dbpath, int keep_used) {
if(rmrf(path)) {
pm_fprintf(stderr, PM_LOG_ERROR,
_("could not remove repository directory\n"));
+ closedir(dir);
return(1);
}
}
-
}
+ closedir(dir);
return(0);
}
static int sync_cleandb_all(void) {
- const char *dbpath = alpm_option_get_dbpath();
+ const char *dbpath;
char newdbpath[PATH_MAX];
+ int ret = 0;
+ dbpath = alpm_option_get_dbpath();
printf(_("Database directory: %s\n"), dbpath);
if(!yesno(_("Do you want to remove unused repositories?"))) {
return(0);
@@ -112,28 +115,26 @@ static int sync_cleandb_all(void) {
/* The sync dbs were previously put in dbpath/, but are now in dbpath/sync/,
* so we will clean everything in dbpath/ (except dbpath/local/ and dbpath/sync/,
* and only the unused sync dbs in dbpath/sync/ */
- sync_cleandb(dbpath, 0);
+ ret += sync_cleandb(dbpath, 0);
sprintf(newdbpath, "%s%s", dbpath, "sync/");
- sync_cleandb(newdbpath, 1);
+ ret += sync_cleandb(newdbpath, 1);
printf(_("Database directory cleaned up\n"));
- return(0);
+ return(ret);
}
static int sync_cleancache(int level)
{
- /* TODO for now, just mess with the first cache directory */
- alpm_list_t* cachedirs = alpm_option_get_cachedirs();
- const char *cachedir = alpm_list_getdata(cachedirs);
+ alpm_list_t *i;
+ alpm_list_t *sync_dbs = alpm_option_get_syncdbs();
+ 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));
+ }
if(level == 1) {
- /* incomplete cleanup */
- DIR *dir;
- struct dirent *ent;
- /* Open up each package and see if it should be deleted,
- * depending on the clean method used */
- printf(_("Cache directory: %s\n"), cachedir);
switch(config->cleanmethod) {
case PM_CLEAN_KEEPINST:
if(!yesno(_("Do you want to remove uninstalled packages from cache?"))) {
@@ -150,11 +151,23 @@ static int sync_cleancache(int level)
return(1);
}
printf(_("removing old packages from cache...\n"));
+ } else {
+ if(!noyes(_("Do you want to remove ALL files from cache?"))) {
+ return(0);
+ }
+ printf(_("removing all files from cache...\n"));
+ }
+
+ for(i = alpm_option_get_cachedirs(); i; i = alpm_list_next(i)) {
+ const char *cachedir = alpm_list_getdata(i);
+ DIR *dir = opendir(cachedir);
+ struct dirent *ent;
- dir = opendir(cachedir);
if(dir == NULL) {
- pm_fprintf(stderr, PM_LOG_ERROR, _("could not access cache directory\n"));
- return(1);
+ pm_fprintf(stderr, PM_LOG_ERROR,
+ _("could not access cache directory %s\n"), cachedir);
+ ret++;
+ continue;
}
rewinddir(dir);
@@ -163,7 +176,6 @@ static int sync_cleancache(int level)
char path[PATH_MAX];
int delete = 1;
pmpkg_t *localpkg = NULL, *pkg = NULL;
- alpm_list_t *sync_dbs = alpm_option_get_syncdbs();
alpm_list_t *j;
if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) {
@@ -172,11 +184,20 @@ static int sync_cleancache(int level)
/* build the full filepath */
snprintf(path, PATH_MAX, "%s%s", cachedir, ent->d_name);
+ /* short circuit for removing all packages from cache */
+ if(level > 1) {
+ unlink(path);
+ 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(localpkg) {
+ alpm_pkg_free(localpkg);
+ }
unlink(path);
}
continue;
@@ -215,26 +236,10 @@ static int sync_cleancache(int level)
unlink(path);
}
}
- } else {
- /* full cleanup */
- printf(_("Cache directory: %s\n"), cachedir);
- if(!noyes(_("Do you want to remove ALL files from cache?"))) {
- return(0);
- }
- printf(_("removing all files from cache...\n"));
-
- if(rmrf(cachedir)) {
- pm_fprintf(stderr, PM_LOG_ERROR, _("could not remove cache directory\n"));
- return(1);
- }
-
- if(makepath(cachedir)) {
- pm_fprintf(stderr, PM_LOG_ERROR, _("could not create new cache directory\n"));
- return(1);
- }
+ closedir(dir);
}
- return(0);
+ return(ret);
}
static int sync_synctree(int level, alpm_list_t *syncs)
@@ -242,7 +247,7 @@ static int sync_synctree(int level, alpm_list_t *syncs)
alpm_list_t *i;
int success = 0, ret;
- if(trans_init(PM_TRANS_TYPE_SYNC, 0) == -1) {
+ if(trans_init(0) == -1) {
return(0);
}
@@ -548,89 +553,68 @@ static alpm_list_t *syncfirst() {
return(res);
}
+static int process_target(char *target)
+{
+ /* process targets */
+ char *targstring = strdup(target);
+ char *targname = strchr(targstring, '/');
+ char *dbname = NULL;
+ int ret = 0;
+ if(targname) {
+ *targname = '\0';
+ targname++;
+ dbname = targstring;
+ ret = alpm_sync_dbtarget(dbname,targname);
+ } else {
+ targname = targstring;
+ ret = alpm_sync_target(targname);
+ }
+
+ if(ret == -1) {
+ if(pm_errno == PM_ERR_TRANS_DUP_TARGET
+ || pm_errno == PM_ERR_PKG_IGNORED) {
+ /* just skip duplicate or ignored targets */
+ pm_printf(PM_LOG_WARNING, _("skipping target: %s\n"), target);
+ } else {
+ pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", target,
+ alpm_strerrorlast());
+ ret = 1;
+ }
+ }
+
+ free(targstring);
+ return(ret);
+}
+
static int sync_trans(alpm_list_t *targets)
{
int retval = 0;
alpm_list_t *data = NULL;
- alpm_list_t *sync_dbs = alpm_option_get_syncdbs();
alpm_list_t *packages = NULL;
+ alpm_list_t *i;
/* Step 1: create a new transaction... */
- if(trans_init(PM_TRANS_TYPE_SYNC, config->flags) == -1) {
+ if(trans_init(config->flags) == -1) {
return(1);
}
+ /* process targets */
+ for(i = targets; i; i = alpm_list_next(i)) {
+ char *targ = alpm_list_getdata(i);
+ if(process_target(targ) == 1) {
+ retval = 1;
+ goto cleanup;
+ }
+ }
+
if(config->op_s_upgrade) {
printf(_(":: Starting full system upgrade...\n"));
alpm_logaction("starting full system upgrade\n");
- if(alpm_trans_sysupgrade(config->op_s_upgrade >= 2) == -1) {
+ if(alpm_sync_sysupgrade(config->op_s_upgrade >= 2) == -1) {
pm_fprintf(stderr, PM_LOG_ERROR, "%s\n", alpm_strerrorlast());
retval = 1;
goto cleanup;
}
- } else {
- alpm_list_t *i;
-
- /* process targets */
- for(i = targets; i; i = alpm_list_next(i)) {
- char *targ = alpm_list_getdata(i);
- if(alpm_trans_addtarget(targ) == -1) {
- pmgrp_t *grp = NULL;
- int found = 0;
- alpm_list_t *j;
-
- if(pm_errno == PM_ERR_TRANS_DUP_TARGET || pm_errno == PM_ERR_PKG_IGNORED) {
- /* just skip duplicate or ignored targets */
- pm_printf(PM_LOG_WARNING, _("skipping target: %s\n"), targ);
- continue;
- }
- if(pm_errno != PM_ERR_PKG_NOT_FOUND) {
- pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n",
- targ, alpm_strerrorlast());
- retval = 1;
- goto cleanup;
- }
- /* target not found: check if it's a group */
- printf(_("%s package not found, searching for group...\n"), targ);
- for(j = sync_dbs; j; j = alpm_list_next(j)) {
- pmdb_t *db = alpm_list_getdata(j);
- grp = alpm_db_readgrp(db, targ);
- if(grp) {
- alpm_list_t *k, *pkgnames = NULL;
-
- found++;
- printf(_(":: group %s (including ignored packages):\n"), targ);
- /* remove dupe entries in case a package exists in multiple repos */
- alpm_list_t *grppkgs = alpm_grp_get_pkgs(grp);
- alpm_list_t *pkgs = alpm_list_remove_dupes(grppkgs);
- for(k = pkgs; k; k = alpm_list_next(k)) {
- pkgnames = alpm_list_add(pkgnames,
- (char*)alpm_pkg_get_name(k->data));
- }
- list_display(" ", pkgnames);
- if(yesno(_(":: Install whole content?"))) {
- for(k = pkgnames; k; k = alpm_list_next(k)) {
- targets = alpm_list_add(targets, strdup(alpm_list_getdata(k)));
- }
- } else {
- for(k = pkgnames; k; k = alpm_list_next(k)) {
- char *pkgname = alpm_list_getdata(k);
- if(yesno(_(":: Install %s from group %s?"), pkgname, targ)) {
- targets = alpm_list_add(targets, strdup(pkgname));
- }
- }
- }
- alpm_list_free(pkgnames);
- alpm_list_free(pkgs);
- }
- }
- if(!found) {
- pm_fprintf(stderr, PM_LOG_ERROR, _("'%s': not found in sync db\n"), targ);
- retval = 1;
- goto cleanup;
- }
- }
- }
}
/* Step 2: "compute" the transaction based on targets and flags */
@@ -639,6 +623,12 @@ static int sync_trans(alpm_list_t *targets)
alpm_strerrorlast());
switch(pm_errno) {
alpm_list_t *i;
+ case PM_ERR_PKG_INVALID_ARCH:
+ for(i = data; i; i = alpm_list_next(i)) {
+ char *pkg = alpm_list_getdata(i);
+ printf(_(":: package %s does not have a valid architecture\n"), pkg);
+ }
+ break;
case PM_ERR_UNSATISFIED_DEPS:
for(i = data; i; i = alpm_list_next(i)) {
pmdepmissing_t *miss = alpm_list_getdata(i);
@@ -650,10 +640,17 @@ static int sync_trans(alpm_list_t *targets)
}
break;
case PM_ERR_CONFLICTING_DEPS:
- for(i = data; i; i = alpm_list_next(i)) {
+ for(i = data; i; i = alpm_list_next(i)) {
pmconflict_t *conflict = alpm_list_getdata(i);
- printf(_(":: %s: conflicts with %s\n"),
- alpm_conflict_get_package1(conflict), alpm_conflict_get_package2(conflict));
+ const char *package1 = alpm_conflict_get_package1(conflict);
+ const char *package2 = alpm_conflict_get_package2(conflict);
+ const char *reason = alpm_conflict_get_reason(conflict);
+ /* only print reason if it contains new information */
+ if(!strcmp(package1, reason) || !strcmp(package2, reason)) {
+ printf(_(":: %s and %s are in conflict\n"), package1, package2);
+ } else {
+ printf(_(":: %s and %s are in conflict (%s)\n"), package1, package2, reason);
+ }
}
break;
default:
@@ -663,7 +660,7 @@ static int sync_trans(alpm_list_t *targets)
goto cleanup;
}
- packages = alpm_trans_get_pkgs();
+ packages = alpm_trans_get_add();
if(packages == NULL) {
/* nothing to do: just exit without complaining */
printf(_(" local database is up to date\n"));
@@ -691,7 +688,8 @@ static int sync_trans(alpm_list_t *targets)
goto cleanup;
}
- display_synctargets(packages);
+ display_targets(alpm_trans_get_remove(), 0);
+ display_targets(alpm_trans_get_add(), 1);
printf("\n");
int confirm;
@@ -768,7 +766,7 @@ int pacman_sync(alpm_list_t *targets)
if(config->op_s_clean) {
int ret = 0;
- if(trans_init(PM_TRANS_TYPE_SYNC, 0) == -1) {
+ if(trans_init(0) == -1) {
return(1);
}
diff --git a/src/pacman/upgrade.c b/src/pacman/upgrade.c
index 1570f95e..57c7b790 100644
--- a/src/pacman/upgrade.c
+++ b/src/pacman/upgrade.c
@@ -42,7 +42,6 @@
int pacman_upgrade(alpm_list_t *targets)
{
alpm_list_t *i, *data = NULL;
- pmtranstype_t transtype = PM_TRANS_TYPE_UPGRADE;
int retval = 0;
if(targets == NULL) {
@@ -65,7 +64,7 @@ int pacman_upgrade(alpm_list_t *targets)
}
/* Step 1: create a new transaction */
- if(trans_init(transtype, config->flags) == -1) {
+ if(trans_init(config->flags) == -1) {
return(1);
}
@@ -73,7 +72,7 @@ int pacman_upgrade(alpm_list_t *targets)
printf(_("loading package data...\n"));
for(i = targets; i; i = alpm_list_next(i)) {
char *targ = alpm_list_getdata(i);
- if(alpm_trans_addtarget(targ) == -1) {
+ if(alpm_add_target(targ) == -1) {
pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n",
targ, alpm_strerrorlast());
trans_release();
@@ -87,6 +86,12 @@ int pacman_upgrade(alpm_list_t *targets)
pm_fprintf(stderr, PM_LOG_ERROR, _("failed to prepare transaction (%s)\n"),
alpm_strerrorlast());
switch(pm_errno) {
+ case PM_ERR_PKG_INVALID_ARCH:
+ for(i = data; i; i = alpm_list_next(i)) {
+ char *pkg = alpm_list_getdata(i);
+ printf(_(":: package %s does not have a valid architecture\n"), pkg);
+ }
+ break;
case PM_ERR_UNSATISFIED_DEPS:
for(i = data; i; i = alpm_list_next(i)) {
pmdepmissing_t *miss = alpm_list_getdata(i);
@@ -104,42 +109,75 @@ int pacman_upgrade(alpm_list_t *targets)
case PM_ERR_CONFLICTING_DEPS:
for(i = data; i; i = alpm_list_next(i)) {
pmconflict_t *conflict = alpm_list_getdata(i);
- printf(_(":: %s: conflicts with %s\n"),
- alpm_conflict_get_package1(conflict), alpm_conflict_get_package2(conflict));
+ const char *package1 = alpm_conflict_get_package1(conflict);
+ const char *package2 = alpm_conflict_get_package2(conflict);
+ const char *reason = alpm_conflict_get_reason(conflict);
+ /* only print reason if it contains new information */
+ if(!strcmp(package1, reason) || !strcmp(package2, reason)) {
+ printf(_(":: %s and %s are in conflict\n"), package1, package2);
+ } else {
+ printf(_(":: %s and %s are in conflict (%s)\n"), package1, package2, reason);
+ }
}
break;
+ default:
+ break;
+ }
+ trans_release();
+ FREELIST(data);
+ return(1);
+ }
+
+ /* Step 3: perform the installation */
+ /* print targets and ask user confirmation */
+ alpm_list_t *packages = alpm_trans_get_add();
+ if(packages == NULL) { /* we are done */
+ trans_release();
+ return(retval);
+ }
+ display_targets(alpm_trans_get_remove(), 0);
+ display_targets(alpm_trans_get_add(), 1);
+ printf("\n");
+ int confirm = yesno(_("Proceed with installation?"));
+ if(!confirm) {
+ trans_release();
+ return(retval);
+ }
+
+ if(alpm_trans_commit(&data) == -1) {
+ pm_fprintf(stderr, PM_LOG_ERROR, _("failed to commit transaction (%s)\n"),
+ alpm_strerrorlast());
+ switch(pm_errno) {
+ alpm_list_t *i;
case PM_ERR_FILE_CONFLICTS:
for(i = data; i; i = alpm_list_next(i)) {
pmfileconflict_t *conflict = alpm_list_getdata(i);
switch(alpm_fileconflict_get_type(conflict)) {
case PM_FILECONFLICT_TARGET:
printf(_("%s exists in both '%s' and '%s'\n"),
- alpm_fileconflict_get_file(conflict),
- alpm_fileconflict_get_target(conflict),
- alpm_fileconflict_get_ctarget(conflict));
- break;
+ alpm_fileconflict_get_file(conflict),
+ alpm_fileconflict_get_target(conflict),
+ alpm_fileconflict_get_ctarget(conflict));
+ break;
case PM_FILECONFLICT_FILESYSTEM:
printf(_("%s: %s exists in filesystem\n"),
- alpm_fileconflict_get_target(conflict),
- alpm_fileconflict_get_file(conflict));
- break;
+ alpm_fileconflict_get_target(conflict),
+ alpm_fileconflict_get_file(conflict));
+ break;
}
}
- printf(_("\nerrors occurred, no packages were upgraded.\n"));
+ break;
+ case PM_ERR_PKG_INVALID:
+ case PM_ERR_DLT_INVALID:
+ for(i = data; i; i = alpm_list_next(i)) {
+ char *filename = alpm_list_getdata(i);
+ printf(_("%s is invalid or corrupted\n"), filename);
+ }
break;
default:
break;
}
- trans_release();
FREELIST(data);
- return(1);
- }
- alpm_list_free(data);
-
- /* Step 3: perform the installation */
- if(alpm_trans_commit(NULL) == -1) {
- pm_fprintf(stderr, PM_LOG_ERROR, _("failed to commit transaction (%s)\n"),
- alpm_strerrorlast());
trans_release();
return(1);
}
diff --git a/src/pacman/util.c b/src/pacman/util.c
index c68e6841..14a0f6cd 100644
--- a/src/pacman/util.c
+++ b/src/pacman/util.c
@@ -45,9 +45,9 @@
#include "callback.h"
-int trans_init(pmtranstype_t type, pmtransflag_t flags)
+int trans_init(pmtransflag_t flags)
{
- if(alpm_trans_init(type, flags, cb_trans_evt,
+ if(alpm_trans_init(flags, cb_trans_evt,
cb_trans_conv, cb_trans_progress) == -1) {
pm_fprintf(stderr, PM_LOG_ERROR, _("failed to init transaction (%s)\n"),
alpm_strerrorlast());
@@ -85,70 +85,18 @@ int needs_root(void)
/* gets the current screen column width */
int getcols(void)
{
- if(!isatty(1)) {
- /* We will default to 80 columns if we're not a tty
- * this seems a fairly standard file width.
- */
- return 80;
- } else {
#ifdef TIOCGSIZE
- struct ttysize win;
- if(ioctl(1, TIOCGSIZE, &win) == 0) {
- return win.ts_cols;
- }
-#elif defined(TIOCGWINSZ)
- struct winsize win;
- if(ioctl(1, TIOCGWINSZ, &win) == 0) {
- return win.ws_col;
- }
-#endif
- /* If we can't figure anything out, we'll just assume 80 columns */
- /* TODO any problems caused by this assumption? */
- return 80;
- }
- /* Original envvar way - prone to display issues
- const char *cenv = getenv("COLUMNS");
- if(cenv != NULL) {
- return atoi(cenv);
+ struct ttysize win;
+ if(ioctl(1, TIOCGSIZE, &win) == 0) {
+ return win.ts_cols;
}
- return -1;
- */
-}
-
-/* does the same thing as 'mkdir -p' */
-int makepath(const char *path)
-{
- /* A bit of pointer hell here. Descriptions:
- * orig - a copy of path so we can safely butcher it with strsep
- * str - the current position in the path string (after the delimiter)
- * ptr - the original position of str after calling strsep
- * incr - incrementally generated path for use in access/mkdir call
- */
- char *orig, *str, *ptr, *incr;
- mode_t oldmask = umask(0000);
- int ret = 0;
-
- orig = strdup(path);
- incr = calloc(strlen(orig) + 1, sizeof(char));
- str = orig;
- while((ptr = strsep(&str, "/"))) {
- if(strlen(ptr)) {
- /* we have another path component- append the newest component to
- * existing string and create one more level of dir structure */
- strcat(incr, "/");
- strcat(incr, ptr);
- if(access(incr, F_OK)) {
- if(mkdir(incr, 0755)) {
- ret = 1;
- break;
- }
- }
- }
+#elif defined(TIOCGWINSZ)
+ struct winsize win;
+ if(ioctl(1, TIOCGWINSZ, &win) == 0) {
+ return win.ws_col;
}
- free(orig);
- free(incr);
- umask(oldmask);
- return(ret);
+#endif
+ return 0;
}
/* does the same thing as 'rm -rf' */
@@ -257,6 +205,14 @@ void indentprint(const char *str, int indent)
return;
}
+ cols = getcols();
+
+ /* if we're not a tty, print without indenting */
+ if(cols == 0) {
+ printf("%s", str);
+ return;
+ }
+
len = strlen(str) + 1;
wcstr = calloc(len, sizeof(wchar_t));
len = mbstowcs(wcstr, str, len);
@@ -266,7 +222,6 @@ void indentprint(const char *str, int indent)
if(!p) {
return;
}
- cols = getcols();
while(*p) {
if(*p == L' ') {
@@ -285,7 +240,7 @@ void indentprint(const char *str, int indent)
}
if(len > (cols - cidx - 1)) {
/* wrap to a newline and reindent */
- fprintf(stdout, "\n%-*s", indent, "");
+ printf("\n%-*s", indent, "");
cidx = indent;
} else {
printf(" ");
@@ -293,7 +248,7 @@ void indentprint(const char *str, int indent)
}
continue;
}
- fprintf(stdout, "%lc", (wint_t)*p);
+ printf("%lc", (wint_t)*p);
cidx += wcwidth(*p);
p++;
}
@@ -307,7 +262,7 @@ char *strtoupper(char *str)
char *ptr = str;
while(*ptr) {
- (*ptr) = toupper(*ptr);
+ (*ptr) = toupper((unsigned char)*ptr);
ptr++;
}
return str;
@@ -324,7 +279,7 @@ char *strtrim(char *str)
return(str);
}
- while(isspace(*pch)) {
+ while(isspace((unsigned char)*pch)) {
pch++;
}
if(pch != str) {
@@ -337,7 +292,7 @@ char *strtrim(char *str)
}
pch = (str + (strlen(str) - 1));
- while(isspace(*pch)) {
+ while(isspace((unsigned char)*pch)) {
pch--;
}
*++pch = '\0';
@@ -345,48 +300,65 @@ char *strtrim(char *str)
return(str);
}
-/* Helper function for strreplace */
-static void _strnadd(char **str, const char *append, unsigned int count)
-{
- if(*str) {
- *str = realloc(*str, strlen(*str) + count + 1);
- } else {
- *str = calloc(sizeof(char), count + 1);
- }
-
- strncat(*str, append, count);
-}
-
/* Replace all occurances of 'needle' with 'replace' in 'str', returning
* a new string (must be free'd) */
char *strreplace(const char *str, const char *needle, const char *replace)
{
- const char *p, *q;
- p = q = str;
+ const char *p = NULL, *q = NULL;
+ char *newstr = NULL, *newp = NULL;
+ alpm_list_t *i = NULL, *list = NULL;
+ size_t needlesz = strlen(needle), replacesz = strlen(replace);
+ size_t newsz;
- char *newstr = NULL;
- unsigned int needlesz = strlen(needle),
- replacesz = strlen(replace);
+ if(!str) {
+ return(NULL);
+ }
- while (1) {
+ p = str;
+ q = strstr(p, needle);
+ while(q) {
+ list = alpm_list_add(list, (char *)q);
+ p = q + needlesz;
q = strstr(p, needle);
- if(!q) { /* not found */
- if(*p) {
- /* add the rest of 'p' */
- _strnadd(&newstr, p, strlen(p));
- }
- break;
- } else { /* found match */
- if(q > p){
- /* add chars between this occurance and last occurance, if any */
- _strnadd(&newstr, p, q - p);
- }
- _strnadd(&newstr, replace, replacesz);
- p = q + needlesz;
+ }
+
+ /* no occurences of needle found */
+ if(!list) {
+ return(strdup(str));
+ }
+ /* size of new string = size of old string + "number of occurences of needle"
+ * x "size difference between replace and needle" */
+ newsz = strlen(str) + 1 +
+ alpm_list_count(list) * (replacesz - needlesz);
+ newstr = malloc(newsz);
+ if(!newstr) {
+ return(NULL);
+ }
+ *newstr = '\0';
+
+ p = str;
+ newp = newstr;
+ for(i = list; i; i = alpm_list_next(i)) {
+ q = alpm_list_getdata(i);
+ if(q > p){
+ /* add chars between this occurence and last occurence, if any */
+ strncpy(newp, p, q - p);
+ newp += q - p;
}
+ strncpy(newp, replace, replacesz);
+ newp += replacesz;
+ p = q + needlesz;
}
+ alpm_list_free(list);
- return newstr;
+ if(*p) {
+ /* add the rest of 'p' */
+ strcpy(newp, p);
+ newp += strlen(p);
+ }
+ *newp = '\0';
+
+ return(newstr);
}
/** Splits a string into a list of strings using the chosen character as
@@ -446,13 +418,13 @@ void string_display(const char *title, const char *string)
int len = 0;
if(title) {
- /* compute the length of title + a space */
- len = string_length(title) + 1;
printf("%s ", title);
}
if(string == NULL || string[0] == '\0') {
printf(_("None"));
} else {
+ /* compute the length of title + a space */
+ len = string_length(title) + 1;
indentprint(string, len);
}
printf("\n");
@@ -474,18 +446,20 @@ void list_display(const char *title, const alpm_list_t *list)
for(i = list, cols = len; i; i = alpm_list_next(i)) {
char *str = alpm_list_getdata(i);
int s = string_length(str);
- /* two additional spaces are added to the length */
- s += 2;
int maxcols = getcols();
- if(s + cols > maxcols) {
+ if(maxcols > 0 && (cols + s + 2) >= maxcols) {
int j;
cols = len;
printf("\n");
for (j = 1; j <= len; j++) {
printf(" ");
}
+ } else if (cols != len) {
+ /* 2 spaces are added if this is not the first element on a line. */
+ printf(" ");
+ cols += 2;
}
- printf("%s ", str);
+ printf("%s", str);
cols += s;
}
printf("\n");
@@ -577,37 +551,6 @@ void display_targets(const alpm_list_t *pkgs, int install)
FREELIST(targets);
}
-/* Display a list of transaction targets.
- * `pkgs` should be a list of pmpkg_t's,
- * retrieved from a transaction object
- */
-void display_synctargets(const alpm_list_t *syncpkgs)
-{
- const alpm_list_t *i, *j;
- alpm_list_t *pkglist = NULL, *rpkglist = NULL;
-
- for(i = syncpkgs; i; i = alpm_list_next(i)) {
- pmpkg_t *pkg = alpm_list_getdata(i);
- pkglist = alpm_list_add(pkglist, pkg);
-
- /* The removes member contains a list of packages to be removed
- * due to the package that is being installed. */
- alpm_list_t *to_replace = alpm_pkg_get_removes(pkg);
-
- for(j = to_replace; j; j = alpm_list_next(j)) {
- pmpkg_t *rp = alpm_list_getdata(j);
- rpkglist = alpm_list_add(rpkglist, rp);
- }
- }
-
- /* start displaying information */
- display_targets(rpkglist, 0);
- display_targets(pkglist, 1);
-
- alpm_list_free(pkglist);
- alpm_list_free(rpkglist);
-}
-
/* Helper function for comparing strings using the
* alpm "compare func" signature */
int str_cmp(const void *s1, const void *s2)
@@ -640,6 +583,7 @@ void display_optdepends(pmpkg_t *pkg)
static int question(short preset, char *fmt, va_list args)
{
char response[32];
+ int sresponse = sizeof(response)-1;
FILE *stream;
if(config->noconfirm) {
@@ -662,7 +606,7 @@ static int question(short preset, char *fmt, va_list args)
return(preset);
}
- if(fgets(response, 32, stdin)) {
+ if(fgets(response, sresponse, stdin)) {
strtrim(response);
if(strlen(response) == 0) {
return(preset);
diff --git a/src/pacman/util.h b/src/pacman/util.h
index 12824221..7a8c39d1 100644
--- a/src/pacman/util.h
+++ b/src/pacman/util.h
@@ -37,11 +37,10 @@
/* update speed for the fill_progress based functions */
#define UPDATE_SPEED_SEC 0.2f
-int trans_init(pmtranstype_t type, pmtransflag_t flags);
+int trans_init(pmtransflag_t flags);
int trans_release(void);
int needs_root(void);
int getcols(void);
-int makepath(const char *path);
int rmrf(const char *path);
char *mbasename(const char *path);
char *mdirname(const char *path);
@@ -54,7 +53,6 @@ void string_display(const char *title, const char *string);
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);
-void display_synctargets(const alpm_list_t *syncpkgs);
void display_new_optdepends(pmpkg_t *oldpkg, pmpkg_t *newpkg);
void display_optdepends(pmpkg_t *pkg);
int yesno(char *fmt, ...);