X-Git-Url: http://git.ozlabs.org/?p=petitboot;a=blobdiff_plain;f=discover%2Fpaths.c;h=e76dc35ecb1038c15b9cd2c6580cc1e454f4c850;hp=7fcff9e0eaf3d8cc1ceb2e66cb68bbc279fd647f;hb=6a065198be213092c67071ee77eccf3e493a4cba;hpb=07a5f9f1c50a9185851cd486d732976573d15c4f diff --git a/discover/paths.c b/discover/paths.c index 7fcff9e..e76dc35 100644 --- a/discover/paths.c +++ b/discover/paths.c @@ -14,8 +14,10 @@ #include #include #include +#include "i18n/i18n.h" #include "paths.h" +#include "device-handler.h" #define DEVICE_MOUNT_BASE (LOCAL_STATE_DIR "/petitboot/mnt") @@ -28,6 +30,15 @@ struct load_task { void *async_data; }; +static inline bool have_busybox(void) +{ +#ifdef WITH_BUSYBOX + return true; +#else + return false; +#endif +} + const char *mount_base(void) { return DEVICE_MOUNT_BASE; @@ -99,6 +110,10 @@ static void load_url_process_exit(struct process *process) load_url_result_cleanup_local(result); } + if (result->status == LOAD_OK && process->stdout_data) + device_handler_status_info(process->stdout_data, + _("Download complete: %s"), task->url->file); + /* The load callback may well free the ctx, which was the * talloc parent of the task. Therefore, we want to do our cleanup * before invoking it @@ -110,6 +125,66 @@ static void load_url_process_exit(struct process *process) cb(result, data); } +/* + * Callback to retrieve progress information from Busybox utilities. + * Busybox utilities use a common progress bar format which progress percentage + * and current size can be can be parsed from. + */ +static int busybox_progress_cb(void *arg) +{ + const char *busybox_fmt = "%*s %u%*[%* |]%u%c %*u:%*u:%*u ETA\n"; + struct process_info *procinfo = arg; + char *n, *s, suffix, *line = NULL; + struct device_handler *handler; + unsigned int percentage, size; + struct process *p; + int rc; + + if (!arg) + return -1; + + p = procinfo_get_process(procinfo); + handler = p->stdout_data; + + rc = process_stdout_custom(procinfo, &line); + + if (rc) { + /* Unregister ourselves from progress tracking */ + device_handler_status_download_remove(handler, procinfo); + } + + if (rc || !line) + return rc; + + rc = sscanf(line, busybox_fmt, &percentage, &size, &suffix); + + /* + * Many unrecognised lines are partial updates. If we see a partial + * line with a newline character, see if we can match a valid line + * at the end of stdout_buf + */ + if (rc != 3) { + n = strchr(line, '\n'); + if (n) + for (s = n - 1; s >= p->stdout_buf; s--) + if (*s == '\n') { + rc = sscanf(s + 1, busybox_fmt, + &percentage, &size, &suffix); + break; + } + } + + if (rc != 3) + percentage = size = 0; + + device_handler_status_download(handler, procinfo, + percentage, size, suffix); + + return 0; +} + + + static void load_process_to_local_file(struct load_task *task, const char **argv, int argv_local_idx) { @@ -300,8 +375,9 @@ static void load_tftp(struct load_task *task) } enum wget_flags { - wget_empty = 0, - wget_no_check_certificate = 1, + wget_empty = 0x1, + wget_no_check_certificate = 0x2, + wget_verbose = 0x4, }; /** @@ -324,10 +400,16 @@ static void load_wget(struct load_task *task, int flags) }; int i; + if (task->process->stdout_cb) + flags |= wget_verbose; + i = 3; -#if !defined(DEBUG) - argv[i++] = "--quiet"; +#if defined(DEBUG) + flags |= wget_verbose; #endif + if ((flags & wget_verbose) == 0) + argv[i++] = "--quiet"; + if (flags & wget_no_check_certificate) argv[i++] = "--no-check-certificate"; @@ -370,10 +452,12 @@ static void load_local(struct load_task *task) */ struct load_url_result *load_url_async(void *ctx, struct pb_url *url, - load_url_complete async_cb, void *async_data) + load_url_complete async_cb, void *async_data, + waiter_cb stdout_cb, void *stdout_data) { struct load_url_result *result; struct load_task *task; + int flags = 0; if (!url) return NULL; @@ -383,21 +467,34 @@ struct load_url_result *load_url_async(void *ctx, struct pb_url *url, task->async = async_cb != NULL; task->result = talloc_zero(ctx, struct load_url_result); task->result->task = task; + task->result->url = url; task->process = process_create(task); if (task->async) { task->async_cb = async_cb; task->async_data = async_data; task->process->exit_cb = load_url_process_exit; task->process->data = task; + task->process->stdout_cb = stdout_cb; + task->process->stdout_data = stdout_data; + } + + if (!stdout_cb && stdout_data && have_busybox()) + task->process->stdout_cb = busybox_progress_cb; + + /* Make sure we save output for any task that has a custom handler */ + if (task->process->stdout_cb) { + task->process->add_stderr = true; + task->process->keep_stdout = true; } switch (url->scheme) { case pb_url_ftp: case pb_url_http: - load_wget(task, 0); + load_wget(task, flags); break; case pb_url_https: - load_wget(task, wget_no_check_certificate); + flags |= wget_no_check_certificate; + load_wget(task, flags); break; case pb_url_nfs: load_nfs(task); @@ -429,7 +526,7 @@ struct load_url_result *load_url_async(void *ctx, struct pb_url *url, struct load_url_result *load_url(void *ctx, struct pb_url *url) { - return load_url_async(ctx, url, NULL, NULL); + return load_url_async(ctx, url, NULL, NULL, NULL, NULL); } void load_url_async_cancel(struct load_url_result *res)