summaryrefslogtreecommitdiff
path: root/src/pacman/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pacman/util.c')
-rw-r--r--src/pacman/util.c305
1 files changed, 205 insertions, 100 deletions
diff --git a/src/pacman/util.c b/src/pacman/util.c
index f7f8ecf5..a5242aeb 100644
--- a/src/pacman/util.c
+++ b/src/pacman/util.c
@@ -18,12 +18,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "config.h"
-
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
-#include <sys/time.h>
+#include <time.h>
#include <stdio.h>
#include <stdlib.h>
@@ -65,7 +63,7 @@ int trans_init(alpm_transflag_t flags, int check_valid)
void trans_init_error(void)
{
- enum _alpm_errno_t err = alpm_errno(config->handle);
+ alpm_errno_t err = alpm_errno(config->handle);
pm_printf(ALPM_LOG_ERROR, _("failed to init transaction (%s)\n"),
alpm_strerror(err));
if(err == ALPM_ERR_HANDLE_LOCK) {
@@ -110,7 +108,7 @@ int check_syncdbs(size_t need_repos, int check_valid)
{
int ret = 0;
alpm_list_t *i;
- alpm_list_t *sync_dbs = alpm_option_get_syncdbs(config->handle);
+ alpm_list_t *sync_dbs = alpm_get_syncdbs(config->handle);
if(need_repos && sync_dbs == NULL) {
pm_printf(ALPM_LOG_ERROR, _("no usable package repositories configured.\n"));
@@ -270,7 +268,7 @@ void indentprint(const char *str, size_t indent)
/* if we're not a tty, or our tty is not wide enough that wrapping even makes
* sense, print without indenting */
if(cols == 0 || indent > cols) {
- printf("%s", str);
+ fputs(str, stdout);
return;
}
@@ -318,13 +316,13 @@ void indentprint(const char *str, size_t indent)
/* Trim whitespace and newlines from a string
*/
-char *strtrim(char *str)
+size_t strtrim(char *str)
{
- char *pch = str;
+ char *end, *pch = str;
if(str == NULL || *str == '\0') {
/* string is empty, so we're done. */
- return str;
+ return 0;
}
while(isspace((unsigned char)*pch)) {
@@ -341,16 +339,16 @@ char *strtrim(char *str)
/* check if there wasn't anything but whitespace in the string. */
if(*str == '\0') {
- return str;
+ return 0;
}
- pch = (str + (strlen(str) - 1));
- while(isspace((unsigned char)*pch)) {
- pch--;
+ end = (str + strlen(str) - 1);
+ while(isspace((unsigned char)*end)) {
+ end--;
}
- *++pch = '\0';
+ *++end = '\0';
- return str;
+ return end - pch;
}
/* Replace all occurances of 'needle' with 'replace' in 'str', returning
@@ -391,7 +389,7 @@ char *strreplace(const char *str, const char *needle, const char *replace)
p = str;
newp = newstr;
for(i = list; i; i = alpm_list_next(i)) {
- q = alpm_list_getdata(i);
+ q = i->data;
if(q > p) {
/* add chars between this occurence and last occurence, if any */
memcpy(newp, p, (size_t)(q - p));
@@ -478,77 +476,123 @@ void string_display(const char *title, const char *string)
printf("\n");
}
-static void table_print_line(const alpm_list_t *line,
- size_t colcount, size_t *widths)
+static void table_print_line(const alpm_list_t *line, short col_padding,
+ size_t colcount, size_t *widths, int *has_data)
{
- size_t i;
+ size_t i, lastcol = 0;
+ int need_padding = 0;
const alpm_list_t *curcell;
+ for(i = colcount; i > 0; i--) {
+ if(has_data[i - 1]) {
+ lastcol = i - 1;
+ break;
+ }
+ }
+
for(i = 0, curcell = line; curcell && i < colcount;
i++, curcell = alpm_list_next(curcell)) {
- const char *value = curcell->data;
- size_t len = string_length(value);
+ const char *value;
+ int cell_padding;
+
+ if(!has_data[i]) {
+ continue;
+ }
+
+ value = curcell->data;
+ if(!value) {
+ value = "";
+ }
/* silly printf requires padding size to be an int */
- int padding = (int)widths[i] - (int)len;
- if(padding < 0) {
- padding = 0;
+ cell_padding = (int)widths[i] - (int)string_length(value);
+ if(cell_padding < 0) {
+ cell_padding = 0;
+ }
+ if(need_padding) {
+ printf("%*s", col_padding, "");
}
/* left-align all but the last column */
- if(i + 1 < colcount) {
- printf("%s%*s", value, padding, "");
+ if(i != lastcol) {
+ printf("%s%*s", value, cell_padding, "");
} else {
- printf("%*s%s", padding, "", value);
+ printf("%*s%s", cell_padding, "", value);
}
+ need_padding = 1;
}
printf("\n");
}
-/* find the max string width of each column */
+
+
+/**
+ * Find the max string width of each column. Also determines whether values
+ * exist in the column and sets the value in has_data accordingly.
+ * @param header a list of header strings
+ * @param rows a list of lists of rows as strings
+ * @param padding the amount of padding between columns
+ * @param totalcols the total number of columns in the header and each row
+ * @param widths a pointer to store width data
+ * @param has_data a pointer to store whether column has data
+ *
+ * @return the total width of the table; 0 on failure
+ */
static size_t table_calc_widths(const alpm_list_t *header,
- const alpm_list_t *rows, size_t totalcols, size_t **widths)
+ const alpm_list_t *rows, short padding, size_t totalcols,
+ size_t **widths, int **has_data)
{
const alpm_list_t *i;
- const unsigned short padding = 2;
- size_t curcol, totalwidth = 0;
+ size_t curcol, totalwidth = 0, usefulcols = 0;
size_t *colwidths;
+ int *coldata;
if(totalcols <= 0) {
return 0;
}
colwidths = malloc(totalcols * sizeof(size_t));
- if(!colwidths) {
+ coldata = calloc(totalcols, sizeof(int));
+ if(!colwidths || !coldata) {
return 0;
}
/* header determines column count and initial values of longest_strs */
for(i = header, curcol = 0; i; i = alpm_list_next(i), curcol++) {
- colwidths[curcol] = string_length(alpm_list_getdata(i));
+ colwidths[curcol] = string_length(i->data);
+ /* note: header does not determine whether column has data */
}
/* now find the longest string in each column */
for(i = rows; i; i = alpm_list_next(i)) {
/* grab first column of each row and iterate through columns */
- const alpm_list_t *j = alpm_list_getdata(i);
+ const alpm_list_t *j = i->data;
for(curcol = 0; j; j = alpm_list_next(j), curcol++) {
- char *str = alpm_list_getdata(j);
+ const char *str = j->data;
size_t str_len = string_length(str);
if(str_len > colwidths[curcol]) {
colwidths[curcol] = str_len;
}
+ if(str_len > 0) {
+ coldata[curcol] = 1;
+ }
}
}
for(i = header, curcol = 0; i; i = alpm_list_next(i), curcol++) {
- /* pad everything but the last column */
- if(curcol + 1 < totalcols) {
- colwidths[curcol] += padding;
+ /* only include columns that have data */
+ if(coldata[curcol]) {
+ usefulcols++;
+ totalwidth += colwidths[curcol];
}
- totalwidth += colwidths[curcol];
+ }
+
+ /* add padding between columns */
+ if(usefulcols > 0) {
+ totalwidth += padding * (usefulcols - 1);
}
*widths = colwidths;
+ *has_data = coldata;
return totalwidth;
}
@@ -565,22 +609,25 @@ static size_t table_calc_widths(const alpm_list_t *header,
int table_display(const char *title, const alpm_list_t *header,
const alpm_list_t *rows)
{
+ const unsigned short padding = 2;
const alpm_list_t *i;
size_t *widths = NULL, totalcols, totalwidth;
+ int *has_data = NULL;
if(rows == NULL || header == NULL) {
return 0;
}
totalcols = alpm_list_count(header);
- totalwidth = table_calc_widths(header, rows, totalcols, &widths);
+ totalwidth = table_calc_widths(header, rows, padding, totalcols,
+ &widths, &has_data);
/* return -1 if terminal is not wide enough */
if(totalwidth > getcols()) {
pm_printf(ALPM_LOG_WARNING,
_("insufficient columns available for table display\n"));
return -1;
}
- if(!totalwidth || !widths) {
+ if(!totalwidth || !widths || !has_data) {
return -1;
}
@@ -588,14 +635,15 @@ int table_display(const char *title, const alpm_list_t *header,
printf("%s\n\n", title);
}
- table_print_line(header, totalcols, widths);
+ table_print_line(header, padding, totalcols, widths, has_data);
printf("\n");
for(i = rows; i; i = alpm_list_next(i)) {
- table_print_line(alpm_list_getdata(i), totalcols, widths);
+ table_print_line(i->data, padding, totalcols, widths, has_data);
}
free(widths);
+ free(has_data);
return 0;
}
@@ -614,18 +662,18 @@ void list_display(const char *title, const alpm_list_t *list)
} else {
const unsigned short maxcols = getcols();
size_t cols = len;
- const char *str = alpm_list_getdata(list);
- printf("%s", str);
+ const char *str = list->data;
+ fputs(str, stdout);
cols += string_length(str);
for(i = alpm_list_next(list); i; i = alpm_list_next(i)) {
- str = alpm_list_getdata(i);
+ str = i->data;
size_t s = string_length(str);
/* wrap only if we have enough usable column space */
if(maxcols > len && cols + s + 2 >= maxcols) {
size_t j;
cols = len;
printf("\n");
- for (j = 1; j <= len; j++) {
+ for(j = 1; j <= len; j++) {
printf(" ");
}
} else if(cols != len) {
@@ -633,10 +681,10 @@ void list_display(const char *title, const alpm_list_t *list)
printf(" ");
cols += 2;
}
- printf("%s", str);
+ fputs(str, stdout);
cols += s;
}
- printf("\n");
+ putchar('\n');
}
}
@@ -654,7 +702,7 @@ void list_display_linebreak(const char *title, const alpm_list_t *list)
} else {
const alpm_list_t *i;
/* Print the first element */
- indentprint((const char *) alpm_list_getdata(list), len);
+ indentprint((const char *)list->data, len);
printf("\n");
/* Print the rest */
for(i = alpm_list_next(list); i; i = alpm_list_next(i)) {
@@ -662,7 +710,7 @@ void list_display_linebreak(const char *title, const alpm_list_t *list)
for(j = 1; j <= len; j++) {
printf(" ");
}
- indentprint((const char *) alpm_list_getdata(i), len);
+ indentprint((const char *)i->data, len);
printf("\n");
}
}
@@ -745,7 +793,7 @@ void signature_display(const char *title, alpm_siglist_t *siglist)
}
/* creates a header row for use with table_display */
-static alpm_list_t *create_verbose_header(int dl_size)
+static alpm_list_t *create_verbose_header(void)
{
alpm_list_t *res = NULL;
char *str;
@@ -758,16 +806,14 @@ static alpm_list_t *create_verbose_header(int dl_size)
res = alpm_list_add(res, str);
str = _("Net Change");
res = alpm_list_add(res, str);
- if(dl_size) {
- str = _("Download Size");
- res = alpm_list_add(res, str);
- }
+ str = _("Download Size");
+ res = alpm_list_add(res, str);
return res;
}
/* returns package info as list of strings */
-static alpm_list_t *create_verbose_row(pm_target_t *target, int dl_size)
+static alpm_list_t *create_verbose_row(pm_target_t *target)
{
char *str;
off_t size = 0;
@@ -777,7 +823,12 @@ static alpm_list_t *create_verbose_row(pm_target_t *target, int dl_size)
/* a row consists of the package name, */
if(target->install) {
- pm_asprintf(&str, "%s", alpm_pkg_get_name(target->install));
+ const alpm_db_t *db = alpm_pkg_get_db(target->install);
+ if(db) {
+ pm_asprintf(&str, "%s/%s", alpm_db_get_name(db), alpm_pkg_get_name(target->install));
+ } else {
+ pm_asprintf(&str, "%s", alpm_pkg_get_name(target->install));
+ }
} else {
pm_asprintf(&str, "%s", alpm_pkg_get_name(target->remove));
}
@@ -799,16 +850,14 @@ static alpm_list_t *create_verbose_row(pm_target_t *target, int dl_size)
pm_asprintf(&str, "%.2f %s", human_size, label);
ret = alpm_list_add(ret, str);
- if(dl_size) {
- size = target->install ? alpm_pkg_download_size(target->install) : 0;
+ size = target->install ? alpm_pkg_download_size(target->install) : 0;
+ if(size != 0) {
human_size = humanize_size(size, 'M', 2, &label);
- if(size != 0) {
- pm_asprintf(&str, "%.2f %s", human_size, label);
- } else {
- str = strdup("");
- }
- ret = alpm_list_add(ret, str);
+ pm_asprintf(&str, "%.2f %s", human_size, label);
+ } else {
+ str = NULL;
}
+ ret = alpm_list_add(ret, str);
return ret;
}
@@ -821,7 +870,6 @@ static void _display_targets(alpm_list_t *targets, int verbose)
double size;
off_t isize = 0, rsize = 0, dlsize = 0;
alpm_list_t *i, *rows = NULL, *names = NULL;
- int show_dl_size = config->op == PM_OP_SYNC;
if(!targets) {
return;
@@ -829,7 +877,7 @@ static void _display_targets(alpm_list_t *targets, int verbose)
/* gather package info */
for(i = targets; i; i = alpm_list_next(i)) {
- pm_target_t *target = alpm_list_getdata(i);
+ pm_target_t *target = i->data;
if(target->install) {
dlsize += alpm_pkg_download_size(target->install);
@@ -845,7 +893,7 @@ static void _display_targets(alpm_list_t *targets, int verbose)
for(i = targets; i; i = alpm_list_next(i)) {
pm_target_t *target = i->data;
- rows = alpm_list_add(rows, create_verbose_row(target, show_dl_size));
+ rows = alpm_list_add(rows, create_verbose_row(target));
if(target->install) {
pm_asprintf(&str, "%s-%s", alpm_pkg_get_name(target->install),
alpm_pkg_get_version(target->install));
@@ -864,7 +912,7 @@ static void _display_targets(alpm_list_t *targets, int verbose)
printf("\n");
if(verbose) {
- alpm_list_t *header = create_verbose_header(show_dl_size);
+ alpm_list_t *header = create_verbose_header();
if(table_display(str, header, rows) != 0) {
/* fallback to list display if table wouldn't fit */
list_display(str, names);
@@ -877,7 +925,7 @@ static void _display_targets(alpm_list_t *targets, int verbose)
/* rows is a list of lists of strings, free inner lists here */
for(i = rows; i; i = alpm_list_next(i)) {
- alpm_list_t *lp = alpm_list_getdata(i);
+ alpm_list_t *lp = i->data;
FREELIST(lp);
}
alpm_list_free(rows);
@@ -931,10 +979,10 @@ static int pkg_cmp(const void *p1, const void *p2)
void display_targets(void)
{
alpm_list_t *i, *targets = NULL;
- alpm_db_t *db_local = alpm_option_get_localdb(config->handle);
+ alpm_db_t *db_local = alpm_get_localdb(config->handle);
for(i = alpm_trans_get_add(config->handle); i; i = alpm_list_next(i)) {
- alpm_pkg_t *pkg = alpm_list_getdata(i);
+ alpm_pkg_t *pkg = i->data;
pm_target_t *targ = calloc(1, sizeof(pm_target_t));
if(!targ) return;
targ->install = pkg;
@@ -945,7 +993,7 @@ void display_targets(void)
targets = alpm_list_add(targets, targ);
}
for(i = alpm_trans_get_remove(config->handle); i; i = alpm_list_next(i)) {
- alpm_pkg_t *pkg = alpm_list_getdata(i);
+ alpm_pkg_t *pkg = i->data;
pm_target_t *targ = calloc(1, sizeof(pm_target_t));
if(!targ) return;
targ->remove = pkg;
@@ -980,7 +1028,7 @@ static char *pkg_get_location(alpm_pkg_t *pkg)
case PM_OP_SYNC:
servers = alpm_db_get_servers(alpm_pkg_get_db(pkg));
if(servers) {
- pm_asprintf(&string, "%s/%s", alpm_list_getdata(servers),
+ pm_asprintf(&string, "%s/%s", servers->data,
alpm_pkg_get_filename(pkg));
return string;
}
@@ -1054,7 +1102,7 @@ void print_packages(const alpm_list_t *packages)
config->print_format = strdup("%l");
}
for(i = packages; i; i = alpm_list_next(i)) {
- alpm_pkg_t *pkg = alpm_list_getdata(i);
+ alpm_pkg_t *pkg = i->data;
char *string = strdup(config->print_format);
char *temp = string;
/* %n : pkgname */
@@ -1096,37 +1144,92 @@ void print_packages(const alpm_list_t *packages)
free(size);
free(temp);
}
- printf("%s\n",string);
+ printf("%s\n", string);
free(string);
}
}
-/* Helper function for comparing strings using the
- * alpm "compare func" signature */
-int str_cmp(const void *s1, const void *s2)
+/**
+ * Helper function for comparing depends using the alpm "compare func"
+ * signature. The function descends through the structure in the following
+ * comparison order: name, modifier (e.g., '>', '='), version, description.
+ * @param d1 the first depend structure
+ * @param d2 the second depend structure
+ * @return -1, 0, or 1 if first is <, ==, or > second
+ */
+static int depend_cmp(const void *d1, const void *d2)
{
- return strcmp(s1, s2);
+ const alpm_depend_t *dep1 = d1;
+ const alpm_depend_t *dep2 = d2;
+ int ret;
+
+ ret = strcmp(dep1->name, dep2->name);
+ if(ret == 0) {
+ ret = dep1->mod - dep2->mod;
+ }
+ if(ret == 0) {
+ if(dep1->version && dep2->version) {
+ ret = strcmp(dep1->version, dep2->version);
+ } else if(!dep1->version && dep2->version) {
+ ret = -1;
+ } else if(dep1->version && !dep2->version) {
+ ret = 1;
+ }
+ }
+ if(ret == 0) {
+ if(dep1->desc && dep2->desc) {
+ ret = strcmp(dep1->desc, dep2->desc);
+ } else if(!dep1->desc && dep2->desc) {
+ ret = -1;
+ } else if(dep1->desc && !dep2->desc) {
+ ret = 1;
+ }
+ }
+
+ return ret;
}
void display_new_optdepends(alpm_pkg_t *oldpkg, alpm_pkg_t *newpkg)
{
- alpm_list_t *old = alpm_pkg_get_optdepends(oldpkg);
- alpm_list_t *new = alpm_pkg_get_optdepends(newpkg);
- alpm_list_t *optdeps = alpm_list_diff(new,old,str_cmp);
- if(optdeps) {
+ alpm_list_t *i, *old, *new, *optdeps, *optstrings = NULL;
+
+ old = alpm_pkg_get_optdepends(oldpkg);
+ new = alpm_pkg_get_optdepends(newpkg);
+ optdeps = alpm_list_diff(new, old, depend_cmp);
+
+ /* turn optdepends list into a text list */
+ for(i = optdeps; i; i = alpm_list_next(i)) {
+ alpm_depend_t *optdep = i->data;
+ optstrings = alpm_list_add(optstrings, alpm_dep_compute_string(optdep));
+ }
+
+ if(optstrings) {
printf(_("New optional dependencies for %s\n"), alpm_pkg_get_name(newpkg));
- list_display_linebreak(" ", optdeps);
+ list_display_linebreak(" ", optstrings);
}
+
alpm_list_free(optdeps);
+ FREELIST(optstrings);
}
void display_optdepends(alpm_pkg_t *pkg)
{
- alpm_list_t *optdeps = alpm_pkg_get_optdepends(pkg);
- if(optdeps) {
+ alpm_list_t *i, *optdeps, *optstrings = NULL;
+
+ optdeps = alpm_pkg_get_optdepends(pkg);
+
+ /* turn optdepends list into a text list */
+ for(i = optdeps; i; i = alpm_list_next(i)) {
+ alpm_depend_t *optdep = i->data;
+ optstrings = alpm_list_add(optstrings, alpm_dep_compute_string(optdep));
+ }
+
+ if(optstrings) {
printf(_("Optional dependencies for %s\n"), alpm_pkg_get_name(pkg));
- list_display_linebreak(" ", optdeps);
+ list_display_linebreak(" ", optstrings);
}
+
+ FREELIST(optstrings);
}
static void display_repo_list(const char *dbname, alpm_list_t *list)
@@ -1146,8 +1249,8 @@ void select_display(const alpm_list_t *pkglist)
char *string = NULL;
const char *dbname = NULL;
- for (i = pkglist; i; i = i->next) {
- alpm_pkg_t *pkg = alpm_list_getdata(i);
+ for(i = pkglist; i; i = i->next) {
+ alpm_pkg_t *pkg = i->data;
alpm_db_t *db = alpm_pkg_get_db(pkg);
if(!dbname)
@@ -1189,17 +1292,17 @@ static int multiselect_parse(char *array, int count, char *response)
{
char *str, *saveptr;
- for (str = response; ; str = NULL) {
+ for(str = response; ; str = NULL) {
int include = 1;
int start, end;
+ size_t len;
char *ends = NULL;
char *starts = strtok_r(str, " ", &saveptr);
if(starts == NULL) {
break;
}
- strtrim(starts);
- int len = strlen(starts);
+ len = strtrim(starts);
if(len == 0)
continue;
@@ -1278,6 +1381,7 @@ int multiselect_question(char *array, int count)
if(fgets(response, response_len, stdin)) {
const size_t response_incr = 64;
+ size_t len;
/* handle buffer not being large enough to read full line case */
while(*lastchar == '\0' && lastchar[-1] != '\n') {
response_len += response_incr;
@@ -1294,8 +1398,9 @@ int multiselect_question(char *array, int count)
return -1;
}
}
- strtrim(response);
- if(strlen(response) > 0) {
+
+ len = strtrim(response);
+ if(len > 0) {
if(multiselect_parse(array, count, response) == -1) {
/* only loop if user gave an invalid answer */
continue;
@@ -1338,8 +1443,8 @@ int select_question(int count)
flush_term_input();
if(fgets(response, sizeof(response), stdin)) {
- strtrim(response);
- if(strlen(response) > 0) {
+ size_t len = strtrim(response);
+ if(len > 0) {
int n;
if(parseindex(response, &n, 1, count) != 0)
continue;
@@ -1387,8 +1492,8 @@ static int question(short preset, char *fmt, va_list args)
flush_term_input();
if(fgets(response, sizeof(response), stdin)) {
- strtrim(response);
- if(strlen(response) == 0) {
+ size_t len = strtrim(response);
+ if(len == 0) {
return preset;
}