ui: callback & boot actions: kexec -> boot
[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, 0);
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[4];
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++ = talloc_asprintf(local, "%s:%s", url->host, url->path);   /* 2 */
137         *p++ = local;                                                   /* 3 */
138         *p++ = NULL;                                                    /* 4 */
139
140         result = pb_run_cmd(argv, 1, 0);
141
142         if (result)
143                 goto fail;
144
145         return local;
146
147 fail:
148         talloc_free(local);
149         return NULL;
150 }
151
152 /**
153  * pb_load_tftp - Loads a remote file via tftp and returns the local file path.
154  *
155  * Returns the local file path in a talloc'ed character string on success,
156  * or NULL on error.
157  */
158
159 static char *pb_load_tftp(void *ctx, struct pb_url *url)
160 {
161         int result;
162         const char *argv[10];
163         const char **p;
164         char *local;
165
166         local = pb_local_name(ctx);
167
168         if (!local)
169                 return NULL;
170
171         /* first try busybox tftp args */
172
173         p = argv;
174         *p++ = pb_system_apps.tftp;     /* 1 */
175         *p++ = "-g";                    /* 2 */
176         *p++ = "-l";                    /* 3 */
177         *p++ = local;                   /* 4 */
178         *p++ = "-r";                    /* 5 */
179         *p++ = url->path;               /* 6 */
180         *p++ = url->host;               /* 7 */
181         if (url->port)
182                 *p++ = url->port;       /* 8 */
183         *p++ = NULL;                    /* 9 */
184
185         result = pb_run_cmd(argv, 1, 0);
186
187         if (!result)
188                 return local;
189
190         /* next try tftp-hpa args */
191
192         p = argv;
193         *p++ = pb_system_apps.tftp;     /* 1 */
194         *p++ = "-m";                    /* 2 */
195         *p++ = "binary";                /* 3 */
196         *p++ = url->host;               /* 4 */
197         if (url->port)
198                 *p++ = url->port;       /* 5 */
199         *p++ = "-c";                    /* 6 */
200         *p++ = "get";                   /* 7 */
201         *p++ = url->path;               /* 8 */
202         *p++ = local;                   /* 9 */
203         *p++ = NULL;                    /* 10 */
204
205         result = pb_run_cmd(argv, 1, 0);
206
207         if (!result)
208                 return local;
209
210         talloc_free(local);
211         return NULL;
212 }
213
214 enum wget_flags {
215         wget_empty = 0,
216         wget_no_check_certificate = 1,
217 };
218
219 /**
220  * pb_load_wget - Loads a remote file via wget and returns the local file path.
221  *
222  * Returns the local file path in a talloc'ed character string on success,
223  * or NULL on error.
224  */
225
226 static char *pb_load_wget(void *ctx, struct pb_url *url, enum wget_flags flags)
227 {
228         int result;
229         const char *argv[7];
230         const char **p;
231         char *local;
232
233         local = pb_local_name(ctx);
234
235         if (!local)
236                 return NULL;
237
238         p = argv;
239         *p++ = pb_system_apps.wget;                     /* 1 */
240 #if !defined(DEBUG)
241         *p++ = "--quiet";                               /* 2 */
242 #endif
243         *p++ = "-O";                                    /* 3 */
244         *p++ = local;                                   /* 4 */
245         *p++ = url->full;                               /* 5 */
246         if (flags & wget_no_check_certificate)
247                 *p++ = "--no-check-certificate";        /* 6 */
248         *p++ = NULL;                                    /* 7 */
249
250         result = pb_run_cmd(argv, 1, 0);
251
252         if (result)
253                 goto fail;
254
255         return local;
256
257 fail:
258         talloc_free(local);
259         return NULL;
260 }
261
262 /**
263  * pb_load_file - Loads a remote file and returns the local file path.
264  * @ctx: The talloc context to associate with the returned string.
265  * @remote: The remote file URL.
266  * @tempfile: An optional variable pointer to be set when a temporary local
267  *  file is created.
268  *
269  * Returns the local file path in a talloc'ed character string on success,
270  * or NULL on error.
271  */
272
273 char *pb_load_file(void *ctx, const char *remote, unsigned int *tempfile)
274 {
275         char *local;
276         struct pb_url *url = pb_url_parse(NULL, remote);
277
278         if (tempfile)
279                 *tempfile = 0;
280
281         if (!url)
282                 return NULL;
283
284         switch (url->scheme) {
285         case pb_url_ftp:
286         case pb_url_http:
287                 local = pb_load_wget(ctx, url, 0);
288                 if (tempfile && local)
289                         *tempfile = 1;
290                 break;
291         case pb_url_https:
292                 local = pb_load_wget(ctx, url, wget_no_check_certificate);
293                 if (tempfile && local)
294                         *tempfile = 1;
295                 break;
296         case pb_url_nfs:
297                 local = pb_load_nfs(ctx, url);
298                 if (tempfile && local)
299                         *tempfile = 1;
300                 break;
301         case pb_url_sftp:
302                 local = pb_load_sftp(ctx, url);
303                 if (tempfile && local)
304                         *tempfile = 1;
305                 break;
306         case pb_url_tftp:
307                 local = pb_load_tftp(ctx, url);
308                 if (tempfile && local)
309                         *tempfile = 1;
310                 break;
311         default:
312                 local = talloc_strdup(ctx, url->full);
313                 break;
314         }
315
316         talloc_free(url);
317         return local;
318 }