Indentation fix, cleanup.
[AROS.git] / arch / all-pc / boot / grub2-aros / util / grub-mkstandalone.c
blob4907d44c0bde12523c85a2128c96b2fca93b9838
2 /*
3 * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013 Free Software Foundation, Inc.
5 * GRUB 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, either version 3 of the License, or
8 * (at your option) any later version.
10 * GRUB is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
19 #include <config.h>
21 #include <grub/util/install.h>
22 #include <grub/util/misc.h>
23 #include <grub/emu/config.h>
25 #include <string.h>
27 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
28 #pragma GCC diagnostic ignored "-Wmissing-declarations"
29 #include <argp.h>
30 #pragma GCC diagnostic error "-Wmissing-prototypes"
31 #pragma GCC diagnostic error "-Wmissing-declarations"
33 static char *output_image;
34 static char **files;
35 static int nfiles;
36 const struct grub_install_image_target_desc *format;
37 static FILE *memdisk;
39 enum
41 OPTION_OUTPUT = 'o',
42 OPTION_FORMAT = 'O'
45 static struct argp_option options[] = {
46 GRUB_INSTALL_OPTIONS,
47 {"output", 'o', N_("FILE"),
48 0, N_("save output in FILE [required]"), 2},
49 {"format", 'O', N_("FILE"), 0, 0, 2},
50 {"compression", 'C', "xz|none|auto", OPTION_HIDDEN, 0, 2},
51 {0, 0, 0, 0, 0, 0}
54 static char *
55 help_filter (int key, const char *text, void *input __attribute__ ((unused)))
57 switch (key)
59 case 'O':
61 char *formats = grub_install_get_image_targets_string (), *ret;
62 ret = xasprintf ("%s\n%s %s", _("generate an image in FORMAT"),
63 _("available formats:"), formats);
64 free (formats);
65 return ret;
67 default:
68 return grub_install_help_filter (key, text, input);
72 static error_t
73 argp_parser (int key, char *arg, struct argp_state *state)
75 if (key == 'C')
76 key = GRUB_INSTALL_OPTIONS_INSTALL_CORE_COMPRESS;
78 if (grub_install_parse (key, arg))
79 return 0;
81 switch (key)
84 case 'o':
85 if (output_image)
86 free (output_image);
88 output_image = xstrdup (arg);
89 break;
91 case 'O':
93 format = grub_install_get_image_target (arg);
94 if (!format)
96 printf (_("unknown target format %s\n"), arg);
97 argp_usage (state);
98 exit (1);
100 break;
103 case ARGP_KEY_ARG:
104 files[nfiles++] = xstrdup (arg);
105 break;
107 default:
108 return ARGP_ERR_UNKNOWN;
110 return 0;
113 struct argp argp = {
114 options, argp_parser, N_("[OPTION] SOURCE..."),
115 N_("Generate a standalone image (containing all modules) in the selected format")"\v"N_("Graft point syntax (E.g. /boot/grub/grub.cfg=./grub.cfg) is accepted"),
116 NULL, help_filter, NULL
119 /* tar support */
120 #define MAGIC "ustar"
121 struct head
123 char name[100];
124 char mode[8];
125 char uid[8];
126 char gid[8];
127 char size[12];
128 char mtime[12];
129 char chksum[8];
130 char typeflag;
131 char linkname[100];
132 char magic[6];
133 char version[2];
134 char uname[32];
135 char gname[32];
136 char devmajor[8];
137 char devminor[8];
138 char prefix[155];
139 char pad[12];
140 } GRUB_PACKED;
142 static void
143 write_zeros (unsigned rsz)
145 char buf[512];
147 memset (buf, 0, 512);
148 fwrite (buf, 1, rsz, memdisk);
151 static void
152 write_pad (unsigned sz)
154 write_zeros ((~sz + 1) & 511);
157 static void
158 set_tar_value (char *field, grub_uint32_t val,
159 unsigned len)
161 unsigned i;
162 for (i = 0; i < len - 1; i++)
163 field[len - 2 - i] = '0' + ((val >> (3 * i)) & 7);
166 static void
167 compute_checksum (struct head *hd)
169 unsigned int chk = 0;
170 unsigned char *ptr;
171 memset (hd->chksum, ' ', 8);
172 for (ptr = (unsigned char *) hd; ptr < (unsigned char *) (hd + 1); ptr++)
173 chk += *ptr;
174 set_tar_value (hd->chksum, chk, 8);
177 static void
178 add_tar_file (const char *from,
179 const char *to)
181 char *tcn;
182 const char *iptr;
183 char *optr;
184 struct head hd;
185 grub_util_fd_t in;
186 ssize_t r;
187 grub_uint32_t mtime = 0;
188 grub_uint32_t size;
190 COMPILE_TIME_ASSERT (sizeof (hd) == 512);
192 if (grub_util_is_special_file (from))
193 return;
195 mtime = grub_util_get_mtime (from);
197 optr = tcn = xmalloc (strlen (to) + 1);
198 for (iptr = to; *iptr == '/'; iptr++);
199 for (; *iptr; iptr++)
200 if (!(iptr[0] == '/' && iptr[1] == '/'))
201 *optr++ = *iptr;
202 *optr = '\0';
204 if (grub_util_is_directory (from))
206 grub_util_fd_dir_t d;
207 grub_util_fd_dirent_t de;
209 d = grub_util_fd_opendir (from);
211 while ((de = grub_util_fd_readdir (d)))
213 char *fp, *tfp;
214 if (strcmp (de->d_name, ".") == 0)
215 continue;
216 if (strcmp (de->d_name, "..") == 0)
217 continue;
218 fp = grub_util_path_concat (2, from, de->d_name);
219 tfp = xasprintf ("%s/%s", to, de->d_name);
220 add_tar_file (fp, tfp);
221 free (fp);
223 grub_util_fd_closedir (d);
224 free (tcn);
225 return;
228 if (optr - tcn > 99)
230 memset (&hd, 0, sizeof (hd));
231 memcpy (hd.name, tcn, 99);
232 memcpy (hd.mode, "0000600", 7);
233 memcpy (hd.uid, "0001750", 7);
234 memcpy (hd.gid, "0001750", 7);
236 set_tar_value (hd.size, optr - tcn, 12);
237 set_tar_value (hd.mtime, mtime, 12);
238 hd.typeflag = 'L';
239 memcpy (hd.magic, MAGIC, sizeof (hd.magic));
240 memcpy (hd.uname, "grub", 4);
241 memcpy (hd.gname, "grub", 4);
243 compute_checksum (&hd);
245 fwrite (&hd, 1, sizeof (hd), memdisk);
246 fwrite (tcn, 1, optr - tcn, memdisk);
248 write_pad (optr - tcn);
251 in = grub_util_fd_open (from, GRUB_UTIL_FD_O_RDONLY);
252 if (!GRUB_UTIL_FD_IS_VALID (in))
253 grub_util_error (_("cannot open `%s': %s"), from, grub_util_fd_strerror ());
255 if (!grub_install_copy_buffer)
256 grub_install_copy_buffer = xmalloc (GRUB_INSTALL_COPY_BUFFER_SIZE);
258 size = grub_util_get_fd_size (in, from, NULL);
260 memset (&hd, 0, sizeof (hd));
261 memcpy (hd.name, tcn, optr - tcn < 99 ? optr - tcn : 99);
262 memcpy (hd.mode, "0000600", 7);
263 memcpy (hd.uid, "0001750", 7);
264 memcpy (hd.gid, "0001750", 7);
266 set_tar_value (hd.size, size, 12);
267 set_tar_value (hd.mtime, mtime, 12);
268 hd.typeflag = '0';
269 memcpy (hd.magic, MAGIC, sizeof (hd.magic));
270 memcpy (hd.uname, "grub", 4);
271 memcpy (hd.gname, "grub", 4);
273 compute_checksum (&hd);
275 fwrite (&hd, 1, sizeof (hd), memdisk);
277 while (1)
279 r = grub_util_fd_read (in, grub_install_copy_buffer, GRUB_INSTALL_COPY_BUFFER_SIZE);
280 if (r <= 0)
281 break;
282 fwrite (grub_install_copy_buffer, 1, r, memdisk);
284 grub_util_fd_close (in);
286 write_pad (size);
287 free (tcn);
291 main (int argc, char *argv[])
293 const char *pkglibdir;
294 int i;
296 grub_util_host_init (&argc, &argv);
297 grub_util_disable_fd_syncs ();
299 files = xmalloc ((argc + 1) * sizeof (files[0]));
301 argp_parse (&argp, argc, argv, 0, 0, 0);
303 pkglibdir = grub_util_get_pkglibdir ();
305 if (!output_image)
306 grub_util_error ("%s", _("output file must be specified"));
308 if (!format)
309 grub_util_error ("%s", _("Target format not specified (use the -O option)."));
311 if (!grub_install_source_directory)
312 grub_install_source_directory = grub_util_path_concat (2, pkglibdir, grub_util_get_target_dirname (format));
314 enum grub_install_plat plat = grub_install_get_target (grub_install_source_directory);
316 char *memdisk_dir = grub_util_make_temporary_dir ();
317 char *boot_grub = grub_util_path_concat (3, memdisk_dir, "boot", "grub");
318 grub_install_copy_files (grub_install_source_directory,
319 boot_grub, plat);
321 char *memdisk_img = grub_util_make_temporary_file ();
323 memdisk = grub_util_fopen (memdisk_img, "wb");
325 add_tar_file (memdisk_dir, "");
326 for (i = 0; i < nfiles; i++)
328 char *eq = grub_strchr (files[i], '=');
329 char *from, *to;
330 if (!eq)
332 from = files[i];
333 to = files[i];
335 else
337 *eq = '\0';
338 to = files[i];
339 from = eq + 1;
341 while (*to == '/')
342 to++;
343 add_tar_file (from, to);
345 write_zeros (512);
347 fclose (memdisk);
349 grub_util_unlink_recursive (memdisk_dir);
351 grub_install_push_module ("memdisk");
352 grub_install_push_module ("tar");
354 grub_install_make_image_wrap (grub_install_source_directory,
355 "(memdisk)/boot/grub", output_image,
356 memdisk_img, NULL,
357 grub_util_get_target_name (format), 0);
359 grub_util_unlink (memdisk_img);
360 return 0;