X-Git-Url: http://git.ozlabs.org/?p=petitboot;a=blobdiff_plain;f=discover%2Fpaths.c;h=dd54ba2bc178289e6ba240c04e24af485ee8c1cf;hp=e76dc35ecb1038c15b9cd2c6580cc1e454f4c850;hb=b0c603d007174e75452c1c14402d62d305da76ab;hpb=6a065198be213092c67071ee77eccf3e493a4cba diff --git a/discover/paths.c b/discover/paths.c index e76dc35..dd54ba2 100644 --- a/discover/paths.c +++ b/discover/paths.c @@ -3,11 +3,13 @@ #endif #include +#include #include #include #include -#include +#include #include +#include #include #include @@ -18,9 +20,20 @@ #include "paths.h" #include "device-handler.h" +#include "sysinfo.h" #define DEVICE_MOUNT_BASE (LOCAL_STATE_DIR "/petitboot/mnt") + +struct list pending_network_jobs; + +struct network_job { + struct load_task *task; + int flags; + + struct list_item list; +}; + struct load_task { struct pb_url *url; struct process *process; @@ -30,15 +43,6 @@ 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; @@ -60,6 +64,12 @@ char *join_paths(void *alloc_ctx, const char *a, const char *b) #ifndef PETITBOOT_TEST +#ifdef WITH_BUSYBOX +static inline bool have_busybox(void) { return true; } +#else +static inline bool have_busybox(void) { return false; } +#endif + static char *local_name(void *ctx) { char *ret, tmp[] = "/tmp/pb-XXXXXX"; @@ -425,18 +435,100 @@ static void load_wget(struct load_task *task, int flags) */ static void load_local(struct load_task *task) { + struct load_url_result *result = task->result; int rc; rc = access(task->url->path, F_OK); if (rc) { - task->result->status = LOAD_ERROR; + result->status = LOAD_ERROR; } else { - task->result->local = talloc_strdup(task->result, - task->url->path); - task->result->status = LOAD_OK; + result->local = talloc_strdup(task->result, task->url->path); + result->status = LOAD_OK; + } + + task->async_cb(task->result, task->async_data); +} + +static void load_url_async_start_pending(struct load_task *task, int flags) +{ + pb_log("Starting pending job for %s\n", task->url->full); + + switch (task->url->scheme) { + case pb_url_ftp: + case pb_url_http: + load_wget(task, flags); + break; + case pb_url_https: + flags |= wget_no_check_certificate; + load_wget(task, flags); + break; + case pb_url_nfs: + load_nfs(task); + break; + case pb_url_sftp: + load_sftp(task); + break; + case pb_url_tftp: + load_tftp(task); + break; + default: + /* Shouldn't be a need via this path but.. */ + load_local(task); + break; + } + + if (task->result->status == LOAD_ERROR) { + pb_log("Pending job failed for %s\n", task->url->full); + load_url_result_cleanup_local(task->result); + talloc_free(task->result); + talloc_free(task); } } +void pending_network_jobs_start(void) +{ + struct network_job *job, *tmp; + + if (!pending_network_jobs.head.next) + return; + + list_for_each_entry_safe(&pending_network_jobs, job, tmp, list) { + load_url_async_start_pending(job->task, job->flags); + list_remove(&job->list); + } +} + +void pending_network_jobs_cancel(void) +{ + struct network_job *job, *tmp; + + if (!pending_network_jobs.head.next) + return; + + list_for_each_entry_safe(&pending_network_jobs, job, tmp, list) + talloc_free(job); + list_init(&pending_network_jobs); +} + +static void pending_network_jobs_add(struct load_task *task, int flags) +{ + struct network_job *job; + + if (!pending_network_jobs.head.next) + list_init(&pending_network_jobs); + + job = talloc(task, struct network_job); + if (!job) { + pb_log("Failed to allocate space for pending job\n"); + return; + } + + job->task = task; + job->flags = flags; + list_add_tail(&pending_network_jobs, &job->list); +} + + /** * load_url - Loads a (possibly) remote URL and returns the local file * path. @@ -457,6 +549,7 @@ struct load_url_result *load_url_async(void *ctx, struct pb_url *url, { struct load_url_result *result; struct load_task *task; + struct addrinfo *res; int flags = 0; if (!url) @@ -487,6 +580,16 @@ struct load_url_result *load_url_async(void *ctx, struct pb_url *url, task->process->keep_stdout = true; } + /* If the url is remote but network is not yet available queue up this + * load for later */ + if (url->scheme != pb_url_file && + getaddrinfo(url->host, NULL, NULL, &res) != 0) { + pb_log("load task for %s queued pending network\n", url->full); + pending_network_jobs_add(task, flags); + task->result->status = LOAD_ASYNC; + return task->result; + } + switch (url->scheme) { case pb_url_ftp: case pb_url_http: @@ -518,7 +621,7 @@ struct load_url_result *load_url_async(void *ctx, struct pb_url *url, return NULL; } - if (!task->async) + if (!task->async || result->status == LOAD_OK) talloc_free(task); return result;