+ 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;
+ suffix = ' ';
+ }
+
+ 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)
+{
+ int rc;
+
+ task->result->local = local_name(task->result);
+ if (!task->result->local) {
+ task->result->status = LOAD_ERROR;
+ return;
+ }
+ task->result->cleanup_local = true;
+
+ if (argv_local_idx)
+ argv[argv_local_idx] = task->result->local;
+
+ task->process->argv = argv;
+ task->process->path = argv[0];
+
+ if (task->async) {
+ rc = process_run_async(task->process);
+ if (rc) {
+ process_release(task->process);
+ task->process = NULL;
+ }
+ task->result->status = rc ? LOAD_ERROR : LOAD_ASYNC;
+ } else {
+ rc = process_run_sync(task->process);
+ 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;
+ }
+}
+
+/**
+ * pb_load_nfs - Create a mountpoint, set the local file within that
+ * mountpoint, and run the appropriate mount command
+ */
+
+static void load_nfs(struct load_task *task)
+{
+ char *mountpoint, *opts;
+ int rc;
+ const char *argv[] = {
+ pb_system_apps.mount,
+ "-t", "nfs",
+ NULL, /* 3: opts */
+ task->url->host,
+ task->url->dir,
+ NULL, /* 6: mountpoint */
+ NULL,
+ };
+
+ task->result->status = LOAD_ERROR;
+ mountpoint = local_name(task->result);
+ if (!mountpoint)
+ return;
+ task->result->cleanup_local = true;
+ argv[6] = mountpoint;
+
+ rc = pb_mkdir_recursive(mountpoint);
+ if (rc)
+ return;
+
+ opts = talloc_strdup(NULL, "ro,nolock,nodiratime");
+ argv[3] = opts;
+
+ if (task->url->port)
+ opts = talloc_asprintf_append(opts, ",port=%s",
+ task->url->port);
+
+ task->result->local = talloc_asprintf(task->result, "%s/%s",
+ mountpoint,
+ task->url->path);
+
+ task->process->path = pb_system_apps.mount;
+ task->process->argv = argv;
+
+ if (task->async) {
+ rc = process_run_async(task->process);
+ if (rc) {
+ process_release(task->process);
+ task->process = NULL;
+ }
+ task->result->status = rc ? LOAD_ERROR : LOAD_ASYNC;
+ } else {
+ rc = process_run_sync(task->process);
+ task->result->status = rc ? LOAD_ERROR : LOAD_OK;
+ process_release(task->process);
+ task->process = NULL;
+ }
+
+ talloc_free(opts);
+}
+
+static void load_sftp(struct load_task *task)
+{
+ const char *argv[] = {
+ pb_system_apps.sftp,
+ NULL, /* 1: host:path */
+ NULL, /* 2: local file */
+ NULL,
+ };
+
+ argv[1] = talloc_asprintf(task, "%s:%s",
+ task->url->host, task->url->path);
+ load_process_to_local_file(task, argv, 2);
+}
+
+static enum tftp_type check_tftp_type(void *ctx)
+{
+ const char *argv[] = { pb_system_apps.tftp, "-V", NULL };
+ struct process *process;
+ enum tftp_type type;
+ int rc;
+
+ process = process_create(ctx);
+ process->path = pb_system_apps.tftp;
+ process->argv = argv;
+ process->keep_stdout = true;
+ process->add_stderr = true;
+ rc = process_run_sync(process);
+
+ if (rc || !process->stdout_buf || process->stdout_len == 0) {
+ pb_log("Can't check TFTP client type!\n");
+ type = TFTP_TYPE_BROKEN;
+
+ } else if (memmem(process->stdout_buf, process->stdout_len,
+ "tftp-hpa", strlen("tftp-hpa"))) {
+ pb_debug("Found TFTP client type: tftp-hpa\n");
+ type = TFTP_TYPE_HPA;
+
+ } else if (memmem(process->stdout_buf, process->stdout_len,
+ "BusyBox", strlen("BusyBox"))) {
+ pb_debug("Found TFTP client type: BusyBox tftp\n");
+ type = TFTP_TYPE_BUSYBOX;