lib/process: replace pb_run_cmd
[petitboot] / discover / paths.c
1 #define _GNU_SOURCE
2
3 #include <string.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6
7 #include <talloc/talloc.h>
8 #include <system/system.h>
9 #include <process/process.h>
10 #include <url/url.h>
11 #include <log/log.h>
12
13 #include "paths.h"
14
15 #define DEVICE_MOUNT_BASE (LOCAL_STATE_DIR "/petitboot/mnt")
16
17 const char *mount_base(void)
18 {
19         return DEVICE_MOUNT_BASE;
20 }
21
22 char *join_paths(void *alloc_ctx, const char *a, const char *b)
23 {
24         char *full_path;
25
26         full_path = talloc_array(alloc_ctx, char, strlen(a) + strlen(b) + 2);
27
28         strcpy(full_path, a);
29         if (b[0] != '/' && a[strlen(a) - 1] != '/')
30                 strcat(full_path, "/");
31         strcat(full_path, b);
32
33         return full_path;
34 }
35
36
37 static char *local_name(void *ctx)
38 {
39         char *tmp, *ret;
40
41         tmp = tempnam(NULL, "pb-");
42
43         if (!tmp)
44                 return NULL;
45
46         ret = talloc_strdup(ctx, tmp);
47         free(tmp);
48
49         return ret;
50 }
51
52 /**
53  * pb_load_nfs - Mounts the NFS export and returns the local file path.
54  *
55  * Returns the local file path in a talloc'ed character string on success,
56  * or NULL on error.
57  */
58 static char *load_nfs(void *ctx, struct pb_url *url)
59 {
60         char *local, *opts;
61         int result;
62
63         local = local_name(ctx);
64
65         if (!local)
66                 return NULL;
67
68         result = pb_mkdir_recursive(local);
69
70         if (result)
71                 goto fail;
72
73         opts = talloc_strdup(NULL, "ro,nolock,nodiratime");
74
75         if (url->port)
76                 opts = talloc_asprintf_append(opts, ",port=%s", url->port);
77
78         result = process_run_simple(ctx, pb_system_apps.mount, "-t", "nfs",
79                         opts, url->host, url->dir, local, NULL);
80
81         talloc_free(opts);
82
83         if (result)
84                 goto fail;
85
86         local = talloc_asprintf_append(local,  "/%s", url->path);
87         pb_log("%s: local '%s'\n", __func__, local);
88
89         return local;
90
91 fail:
92         pb_rmdir_recursive("/", local);
93         talloc_free(local);
94         return NULL;
95 }
96
97 /**
98  * pb_load_sftp - Loads a remote file via sftp and returns the local file path.
99  *
100  * Returns the local file path in a talloc'ed character string on success,
101  * or NULL on error.
102  */
103 static char *load_sftp(void *ctx, struct pb_url *url)
104 {
105         char *host_path, *local;
106         int result;
107
108         local = local_name(ctx);
109
110         if (!local)
111                 return NULL;
112
113         host_path = talloc_asprintf(local, "%s:%s", url->host, url->path);
114
115         result = process_run_simple(ctx, pb_system_apps.sftp, host_path,
116                         local, NULL);
117
118         if (result)
119                 goto fail;
120
121         return local;
122
123 fail:
124         talloc_free(local);
125         return NULL;
126 }
127
128 /**
129  * pb_load_tftp - Loads a remote file via tftp and returns the local file path.
130  *
131  * Returns the local file path in a talloc'ed character string on success,
132  * or NULL on error.
133  */
134
135 static char *load_tftp(void *ctx, struct pb_url *url)
136 {
137         int result;
138         const char *argv[10];
139         const char **p;
140         char *local;
141
142         local = local_name(ctx);
143
144         if (!local)
145                 return NULL;
146
147         /* first try busybox tftp args */
148
149         p = argv;
150         *p++ = pb_system_apps.tftp;     /* 1 */
151         *p++ = "-g";                    /* 2 */
152         *p++ = "-l";                    /* 3 */
153         *p++ = local;                   /* 4 */
154         *p++ = "-r";                    /* 5 */
155         *p++ = url->path;               /* 6 */
156         *p++ = url->host;               /* 7 */
157         if (url->port)
158                 *p++ = url->port;       /* 8 */
159         *p++ = NULL;                    /* 9 */
160
161         result = process_run_simple_argv(ctx, argv);
162
163         if (!result)
164                 return local;
165
166         /* next try tftp-hpa args */
167
168         p = argv;
169         *p++ = pb_system_apps.tftp;     /* 1 */
170         *p++ = "-m";                    /* 2 */
171         *p++ = "binary";                /* 3 */
172         *p++ = url->host;               /* 4 */
173         if (url->port)
174                 *p++ = url->port;       /* 5 */
175         *p++ = "-c";                    /* 6 */
176         *p++ = "get";                   /* 7 */
177         *p++ = url->path;               /* 8 */
178         *p++ = local;                   /* 9 */
179         *p++ = NULL;                    /* 10 */
180
181         result = process_run_simple_argv(ctx, argv);
182
183         if (!result)
184                 return local;
185
186         talloc_free(local);
187         return NULL;
188 }
189
190 enum wget_flags {
191         wget_empty = 0,
192         wget_no_check_certificate = 1,
193 };
194
195 /**
196  * pb_load_wget - Loads a remote file via wget and returns the local file path.
197  *
198  * Returns the local file path in a talloc'ed character string on success,
199  * or NULL on error.
200  */
201
202 static char *load_wget(void *ctx, struct pb_url *url, enum wget_flags flags)
203 {
204         int result;
205         const char *argv[7];
206         const char **p;
207         char *local;
208
209         local = local_name(ctx);
210
211         if (!local)
212                 return NULL;
213
214         p = argv;
215         *p++ = pb_system_apps.wget;                     /* 1 */
216 #if !defined(DEBUG)
217         *p++ = "--quiet";                               /* 2 */
218 #endif
219         *p++ = "-O";                                    /* 3 */
220         *p++ = local;                                   /* 4 */
221         *p++ = url->full;                               /* 5 */
222         if (flags & wget_no_check_certificate)
223                 *p++ = "--no-check-certificate";        /* 6 */
224         *p++ = NULL;                                    /* 7 */
225
226         result = process_run_simple_argv(ctx, argv);
227
228         if (result)
229                 goto fail;
230
231         return local;
232
233 fail:
234         talloc_free(local);
235         return NULL;
236 }
237
238 /**
239  * load_url - Loads a (possibly) remote URL and returns the local file
240  * path.
241  * @ctx: The talloc context to associate with the returned string.
242  * @URL: The remote file URL.
243  * @tempfile: An optional variable pointer to be set when a temporary local
244  *  file is created.
245  *
246  * Returns the local file path in a talloc'ed character string on success,
247  * or NULL on error.
248  */
249
250 char *load_url(void *ctx, struct pb_url *url, unsigned int *tempfile)
251 {
252         char *local;
253         int tmp = 0;
254
255         if (!url)
256                 return NULL;
257
258         switch (url->scheme) {
259         case pb_url_ftp:
260         case pb_url_http:
261                 local = load_wget(ctx, url, 0);
262                 tmp = !!local;
263                 break;
264         case pb_url_https:
265                 local = load_wget(ctx, url, wget_no_check_certificate);
266                 tmp = !!local;
267                 break;
268         case pb_url_nfs:
269                 local = load_nfs(ctx, url);
270                 tmp = !!local;
271                 break;
272         case pb_url_sftp:
273                 local = load_sftp(ctx, url);
274                 tmp = !!local;
275                 break;
276         case pb_url_tftp:
277                 local = load_tftp(ctx, url);
278                 tmp = !!local;
279                 break;
280         default:
281                 local = talloc_strdup(ctx, url->full);
282                 tmp = 0;
283                 break;
284         }
285
286         if (tempfile)
287                 *tempfile = tmp;
288
289         return local;
290 }