diff options
Diffstat (limited to 'src/print.c')
-rw-r--r-- | src/print.c | 249 |
1 files changed, 118 insertions, 131 deletions
diff --git a/src/print.c b/src/print.c index 84c8ed1..829f7f5 100644 --- a/src/print.c +++ b/src/print.c @@ -19,43 +19,125 @@ #include "apk_defines.h" #include "apk_print.h" -static int apk_screen_width = 0; -static int apk_progress_force = 1; -static const char *apk_size_units[] = {"B", "KiB", "MiB", "GiB", "TiB"}; - -void apk_reset_screen_width(void) -{ - apk_screen_width = 0; - apk_progress_force = 1; -} - -int apk_get_screen_width(void) +const char *apk_error_str(int error) { - struct winsize w; - - if (apk_screen_width == 0) { - apk_screen_width = 50; - if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == 0 && - w.ws_col > 25) - apk_screen_width = w.ws_col; + if (error < 0) + error = -error; + switch (error) { + case ENOKEY: + return "UNTRUSTED signature"; + case EKEYREJECTED: + return "BAD signature"; + case EIO: + return "IO ERROR"; + case EBADMSG: + return "BAD archive"; + case ENOMSG: + return "archive does not contain expected data"; + case ENOPKG: + return "could not find a repo which provides this package (check repositories file and run 'apk update')"; + case ECONNABORTED: + return "network connection aborted"; + case ECONNREFUSED: + return "could not connect to server (check repositories file)"; + case ENETUNREACH: + return "network error (check Internet connection and firewall)"; + case ENXIO: + return "DNS lookup error"; + case EREMOTEIO: + return "remote server returned error (try 'apk update')"; + case ETIMEDOUT: + return "operation timed out"; + case EAGAIN: + return "temporary error (try again later)"; + case EAPKBADURL: + return "invalid URL (check your repositories file)"; + case EAPKSTALEINDEX: + return "package mentioned in index not found (try 'apk update')"; + case EAPKFORMAT: + return "package file format error"; + case EAPKDEPFORMAT: + return "package dependency format error"; + default: + return strerror(error); } - - return apk_screen_width; } const char *apk_get_human_size(off_t size, off_t *dest) { + static const char *size_units[] = {"B", "KiB", "MiB", "GiB", "TiB"}; size_t i; off_t s; assert(size >= 0); - for (i = 0, s = size; s >= 10000 && - i < ARRAY_SIZE(apk_size_units); i++) + for (i = 0, s = size; s >= 10000 && i < ARRAY_SIZE(size_units); i++) s /= 1024; if (dest) *dest = s; - return apk_size_units[min(i, ARRAY_SIZE(apk_size_units) - 1)]; + return size_units[min(i, ARRAY_SIZE(size_units) - 1)]; +} + +void apk_url_parse(struct apk_url_print *urlp, const char *url) +{ + const char *authority, *path_or_host, *pw; + + *urlp = (struct apk_url_print) { + .url = "", + .pwmask = "", + .url_or_host = url, + }; + + if (!(authority = strstr(url, "://"))) return; + authority += 3; + path_or_host = strpbrk(authority, "/@"); + if (!path_or_host || *path_or_host == '/') return; + pw = strpbrk(authority, "@:"); + if (!pw || *pw == '@') return; + *urlp = (struct apk_url_print) { + .url = url, + .pwmask = "*", + .url_or_host = path_or_host, + .len_before_pw = pw - url + 1, + }; +} + +void apk_out_reset(struct apk_out *out) +{ + out->width = 0; + out->last_change++; +} + +static int apk_out_get_width(struct apk_out *out) +{ + struct winsize w; + + if (out->width == 0) { + out->width = 50; + if (ioctl(fileno(out->out), TIOCGWINSZ, &w) == 0 && + w.ws_col > 25) + out->width = w.ws_col; + } + + return out->width; +} + +static void log_internal(FILE *dest, const char *prefix, const char *format, va_list va) +{ + if (dest != stdout) fflush(stdout); + if (prefix != NULL) fprintf(dest, "%s", prefix); + vfprintf(dest, format, va); + fprintf(dest, "\n"); + fflush(dest); +} + +void apk_out_fmt(struct apk_out *out, const char *prefix, const char *format, ...) +{ + va_list va; + va_start(va, format); + log_internal(prefix ? out->err : out->out, prefix, format, va); + out->last_change++; + va_end(va); } void apk_print_progress(struct apk_progress *p, size_t done, size_t total) @@ -64,31 +146,31 @@ void apk_print_progress(struct apk_progress *p, size_t done, size_t total) int bar = 0; char buf[64]; /* enough for petabytes... */ int i, percent = 0; - FILE *out = p->out; - - if (p->last_done == done && !apk_progress_force) - return; + FILE *out; + if (p->last_done == done && (!p->out || p->last_out_change == p->out->last_change)) return; if (p->fd != 0) { i = snprintf(buf, sizeof(buf), "%zu/%zu\n", done, total); write(p->fd, buf, i); } p->last_done = done; + if (!p->out) return; + out = p->out->out; if (!out) return; - bar_width = apk_get_screen_width() - 6; + bar_width = apk_out_get_width(p->out) - 6; if (total > 0) { bar = muldiv(bar_width, done, total); percent = muldiv(100, done, total); } - if (bar == p->last_bar && percent == p->last_percent && !apk_progress_force) + if (bar == p->last_bar && percent == p->last_percent && p->last_out_change == p->out->last_change) return; p->last_bar = bar; p->last_percent = percent; - apk_progress_force = 0; + p->last_out_change = p->out->last_change; fprintf(out, "\e7%3i%% ", percent); @@ -103,13 +185,14 @@ void apk_print_progress(struct apk_progress *p, size_t done, size_t total) int apk_print_indented(struct apk_indent *i, apk_blob_t blob) { + FILE *out = i->out->out; if (i->x <= i->indent) - i->x += printf("%*s" BLOB_FMT, i->indent - i->x, "", BLOB_PRINTF(blob)); - else if (i->x + blob.len + 1 >= apk_get_screen_width()) - i->x = printf("\n%*s" BLOB_FMT, i->indent, "", BLOB_PRINTF(blob)) - 1; + i->x += fprintf(out, "%*s" BLOB_FMT, i->indent - i->x, "", BLOB_PRINTF(blob)); + else if (i->x + blob.len + 1 >= apk_out_get_width(i->out)) + i->x = fprintf(out, "\n%*s" BLOB_FMT, i->indent, "", BLOB_PRINTF(blob)) - 1; else - i->x += printf(" " BLOB_FMT, BLOB_PRINTF(blob)); - apk_progress_force = 1; + i->x += fprintf(out, " " BLOB_FMT, BLOB_PRINTF(blob)); + i->out->last_change++; return 0; } @@ -130,99 +213,3 @@ void apk_print_indented_fmt(struct apk_indent *i, const char *fmt, ...) apk_print_indented(i, APK_BLOB_PTR_LEN(tmp, n)); va_end(va); } - -const char *apk_error_str(int error) -{ - if (error < 0) - error = -error; - switch (error) { - case ENOKEY: - return "UNTRUSTED signature"; - case EKEYREJECTED: - return "BAD signature"; - case EIO: - return "IO ERROR"; - case EBADMSG: - return "BAD archive"; - case ENOMSG: - return "archive does not contain expected data"; - case ENOPKG: - return "could not find a repo which provides this package (check repositories file and run 'apk update')"; - case ECONNABORTED: - return "network connection aborted"; - case ECONNREFUSED: - return "could not connect to server (check repositories file)"; - case ENETUNREACH: - return "network error (check Internet connection and firewall)"; - case ENXIO: - return "DNS lookup error"; - case EREMOTEIO: - return "remote server returned error (try 'apk update')"; - case ETIMEDOUT: - return "operation timed out"; - case EAGAIN: - return "temporary error (try again later)"; - case EAPKBADURL: - return "invalid URL (check your repositories file)"; - case EAPKSTALEINDEX: - return "package mentioned in index not found (try 'apk update')"; - case EAPKFORMAT: - return "package file format error"; - case EAPKDEPFORMAT: - return "package dependency format error"; - default: - return strerror(error); - } -} - -static void log_internal(FILE *dest, const char *prefix, const char *format, va_list va) -{ - if (dest != stdout) - fflush(stdout); - if (prefix != NULL) - fprintf(dest, "%s", prefix); - vfprintf(dest, format, va); - fprintf(dest, "\n"); - fflush(dest); - apk_progress_force = 1; -} - -void apk_log(const char *prefix, const char *format, ...) -{ - va_list va; - va_start(va, format); - log_internal(stdout, prefix, format, va); - va_end(va); -} - -void apk_log_err(const char *prefix, const char *format, ...) -{ - va_list va; - va_start(va, format); - log_internal(stderr, prefix, format, va); - va_end(va); -} - -void apk_url_parse(struct apk_url_print *urlp, const char *url) -{ - const char *authority, *path_or_host, *pw; - - *urlp = (struct apk_url_print) { - .url = "", - .pwmask = "", - .url_or_host = url, - }; - - if (!(authority = strstr(url, "://"))) return; - authority += 3; - path_or_host = strpbrk(authority, "/@"); - if (!path_or_host || *path_or_host == '/') return; - pw = strpbrk(authority, "@:"); - if (!pw || *pw == '@') return; - *urlp = (struct apk_url_print) { - .url = url, - .pwmask = "*", - .url_or_host = path_or_host, - .len_before_pw = pw - url + 1, - }; -} |