7 #include <talloc/talloc.h>
8 #include <system/system.h>
9 #include <process/process.h>
15 #define DEVICE_MOUNT_BASE (LOCAL_STATE_DIR "/petitboot/mnt")
17 struct load_url_async_data {
18 load_url_callback url_cb;
22 const char *mount_base(void)
24 return DEVICE_MOUNT_BASE;
27 char *join_paths(void *alloc_ctx, const char *a, const char *b)
31 full_path = talloc_array(alloc_ctx, char, strlen(a) + strlen(b) + 2);
34 if (b[0] != '/' && a[strlen(a) - 1] != '/')
35 strcat(full_path, "/");
42 static char *local_name(void *ctx)
46 tmp = tempnam(NULL, "pb-");
51 ret = talloc_strdup(ctx, tmp);
57 static void load_url_exit_cb(struct process *process)
59 struct load_url_async_data *url_data = process->data;
61 pb_log("The download client '%s' [pid %d] exited, rc %d\n",
62 process->path, process->pid, process->exit_status);
64 url_data->url_cb(url_data->ctx, process->exit_status);
66 process_release(process);
70 * pb_load_nfs - Mounts the NFS export and returns the local file path.
72 * Returns the local file path in a talloc'ed character string on success,
75 static char *load_nfs(void *ctx, struct pb_url *url,
76 struct load_url_async_data *url_data)
80 struct process *process;
81 const char *argv[] = {
91 local = local_name(ctx);
96 result = pb_mkdir_recursive(local);
100 opts = talloc_strdup(NULL, "ro,nolock,nodiratime");
104 opts = talloc_asprintf_append(opts, ",port=%s", url->port);
107 process = process_create(ctx);
109 process->path = pb_system_apps.mount;
110 process->argv = argv;
111 process->exit_cb = load_url_exit_cb;
112 process->data = url_data;
114 result = process_run_async(process);
116 process_release(process);
118 result = process_run_simple_argv(ctx, argv);
126 local = talloc_asprintf_append(local, "/%s", url->path);
127 pb_log("%s: local '%s'\n", __func__, local);
132 pb_rmdir_recursive("/", local);
138 * pb_load_sftp - Loads a remote file via sftp and returns the local file path.
140 * Returns the local file path in a talloc'ed character string on success,
143 static char *load_sftp(void *ctx, struct pb_url *url,
144 struct load_url_async_data *url_data)
146 char *host_path, *local;
148 struct process *process;
149 const char *argv[] = {
156 local = local_name(ctx);
161 host_path = talloc_asprintf(local, "%s:%s", url->host, url->path);
165 process = process_create(ctx);
167 process->path = pb_system_apps.sftp;
168 process->argv = argv;
169 process->exit_cb = load_url_exit_cb;
170 process->data = url_data;
172 result = process_run_async(process);
174 process_release(process);
176 result = process_run_simple_argv(ctx, argv);
189 static enum tftp_type check_tftp_type(void *ctx)
191 const char *argv[] = { pb_system_apps.tftp, "-V", NULL };
192 struct process *process;
195 process = process_create(ctx);
196 process->path = pb_system_apps.tftp;
197 process->argv = argv;
198 process->keep_stdout = true;
199 process_run_sync(process);
201 if (!process->stdout_buf || process->stdout_len == 0) {
202 pb_log("Can't check TFTP client type!\n");
203 type = TFTP_TYPE_BROKEN;
205 } else if (memmem(process->stdout_buf, process->stdout_len,
206 "tftp-hpa", strlen("tftp-hpa"))) {
207 pb_debug("Found TFTP client type: tftp-hpa\n");
208 type = TFTP_TYPE_HPA;
210 } else if (memmem(process->stdout_buf, process->stdout_len,
211 "BusyBox", strlen("BusyBox"))) {
212 pb_debug("Found TFTP client type: BusyBox tftp\n");
213 type = TFTP_TYPE_BUSYBOX;
216 pb_log("Unknown TFTP client type!\n");
217 type = TFTP_TYPE_BROKEN;
220 process_release(process);
225 * pb_load_tftp - Loads a remote file via tftp and returns the local file path.
227 * Returns the local file path in a talloc'ed character string on success,
231 static char *load_tftp(void *ctx, struct pb_url *url,
232 struct load_url_async_data *url_data)
235 const char *argv[10];
238 struct process *process;
240 if (tftp_type == TFTP_TYPE_UNKNOWN)
241 tftp_type = check_tftp_type(ctx);
243 if (tftp_type == TFTP_TYPE_BROKEN)
246 local = local_name(ctx);
250 if (tftp_type == TFTP_TYPE_BUSYBOX) {
251 /* first try busybox tftp args */
254 *p++ = pb_system_apps.tftp; /* 1 */
257 *p++ = local; /* 4 */
259 *p++ = url->path; /* 6 */
260 *p++ = url->host; /* 7 */
262 *p++ = url->port; /* 8 */
266 *p++ = pb_system_apps.tftp; /* 1 */
268 *p++ = "binary"; /* 3 */
269 *p++ = url->host; /* 4 */
271 *p++ = url->port; /* 5 */
273 *p++ = "get"; /* 7 */
274 *p++ = url->path; /* 8 */
275 *p++ = local; /* 9 */
276 *p++ = NULL; /* 10 */
280 process = process_create(ctx);
282 process->path = pb_system_apps.tftp;
283 process->argv = argv;
284 process->exit_cb = load_url_exit_cb;
285 process->data = url_data;
287 result = process_run_async(process);
289 result = process_run_simple_argv(ctx, argv);
301 wget_no_check_certificate = 1,
305 * pb_load_wget - Loads a remote file via wget and returns the local file path.
307 * Returns the local file path in a talloc'ed character string on success,
311 static char *load_wget(void *ctx, struct pb_url *url, enum wget_flags flags,
312 struct load_url_async_data *url_data)
318 struct process *process;
320 local = local_name(ctx);
326 *p++ = pb_system_apps.wget; /* 1 */
328 *p++ = "--quiet"; /* 2 */
331 *p++ = local; /* 4 */
332 *p++ = url->full; /* 5 */
333 if (flags & wget_no_check_certificate)
334 *p++ = "--no-check-certificate"; /* 6 */
338 process = process_create(ctx);
340 process->path = pb_system_apps.wget;
341 process->argv = argv;
342 process->exit_cb = load_url_exit_cb;
343 process->data = url_data;
345 result = process_run_async(process);
347 process_release(process);
349 result = process_run_simple_argv(ctx, argv);
363 * load_url - Loads a (possibly) remote URL and returns the local file
365 * @ctx: The talloc context to associate with the returned string.
366 * @url: The remote file URL.
367 * @tempfile: An optional variable pointer to be set when a temporary local
369 * @url_cb: An optional callback pointer if the caller wants to load url
372 * Returns the local file path in a talloc'ed character string on success,
376 char *load_url_async(void *ctx, struct pb_url *url, unsigned int *tempfile,
377 load_url_callback url_cb)
381 struct load_url_async_data *url_data;
389 url_data = talloc_zero(ctx, struct load_url_async_data);
390 url_data->url_cb = url_cb;
394 switch (url->scheme) {
397 local = load_wget(ctx, url, 0, url_data);
401 local = load_wget(ctx, url, wget_no_check_certificate,
406 local = load_nfs(ctx, url, url_data);
410 local = load_sftp(ctx, url, url_data);
414 local = load_tftp(ctx, url, url_data);
418 local = talloc_strdup(ctx, url->full);
429 char *load_url(void *ctx, struct pb_url *url, unsigned int *tempfile)
431 return load_url_async(ctx, url, tempfile, NULL);