]> git.ozlabs.org Git - petitboot/blob - ui/common/loader.c
009871d3109ee348f5704bd530bc0e4422903382
[petitboot] / ui / common / loader.c
1 /*
2  *  Copyright (C) 2009 Sony Computer Entertainment Inc.
3  *  Copyright 2009 Sony Corp.
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; version 2 of the License.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 #if defined(HAVE_CONFIG_H)
20 #include "config.h"
21 #endif
22
23 #define _GNU_SOURCE
24 #include <assert.h>
25 #include <stdlib.h>
26
27 #include "log/log.h"
28 #include <system/system.h>
29 #include "talloc/talloc.h"
30 #include "loader.h"
31 #include "url.h"
32
33
34 /**
35  * pb_local_name - Helper to create a unique local path name.
36  * @ctx: A talloc context.
37  *
38  * Returns the local file path in a talloc'ed character string on success,
39  * or NULL on error.
40  */
41
42 static char *pb_local_name(void *ctx)
43 {
44         char *tmp, *ret;
45
46         tmp = tempnam(NULL, "pb-");
47
48         if (!tmp)
49                 return NULL;
50
51         ret = talloc_strdup(ctx, tmp);
52         free(tmp);
53
54         return ret;
55 }
56
57 /**
58  * pb_load_nfs - Mounts the NFS export and returns the local file path.
59  *
60  * Returns the local file path in a talloc'ed character string on success,
61  * or NULL on error.
62  */
63
64 static char *pb_load_nfs(void *ctx, struct pb_url *url)
65 {
66         int result;
67         const char *argv[8];
68         const char **p;
69         char *local;
70         char *opts;
71
72         local = pb_local_name(ctx);
73
74         if (!local)
75                 return NULL;
76
77         result = pb_mkdir_recursive(local);
78
79         if (result)
80                 goto fail;
81
82         opts = talloc_strdup(NULL, "ro,nolock,nodiratime");
83
84         if (url->port)
85                 opts = talloc_asprintf_append(opts, ",port=%s", url->port);
86
87         p = argv;
88         *p++ = pb_system_apps.mount;    /* 1 */
89         *p++ = "-t";                    /* 2 */
90         *p++ = "nfs";                   /* 3 */
91         *p++ = opts;                    /* 4 */
92         *p++ = url->host;               /* 5 */
93         *p++ = url->dir;                /* 6 */
94         *p++ = local;                   /* 7 */
95         *p++ = NULL;                    /* 8 */
96
97         result = pb_run_cmd(argv, 1);
98
99         talloc_free(opts);
100
101         if (result)
102                 goto fail;
103
104         local = talloc_asprintf_append(local,  "/%s", url->path);
105         pb_log("%s: local '%s'\n", __func__, local);
106
107         return local;
108
109 fail:
110         pb_rmdir_recursive("/", local);
111         talloc_free(local);
112         return NULL;
113 }
114
115 /**
116  * pb_load_sftp - Loads a remote file via sftp and returns the local file path.
117  *
118  * Returns the local file path in a talloc'ed character string on success,
119  * or NULL on error.
120  */
121
122 static char *pb_load_sftp(void *ctx, struct pb_url __attribute__((unused)) *url)
123 {
124         int result;
125         const char *argv[5];
126         const char **p;
127         char *local;
128
129         local = pb_local_name(ctx);
130
131         if (!local)
132                 return NULL;
133
134         p = argv;
135         *p++ = pb_system_apps.sftp;     /* 1 */
136         *p++ = url->host;               /* 2 */
137         *p++ = url->path;               /* 3 */
138         *p++ = local;                   /* 4 */
139         *p++ = NULL;                    /* 5 */
140
141         result = pb_run_cmd(argv, 1);
142
143         if (result)
144                 goto fail;
145
146         return local;
147
148 fail:
149         talloc_free(local);
150         return NULL;
151 }
152
153 /**
154  * pb_load_tftp - Loads a remote file via tftp and returns the local file path.
155  *
156  * Returns the local file path in a talloc'ed character string on success,
157  * or NULL on error.
158  */
159
160 static char *pb_load_tftp(void *ctx, struct pb_url *url)
161 {
162         int result;
163         const char *argv[10];
164         const char **p;
165         char *local;
166
167         local = pb_local_name(ctx);
168
169         if (!local)
170                 return NULL;
171
172         /* first try busybox tftp args */
173
174         p = argv;
175         *p++ = pb_system_apps.tftp;     /* 1 */
176         *p++ = "-g";                    /* 2 */
177         *p++ = "-l";                    /* 3 */
178         *p++ = local;                   /* 4 */
179         *p++ = "-r";                    /* 5 */
180         *p++ = url->path;               /* 6 */
181         *p++ = url->host;               /* 7 */
182         if (url->port)
183                 *p++ = url->port;       /* 8 */
184         *p++ = NULL;                    /* 9 */
185
186         result = pb_run_cmd(argv, 1);
187
188         if (!result)
189                 return local;
190
191         /* next try tftp-hpa args */
192
193         p = argv;
194         *p++ = pb_system_apps.tftp;     /* 1 */
195         *p++ = "-m";                    /* 2 */
196         *p++ = "binary";                /* 3 */
197         *p++ = url->host;               /* 4 */
198         if (url->port)
199                 *p++ = url->port;       /* 5 */
200         *p++ = "-c";                    /* 6 */
201         *p++ = "get";                   /* 7 */
202         *p++ = url->path;               /* 8 */
203         *p++ = local;                   /* 9 */
204         *p++ = NULL;                    /* 10 */
205
206         result = pb_run_cmd(argv, 1);
207
208         if (!result)
209                 return local;
210
211         talloc_free(local);
212         return NULL;
213 }
214
215 enum wget_flags {
216         wget_empty = 0,
217         wget_no_check_certificate = 1,
218 };
219
220 /**
221  * pb_load_wget - Loads a remote file via wget and returns the local file path.
222  *
223  * Returns the local file path in a talloc'ed character string on success,
224  * or NULL on error.
225  */
226
227 static char *pb_load_wget(void *ctx, struct pb_url *url, enum wget_flags flags)
228 {
229         int result;
230         const char *argv[7];
231         const char **p;
232         char *local;
233
234         local = pb_local_name(ctx);
235
236         if (!local)
237                 return NULL;
238
239         p = argv;
240         *p++ = pb_system_apps.wget;                     /* 1 */
241 #if !defined(DEBUG)
242         *p++ = "--quiet";                               /* 2 */
243 #endif
244         *p++ = "-O";                                    /* 3 */
245         *p++ = local;                                   /* 4 */
246         *p++ = url->full;                               /* 5 */
247         if (flags & wget_no_check_certificate)
248                 *p++ = "--no-check-certificate";        /* 6 */
249         *p++ = NULL;                                    /* 7 */
250
251         result = pb_run_cmd(argv, 1);
252
253         if (result)
254                 goto fail;
255
256         return local;
257
258 fail:
259         talloc_free(local);
260         return NULL;
261 }
262
263 /**
264  * pb_load_file - Loads a remote file and returns the local file path.
265  * @ctx: The talloc context to associate with the returned string.
266  * @remote: The remote file URL.
267  * @tempfile: An optional variable pointer to be set when a temporary local
268  *  file is created.
269  *
270  * Returns the local file path in a talloc'ed character string on success,
271  * or NULL on error.
272  */
273
274 char *pb_load_file(void *ctx, const char *remote, unsigned int *tempfile)
275 {
276         char *local;
277         struct pb_url *url = pb_url_parse(NULL, remote);
278
279         if (tempfile)
280                 *tempfile = 0;
281
282         if (!url)
283                 return NULL;
284
285         switch (url->scheme) {
286         case pb_url_ftp:
287         case pb_url_http:
288                 local = pb_load_wget(ctx, url, 0);
289                 if (tempfile && local)
290                         *tempfile = 1;
291                 break;
292         case pb_url_https:
293                 local = pb_load_wget(ctx, url, wget_no_check_certificate);
294                 if (tempfile && local)
295                         *tempfile = 1;
296                 break;
297         case pb_url_nfs:
298                 local = pb_load_nfs(ctx, url);
299                 if (tempfile && local)
300                         *tempfile = 1;
301                 break;
302         case pb_url_sftp:
303                 local = pb_load_sftp(ctx, url);
304                 if (tempfile && local)
305                         *tempfile = 1;
306                 break;
307         case pb_url_tftp:
308                 local = pb_load_tftp(ctx, url);
309                 if (tempfile && local)
310                         *tempfile = 1;
311                 break;
312         default:
313                 local = talloc_strdup(ctx, url->full);
314                 break;
315         }
316
317         talloc_free(url);
318         return local;
319 }