summaryrefslogtreecommitdiffstats
path: root/src/pacman/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pacman/util.c')
-rw-r--r--src/pacman/util.c274
1 files changed, 232 insertions, 42 deletions
diff --git a/src/pacman/util.c b/src/pacman/util.c
index 557696b0..c08ebb15 100644
--- a/src/pacman/util.c
+++ b/src/pacman/util.c
@@ -1,7 +1,7 @@
/*
* util.c
*
- * Copyright (c) 2006-2010 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
*
* This program is free software; you can redistribute it and/or modify
@@ -143,7 +143,7 @@ int rmrf(const char *path)
if(dp->d_ino) {
char name[PATH_MAX];
sprintf(name, "%s/%s", path, dp->d_name);
- if(strcmp(dp->d_name, "..") && strcmp(dp->d_name, ".")) {
+ if(strcmp(dp->d_name, "..") != 0 && strcmp(dp->d_name, ".") != 0) {
errflag += rmrf(name);
}
}
@@ -157,25 +157,17 @@ int rmrf(const char *path)
}
/** Parse the basename of a program from a path.
-* Grabbed from the uClibc source.
* @param path path to parse basename from
*
* @return everything following the final '/'
*/
-char *mbasename(const char *path)
+const char *mbasename(const char *path)
{
- const char *s;
- const char *p;
-
- p = s = path;
-
- while (*s) {
- if (*s++ == '/') {
- p = s;
- }
+ const char *last = strrchr(path, '/');
+ if(last) {
+ return(last + 1);
}
-
- return (char *)p;
+ return(path);
}
/** Parse the dirname of a program from a path.
@@ -275,7 +267,7 @@ char *strtoupper(char *str)
char *ptr = str;
while(*ptr) {
- (*ptr) = toupper((unsigned char)*ptr);
+ (*ptr) = (char)toupper((unsigned char)*ptr);
ptr++;
}
return str;
@@ -355,7 +347,7 @@ char *strreplace(const char *str, const char *needle, const char *replace)
q = alpm_list_getdata(i);
if(q > p){
/* add chars between this occurence and last occurence, if any */
- strncpy(newp, p, q - p);
+ strncpy(newp, p, (size_t)(q - p));
newp += q - p;
}
strncpy(newp, replace, replacesz);
@@ -389,7 +381,7 @@ alpm_list_t *strsplit(const char *str, const char splitchar)
char *dup = NULL;
while((str = strchr(str, splitchar))) {
- dup = strndup(prev, str - prev);
+ dup = strndup(prev, (size_t)(str - prev));
if(dup == NULL) {
return(NULL);
}
@@ -523,29 +515,30 @@ void display_targets(const alpm_list_t *pkgs, int install)
for(i = pkgs; i; i = alpm_list_next(i)) {
pmpkg_t *pkg = alpm_list_getdata(i);
- dlsize += alpm_pkg_download_size(pkg);
+ if(install) {
+ dlsize += alpm_pkg_download_size(pkg);
+ }
isize += alpm_pkg_get_isize(pkg);
/* print the package size with the output if ShowSize option set */
if(config->showsize) {
- double mbsize = 0.0;
- mbsize = alpm_pkg_get_size(pkg) / (1024.0 * 1024.0);
+ double mbsize = (double)alpm_pkg_get_size(pkg) / (1024.0 * 1024.0);
- asprintf(&str, "%s-%s [%.2f MB]", alpm_pkg_get_name(pkg),
+ pm_asprintf(&str, "%s-%s [%.2f MB]", alpm_pkg_get_name(pkg),
alpm_pkg_get_version(pkg), mbsize);
} else {
- asprintf(&str, "%s-%s", alpm_pkg_get_name(pkg),
+ pm_asprintf(&str, "%s-%s", alpm_pkg_get_name(pkg),
alpm_pkg_get_version(pkg));
}
targets = alpm_list_add(targets, str);
}
/* Convert byte sizes to MB */
- mbdlsize = dlsize / (1024.0 * 1024.0);
- mbisize = isize / (1024.0 * 1024.0);
+ mbdlsize = (double)dlsize / (1024.0 * 1024.0);
+ mbisize = (double)isize / (1024.0 * 1024.0);
if(install) {
- asprintf(&str, _("Targets (%d):"), alpm_list_count(targets));
+ pm_asprintf(&str, _("Targets (%d):"), alpm_list_count(targets));
list_display(str, targets);
free(str);
printf("\n");
@@ -555,7 +548,7 @@ void display_targets(const alpm_list_t *pkgs, int install)
printf(_("Total Installed Size: %.2f MB\n"), mbisize);
}
} else {
- asprintf(&str, _("Remove (%d):"), alpm_list_count(targets));
+ pm_asprintf(&str, _("Remove (%d):"), alpm_list_count(targets));
list_display(str, targets);
free(str);
printf("\n");
@@ -589,14 +582,14 @@ static char *pkg_get_location(pmpkg_t *pkg)
dburl = alpm_db_get_url(db);
if(dburl) {
char *pkgurl = NULL;
- asprintf(&pkgurl, "%s/%s", dburl, alpm_pkg_get_filename(pkg));
+ pm_asprintf(&pkgurl, "%s/%s", dburl, alpm_pkg_get_filename(pkg));
return(pkgurl);
}
case PM_OP_UPGRADE:
return(strdup(alpm_pkg_get_filename(pkg)));
default:
string = NULL;
- asprintf(&string, "%s-%s", alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg));
+ pm_asprintf(&string, "%s-%s", alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg));
return(string);
}
}
@@ -645,13 +638,11 @@ void print_packages(const alpm_list_t *packages)
/* %s : size */
if(strstr(temp,"%s")) {
char *size;
- double mbsize = 0.0;
- mbsize = pkg_get_size(pkg) / (1024.0 * 1024.0);
- asprintf(&size, "%.2f", mbsize);
+ double mbsize = (double)pkg_get_size(pkg) / (1024.0 * 1024.0);
+ pm_asprintf(&size, "%.2f", mbsize);
string = strreplace(temp, "%s", size);
free(size);
free(temp);
- temp = string;
}
printf("%s\n",string);
free(string);
@@ -686,11 +677,194 @@ void display_optdepends(pmpkg_t *pkg)
}
}
+static void display_repo_list(const char *dbname, alpm_list_t *list)
+{
+ const char *prefix= " ";
+
+ printf(":: ");
+ printf(_("Repository %s\n"), dbname);
+ list_display(prefix, list);
+}
+
+void select_display(const alpm_list_t *pkglist)
+{
+ const alpm_list_t *i;
+ int nth = 1;
+ alpm_list_t *list = NULL;
+ char *string = NULL;
+ const char *dbname = NULL;
+
+ for (i = pkglist; i; i = i->next) {
+ pmpkg_t *pkg = alpm_list_getdata(i);
+ pmdb_t *db = alpm_pkg_get_db(pkg);
+
+ if(!dbname)
+ dbname = alpm_db_get_name(db);
+ if(strcmp(alpm_db_get_name(db), dbname) != 0) {
+ display_repo_list(dbname, list);
+ FREELIST(list);
+ dbname = alpm_db_get_name(db);
+ }
+ string = NULL;
+ pm_asprintf(&string, "%d) %s", nth, alpm_pkg_get_name(pkg));
+ list = alpm_list_add(list, string);
+ nth++;
+ }
+ display_repo_list(dbname, list);
+ FREELIST(list);
+}
+
+static int parseindex(char *s, int *val, int min, int max)
+{
+ char *endptr = NULL;
+ int n = strtol(s, &endptr, 10);
+ if(*endptr == '\0') {
+ if(n < min || n > max) {
+ fprintf(stderr, _("Invalid value: %d is not between %d and %d\n"),
+ n, min, max);
+ return(-1);
+ }
+ *val = n;
+ return(0);
+ } else {
+ fprintf(stderr, _("Invalid number: %s\n"), s);
+ return(-1);
+ }
+}
+
+static int multiselect_parse(char *array, int count, char *response)
+{
+ char *str, *saveptr;
+
+ for (str = response; ; str = NULL) {
+ int include = 1;
+ int start, end;
+ char *ends = NULL;
+ char *starts = strtok_r(str, " ", &saveptr);
+
+ if (starts == NULL)
+ break;
+ strtrim(starts);
+ int len = strlen(starts);
+ if(len == 0)
+ continue;
+
+ if (*starts == '^') {
+ starts++;
+ len--;
+ include = 0;
+ } else if(str) {
+ /* if first token is including, we unselect all targets */
+ memset(array, 0, count);
+ }
+
+ if(len > 1) {
+ /* check for range */
+ char *p;
+ if((p = strchr(starts+1, '-'))) {
+ *p = 0;
+ ends = p+1;
+ }
+ }
+
+ if(parseindex(starts, &start, 1, count) != 0)
+ return(-1);
+
+ if(!ends) {
+ array[start-1] = include;
+ } else {
+ if(parseindex(ends, &end, start, count) != 0)
+ return(-1);
+ for(int d = start; d <= end; d++) {
+ array[d-1] = include;
+ }
+ }
+ }
+
+ return(0);
+}
+
+int multiselect_question(char *array, int count)
+{
+ char response[64];
+ FILE *stream;
+
+ if(config->noconfirm) {
+ stream = stdout;
+ } else {
+ /* Use stderr so questions are always displayed when redirecting output */
+ stream = stderr;
+ }
+
+ while(1) {
+ memset(array, 1, count);
+
+ fprintf(stream, "\n");
+ fprintf(stream, _("Enter a selection (default=all)"));
+ fprintf(stream, ": ");
+
+ if(config->noconfirm) {
+ fprintf(stream, "\n");
+ break;
+ }
+
+ if(fgets(response, sizeof(response), stdin)) {
+ strtrim(response);
+ if(strlen(response) > 0) {
+ if(multiselect_parse(array, count, response) == -1) {
+ /* only loop if user gave an invalid answer */
+ continue;
+ }
+ }
+ }
+ break;
+ }
+ return(0);
+}
+
+int select_question(int count)
+{
+ char response[32];
+ FILE *stream;
+ int preset = 1;
+
+ if(config->noconfirm) {
+ stream = stdout;
+ } else {
+ /* Use stderr so questions are always displayed when redirecting output */
+ stream = stderr;
+ }
+
+ while(1) {
+ fprintf(stream, "\n");
+ fprintf(stream, _("Enter a number (default=%d)"), preset);
+ fprintf(stream, ": ");
+
+ if(config->noconfirm) {
+ fprintf(stream, "\n");
+ break;
+ }
+
+ 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);
+ }
+ }
+ break;
+ }
+
+ return(preset-1);
+}
+
+
/* presents a prompt and gets a Y/N answer */
static int question(short preset, char *fmt, va_list args)
{
char response[32];
- int sresponse = sizeof(response)-1;
FILE *stream;
if(config->noconfirm) {
@@ -713,15 +887,15 @@ static int question(short preset, char *fmt, va_list args)
return(preset);
}
- if(fgets(response, sresponse, stdin)) {
+ if(fgets(response, sizeof(response), stdin)) {
strtrim(response);
if(strlen(response) == 0) {
return(preset);
}
- if(!strcasecmp(response, _("Y")) || !strcasecmp(response, _("YES"))) {
+ if(strcasecmp(response, _("Y")) == 0 || strcasecmp(response, _("YES")) == 0) {
return(1);
- } else if (!strcasecmp(response, _("N")) || !strcasecmp(response, _("NO"))) {
+ } else if (strcasecmp(response, _("N")) == 0 || strcasecmp(response, _("NO")) == 0) {
return(0);
}
}
@@ -778,6 +952,22 @@ int pm_fprintf(FILE *stream, pmloglevel_t level, const char *format, ...)
return(ret);
}
+int pm_asprintf(char **string, const char *format, ...)
+{
+ int ret = 0;
+ va_list args;
+
+ /* print the message using va_arg list */
+ va_start(args, format);
+ if(vasprintf(string, format, args) == -1) {
+ pm_fprintf(stderr, PM_LOG_ERROR, _("failed to allocate string\n"));
+ ret = -1;
+ }
+ va_end(args);
+
+ return(ret);
+}
+
int pm_vasprintf(char **string, pmloglevel_t level, const char *format, va_list args)
{
int ret = 0;
@@ -794,16 +984,16 @@ int pm_vasprintf(char **string, pmloglevel_t level, const char *format, va_list
/* print a prefix to the message */
switch(level) {
case PM_LOG_DEBUG:
- asprintf(string, "debug: %s", msg);
+ pm_asprintf(string, "debug: %s", msg);
break;
case PM_LOG_ERROR:
- asprintf(string, _("error: %s"), msg);
+ pm_asprintf(string, _("error: %s"), msg);
break;
case PM_LOG_WARNING:
- asprintf(string, _("warning: %s"), msg);
+ pm_asprintf(string, _("warning: %s"), msg);
break;
case PM_LOG_FUNCTION:
- asprintf(string, _("function: %s"), msg);
+ pm_asprintf(string, _("function: %s"), msg);
break;
default:
break;
@@ -824,7 +1014,7 @@ int pm_vfprintf(FILE *stream, pmloglevel_t level, const char *format, va_list ar
#if defined(PACMAN_DEBUG)
/* If debug is on, we'll timestamp the output */
- if(config->logmask & PM_LOG_DEBUG) {
+ if(config->logmask & PM_LOG_DEBUG) {
time_t t;
struct tm *tmp;
char timestr[10] = {0};