-#define _GNU_SOURCE
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
static char *local_name(void *ctx)
{
- char *tmp, *ret;
+ char *ret, tmp[] = "/tmp/pb-XXXXXX";
+ int fd;
- tmp = tempnam(NULL, "pb-");
+ fd = mkstemp(tmp);
- if (!tmp)
+ if (fd < 0)
return NULL;
+ close(fd);
+
ret = talloc_strdup(ctx, tmp);
- free(tmp);
return ret;
}
data = task->async_data;
cb = task->async_cb;
- result->status = process->exit_status == 0 ? LOAD_OK : LOAD_ERROR;
- if (result->status == LOAD_ERROR)
+ if (result->status == LOAD_CANCELLED) {
+ load_url_result_cleanup_local(result);
+ } else if (process_exit_ok(process)) {
+ result->status = LOAD_OK;
+ } else {
+ result->status = LOAD_ERROR;
load_url_result_cleanup_local(result);
+ }
/* The load callback may well free the ctx, which was the
* talloc parent of the task. Therefore, we want to do our cleanup
*/
process_release(process);
talloc_free(task);
+ result->task = NULL;
cb(result, data);
}
task->result->status = rc ? LOAD_ERROR : LOAD_ASYNC;
} else {
rc = process_run_sync(task->process);
- task->result->status = rc ? LOAD_ERROR : LOAD_OK;
+ if (rc || !process_exit_ok(task->process))
+ task->result->status = LOAD_ERROR;
+ else
+ task->result->status = LOAD_OK;
process_release(task->process);
task->process = NULL;
}
process->path = pb_system_apps.tftp;
process->argv = argv;
process->keep_stdout = true;
+ process->add_stderr = true;
process_run_sync(process);
if (!process->stdout_buf || process->stdout_len == 0) {
load_process_to_local_file(task, argv, 2);
}
+/* Although we don't need to load anything for a local path (we just return
+ * the path from the file:// URL), the other load helpers will error-out on
+ * non-existant files. So, do the same here with an access() check on the local
+ * filename.
+ */
+static void load_local(struct load_task *task)
+{
+ int rc;
+
+ rc = access(task->url->path, F_OK);
+ if (rc) {
+ task->result->status = LOAD_ERROR;
+ } else {
+ task->result->local = talloc_strdup(task->result,
+ task->url->path);
+ task->result->status = LOAD_OK;
+ }
+}
+
/**
* load_url - Loads a (possibly) remote URL and returns the local file
* path.
task->url = url;
task->async = async_cb != NULL;
task->result = talloc_zero(ctx, struct load_url_result);
+ task->result->task = task;
task->process = process_create(task);
if (task->async) {
task->async_cb = async_cb;
load_tftp(task);
break;
default:
- task->result->local = talloc_strdup(task->result,
- url->path);
- task->result->status = LOAD_OK;
+ load_local(task);
break;
}
{
return load_url_async(ctx, url, NULL, NULL);
}
+
+void load_url_async_cancel(struct load_url_result *res)
+{
+ struct load_task *task = res->task;
+
+ /* the completion callback may have already been called; this clears
+ * res->task */
+ if (!task)
+ return;
+
+ if (res->status == LOAD_CANCELLED)
+ return;
+
+ assert(task->async);
+ assert(task->process);
+
+ res->status = LOAD_CANCELLED;
+ process_stop_async(task->process);
+}