]> git.ozlabs.org Git - petitboot/blobdiff - discover/paths.c
Various fixups and checks to make scan-build happy
[petitboot] / discover / paths.c
index e76dc35ecb1038c15b9cd2c6580cc1e454f4c850..16fdd597444d19856f1aad00cb810aa3ee68657e 100644 (file)
@@ -3,11 +3,13 @@
 #endif
 
 #include <assert.h>
+#include <netdb.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <sys/types.h>
+#include <sys/socket.h>
 #include <sys/stat.h>
+#include <sys/types.h>
 
 #include <talloc/talloc.h>
 #include <system/system.h>
 
 #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";
@@ -108,6 +118,8 @@ static void load_url_process_exit(struct process *process)
        } else {
                result->status = LOAD_ERROR;
                load_url_result_cleanup_local(result);
+               pb_debug("Download client stdout buffer:\n%s\n",
+                               process->stdout_buf);
        }
 
        if (result->status == LOAD_OK && process->stdout_data)
@@ -146,7 +158,7 @@ static int busybox_progress_cb(void *arg)
        p = procinfo_get_process(procinfo);
        handler = p->stdout_data;
 
-       rc = process_stdout_custom(procinfo, &line);
+       rc = process_process_stdout(procinfo, &line);
 
        if (rc) {
                /* Unregister ourselves from progress tracking */
@@ -174,8 +186,10 @@ static int busybox_progress_cb(void *arg)
                                }
        }
 
-       if (rc != 3)
+       if (rc != 3) {
                percentage = size = 0;
+               suffix = ' ';
+       }
 
        device_handler_status_download(handler, procinfo,
                        percentage, size, suffix);
@@ -425,18 +439,101 @@ 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;
        }
+
+       if (task->async_cb)
+               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 +554,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 +585,18 @@ 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) {
+               if (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;
+               }
+               freeaddrinfo(res);
+       }
+
        switch (url->scheme) {
        case pb_url_ftp:
        case pb_url_http:
@@ -518,7 +628,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;