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/>.
21 #include <grub/util/install.h>
22 #include <grub/util/misc.h>
23 #include <grub/emu/config.h>
27 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
28 #pragma GCC diagnostic ignored "-Wmissing-declarations"
30 #pragma GCC diagnostic error "-Wmissing-prototypes"
31 #pragma GCC diagnostic error "-Wmissing-declarations"
33 static char *output_image
;
36 const struct grub_install_image_target_desc
*format
;
45 static struct argp_option 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},
55 help_filter (int key
, const char *text
, void *input
__attribute__ ((unused
)))
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
);
68 return grub_install_help_filter (key
, text
, input
);
73 argp_parser (int key
, char *arg
, struct argp_state
*state
)
76 key
= GRUB_INSTALL_OPTIONS_INSTALL_CORE_COMPRESS
;
78 if (grub_install_parse (key
, arg
))
88 output_image
= xstrdup (arg
);
93 format
= grub_install_get_image_target (arg
);
96 printf (_("unknown target format %s\n"), arg
);
104 files
[nfiles
++] = xstrdup (arg
);
108 return ARGP_ERR_UNKNOWN
;
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
120 #define MAGIC "ustar"
143 write_zeros (unsigned rsz
)
147 memset (buf
, 0, 512);
148 fwrite (buf
, 1, rsz
, memdisk
);
152 write_pad (unsigned sz
)
154 write_zeros ((~sz
+ 1) & 511);
158 set_tar_value (char *field
, grub_uint32_t val
,
162 for (i
= 0; i
< len
- 1; i
++)
163 field
[len
- 2 - i
] = '0' + ((val
>> (3 * i
)) & 7);
167 compute_checksum (struct head
*hd
)
169 unsigned int chk
= 0;
171 memset (hd
->chksum
, ' ', 8);
172 for (ptr
= (unsigned char *) hd
; ptr
< (unsigned char *) (hd
+ 1); ptr
++)
174 set_tar_value (hd
->chksum
, chk
, 8);
178 add_tar_file (const char *from
,
187 grub_uint32_t mtime
= 0;
190 COMPILE_TIME_ASSERT (sizeof (hd
) == 512);
192 if (grub_util_is_special_file (from
))
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] == '/'))
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
)))
214 if (strcmp (de
->d_name
, ".") == 0)
216 if (strcmp (de
->d_name
, "..") == 0)
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
);
223 grub_util_fd_closedir (d
);
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);
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);
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
);
279 r
= grub_util_fd_read (in
, grub_install_copy_buffer
, GRUB_INSTALL_COPY_BUFFER_SIZE
);
282 fwrite (grub_install_copy_buffer
, 1, r
, memdisk
);
284 grub_util_fd_close (in
);
291 main (int argc
, char *argv
[])
293 const char *pkglibdir
;
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 ();
306 grub_util_error ("%s", _("output file must be specified"));
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
,
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
], '=');
343 add_tar_file (from
, to
);
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
,
357 grub_util_get_target_name (format
), 0);
359 grub_util_unlink (memdisk_img
);