diff options
Diffstat (limited to 'src/pacman/util.c')
-rw-r--r-- | src/pacman/util.c | 274 |
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}; |