Upgraded GRUB2 to 2.00 release.
[AROS.git] / arch / all-pc / boot / grub2-aros / util / grub-fstest.c
bloba546b75fe7563b2d8378c196946722bc8cbdcb8c
1 /* grub-fstest.c - debug tool for filesystem driver */
2 /*
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2008,2009,2010 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
20 #include <config.h>
21 #include <grub/types.h>
22 #include <grub/emu/misc.h>
23 #include <grub/util/misc.h>
24 #include <grub/misc.h>
25 #include <grub/device.h>
26 #include <grub/disk.h>
27 #include <grub/file.h>
28 #include <grub/fs.h>
29 #include <grub/env.h>
30 #include <grub/term.h>
31 #include <grub/mm.h>
32 #include <grub/lib/hexdump.h>
33 #include <grub/crypto.h>
34 #include <grub/command.h>
35 #include <grub/i18n.h>
36 #include <grub/zfs/zfs.h>
38 #include <stdio.h>
39 #include <unistd.h>
40 #include <string.h>
41 #include <stdlib.h>
43 #include <sys/types.h>
44 #include <dirent.h>
45 #include <sys/types.h>
46 #include <sys/stat.h>
47 #include <unistd.h>
49 #include "progname.h"
50 #include "argp.h"
52 static grub_err_t
53 execute_command (const char *name, int n, char **args)
55 grub_command_t cmd;
57 cmd = grub_command_find (name);
58 if (! cmd)
59 grub_util_error (_("can't find command `%s'"), name);
61 return (cmd->func) (cmd, n, args);
64 enum {
65 CMD_LS = 1,
66 CMD_CP,
67 CMD_CAT,
68 CMD_CMP,
69 CMD_HEX,
70 CMD_CRC,
71 CMD_BLOCKLIST,
72 CMD_TESTLOAD,
73 CMD_ZFSINFO,
74 CMD_XNU_UUID
76 #define BUF_SIZE 32256
78 static grub_disk_addr_t skip, leng;
79 static int uncompress = 0;
81 static void
82 read_file (char *pathname, int (*hook) (grub_off_t ofs, char *buf, int len))
84 static char buf[BUF_SIZE];
85 grub_file_t file;
87 if ((pathname[0] == '-') && (pathname[1] == 0))
89 grub_device_t dev;
91 dev = grub_device_open (0);
92 if ((! dev) || (! dev->disk))
93 grub_util_error ("%s", grub_errmsg);
95 grub_util_info ("total sectors : %lld",
96 (unsigned long long) dev->disk->total_sectors);
98 if (! leng)
99 leng = (dev->disk->total_sectors << GRUB_DISK_SECTOR_BITS) - skip;
101 while (leng)
103 grub_size_t len;
105 len = (leng > BUF_SIZE) ? BUF_SIZE : leng;
107 if (grub_disk_read (dev->disk, 0, skip, len, buf))
108 grub_util_error (_("disk read fails at offset %lld, length %d"),
109 skip, len);
111 if (hook (skip, buf, len))
112 break;
114 skip += len;
115 leng -= len;
118 grub_device_close (dev);
119 return;
122 if (uncompress == 0)
123 grub_file_filter_disable_compression ();
124 file = grub_file_open (pathname);
125 if (!file)
127 grub_util_error (_("cannot open `%s': %s"), pathname,
128 grub_errmsg);
129 return;
132 grub_util_info ("file size : %lld", (unsigned long long) file->size);
134 if (skip > file->size)
136 grub_util_error (_("invalid skip value %lld"), (unsigned long long) skip);
137 return;
141 grub_off_t ofs, len;
142 ofs = skip;
143 len = file->size - skip;
144 if ((leng) && (leng < len))
145 len = leng;
147 file->offset = skip;
149 while (len)
151 grub_ssize_t sz;
153 sz = grub_file_read (file, buf, (len > BUF_SIZE) ? BUF_SIZE : len);
154 if (sz < 0)
156 grub_util_error (_("read error at offset %llu: %s"), ofs,
157 grub_errmsg);
158 break;
161 if ((sz == 0) || (hook (ofs, buf, sz)))
162 break;
164 ofs += sz;
165 len -= sz;
169 grub_file_close (file);
172 static void
173 cmd_cp (char *src, char *dest)
175 FILE *ff;
177 auto int cp_hook (grub_off_t ofs, char *buf, int len);
178 int cp_hook (grub_off_t ofs, char *buf, int len)
180 (void) ofs;
182 if ((int) fwrite (buf, 1, len, ff) != len)
184 grub_util_error (_("cannot write to `%s': %s"),
185 dest, strerror (errno));
186 return 1;
189 return 0;
192 ff = fopen (dest, "wb");
193 if (ff == NULL)
195 grub_util_error (_("cannot open OS file `%s': %s"), dest,
196 strerror (errno));
197 return;
199 read_file (src, cp_hook);
200 fclose (ff);
203 static void
204 cmd_cat (char *src)
206 auto int cat_hook (grub_off_t ofs, char *buf, int len);
207 int cat_hook (grub_off_t ofs, char *buf, int len)
209 (void) ofs;
211 if ((int) fwrite (buf, 1, len, stdout) != len)
213 grub_util_error (_("cannot write to the stdout: %s"),
214 strerror (errno));
215 return 1;
218 return 0;
221 read_file (src, cat_hook);
224 static void
225 cmd_cmp (char *src, char *dest)
227 FILE *ff;
228 static char buf_1[BUF_SIZE];
230 auto int cmp_hook (grub_off_t ofs, char *buf, int len);
231 int cmp_hook (grub_off_t ofs, char *buf, int len)
233 if ((int) fread (buf_1, 1, len, ff) != len)
235 grub_util_error (_("read error at offset %llu: %s"), ofs,
236 grub_errmsg);
237 return 1;
240 if (grub_memcmp (buf, buf_1, len))
242 int i;
244 for (i = 0; i < len; i++, ofs++)
245 if (buf_1[i] != buf[i])
247 grub_util_error (_("compare fail at offset %llu"), ofs);
248 return 1;
251 return 0;
254 struct stat st;
255 if (stat (dest, &st) == -1)
256 grub_util_error (_("OS file %s open error: %s"), dest,
257 strerror (errno));
259 if (S_ISDIR (st.st_mode))
261 DIR *dir = opendir (dest);
262 struct dirent *entry;
263 if (dir == NULL)
265 grub_util_error (_("OS file %s open error: %s"), dest,
266 strerror (errno));
267 return;
269 while ((entry = readdir (dir)))
271 char *srcnew, *destnew;
272 char *ptr;
273 if (strcmp (entry->d_name, ".") == 0
274 || strcmp (entry->d_name, "..") == 0)
275 continue;
276 srcnew = xmalloc (strlen (src) + sizeof ("/")
277 + strlen (entry->d_name));
278 destnew = xmalloc (strlen (dest) + sizeof ("/")
279 + strlen (entry->d_name));
280 ptr = stpcpy (srcnew, src);
281 *ptr++ = '/';
282 strcpy (ptr, entry->d_name);
283 ptr = stpcpy (destnew, dest);
284 *ptr++ = '/';
285 strcpy (ptr, entry->d_name);
287 if (lstat (destnew, &st) == -1 || (!S_ISREG (st.st_mode)
288 && !S_ISDIR (st.st_mode)))
289 continue;
291 cmd_cmp (srcnew, destnew);
293 closedir (dir);
294 return;
297 ff = fopen (dest, "rb");
298 if (ff == NULL)
300 grub_util_error (_("OS file %s open error: %s"), dest,
301 strerror (errno));
302 return;
305 if ((skip) && (fseeko (ff, skip, SEEK_SET)))
306 grub_util_error (_("cannot seek `%s': %s"), dest,
307 strerror (errno));
309 read_file (src, cmp_hook);
312 grub_uint64_t pre;
313 pre = ftell (ff);
314 fseek (ff, 0, SEEK_END);
315 if (pre != ftell (ff))
316 grub_util_error ("%s", _("unexpected end of file"));
318 fclose (ff);
321 static void
322 cmd_hex (char *pathname)
324 auto int hex_hook (grub_off_t ofs, char *buf, int len);
325 int hex_hook (grub_off_t ofs, char *buf, int len)
327 hexdump (ofs, buf, len);
328 return 0;
331 read_file (pathname, hex_hook);
334 static void
335 cmd_crc (char *pathname)
337 grub_uint8_t crc32_context[GRUB_MD_CRC32->contextsize];
338 GRUB_MD_CRC32->init(crc32_context);
340 auto int crc_hook (grub_off_t ofs, char *buf, int len);
341 int crc_hook (grub_off_t ofs, char *buf, int len)
343 (void) ofs;
345 GRUB_MD_CRC32->write(crc32_context, buf, len);
346 return 0;
349 read_file (pathname, crc_hook);
350 GRUB_MD_CRC32->final(crc32_context);
351 printf ("%08x\n",
352 grub_be_to_cpu32 (grub_get_unaligned32 (GRUB_MD_CRC32->read (crc32_context))));
355 static const char *root = NULL;
356 static int args_count = 0;
357 static int nparm = 0;
358 static int num_disks = 1;
359 static char **images = NULL;
360 static int cmd = 0;
361 static char *debug_str = NULL;
362 static char **args = NULL;
363 static int mount_crypt = 0;
365 static void
366 fstest (int n)
368 char *host_file;
369 char *loop_name;
370 int i;
372 for (i = 0; i < num_disks; i++)
374 char *argv[2];
375 loop_name = grub_xasprintf ("loop%d", i);
376 if (!loop_name)
377 grub_util_error ("%s", grub_errmsg);
379 host_file = grub_xasprintf ("(host)%s", images[i]);
380 if (!host_file)
381 grub_util_error ("%s", grub_errmsg);
383 argv[0] = loop_name;
384 argv[1] = host_file;
386 if (execute_command ("loopback", 2, argv))
387 grub_util_error (_("`loopback' command fails: %s"), grub_errmsg);
389 grub_free (loop_name);
390 grub_free (host_file);
394 if (mount_crypt)
396 char *argv[2] = { xstrdup ("-a"), NULL};
397 if (execute_command ("cryptomount", 1, argv))
398 grub_util_error (_("`cryptomount' command fails: %s"),
399 grub_errmsg);
400 free (argv[0]);
404 grub_ldm_fini ();
405 grub_lvm_fini ();
406 grub_mdraid09_fini ();
407 grub_mdraid1x_fini ();
408 grub_diskfilter_fini ();
409 grub_diskfilter_init ();
410 grub_mdraid09_init ();
411 grub_mdraid1x_init ();
412 grub_lvm_init ();
413 grub_ldm_init ();
415 switch (cmd)
417 case CMD_LS:
418 execute_command ("ls", n, args);
419 break;
420 case CMD_ZFSINFO:
421 execute_command ("zfsinfo", n, args);
422 break;
423 case CMD_CP:
424 cmd_cp (args[0], args[1]);
425 break;
426 case CMD_CAT:
427 cmd_cat (args[0]);
428 break;
429 case CMD_CMP:
430 cmd_cmp (args[0], args[1]);
431 break;
432 case CMD_HEX:
433 cmd_hex (args[0]);
434 break;
435 case CMD_CRC:
436 cmd_crc (args[0]);
437 break;
438 case CMD_BLOCKLIST:
439 execute_command ("blocklist", n, args);
440 grub_printf ("\n");
441 break;
442 case CMD_TESTLOAD:
443 execute_command ("testload", n, args);
444 grub_printf ("\n");
445 break;
446 case CMD_XNU_UUID:
448 grub_device_t dev;
449 grub_fs_t fs;
450 char *uuid = 0;
451 char *argv[3] = { xstrdup ("-l"), NULL, NULL};
452 dev = grub_device_open (n ? args[0] : 0);
453 if (!dev)
454 grub_util_error ("%s", grub_errmsg);
455 fs = grub_fs_probe (dev);
456 if (!fs)
457 grub_util_error ("%s", grub_errmsg);
458 if (!fs->uuid)
459 grub_util_error ("%s", _("couldn't retrieve UUID"));
460 if (fs->uuid (dev, &uuid))
461 grub_util_error ("%s", grub_errmsg);
462 if (!uuid)
463 grub_util_error ("%s", _("couldn't retrieve UUID"));
464 argv[1] = uuid;
465 execute_command ("xnu_uuid", 2, argv);
466 grub_free (argv[0]);
467 grub_free (uuid);
468 grub_device_close (dev);
472 for (i = 0; i < num_disks; i++)
474 char *argv[2];
476 loop_name = grub_xasprintf ("loop%d", i);
477 if (!loop_name)
478 grub_util_error ("%s", grub_errmsg);
480 argv[0] = xstrdup ("-d");
481 argv[1] = loop_name;
483 execute_command ("loopback", 2, argv);
485 grub_free (loop_name);
486 grub_free (argv[0]);
490 static struct argp_option options[] = {
491 {0, 0, 0 , OPTION_DOC, N_("Commands:"), 1},
492 {N_("ls PATH"), 0, 0 , OPTION_DOC, N_("List files in PATH."), 1},
493 {N_("cp FILE LOCAL"), 0, 0, OPTION_DOC, N_("Copy FILE to local file LOCAL."), 1},
494 {N_("cat FILE"), 0, 0 , OPTION_DOC, N_("Copy FILE to standard output."), 1},
495 {N_("cmp FILE LOCAL"), 0, 0, OPTION_DOC, N_("Compare FILE with local file LOCAL."), 1},
496 {N_("hex FILE"), 0, 0 , OPTION_DOC, N_("Show contents of FILE in hex."), 1},
497 {N_("crc FILE"), 0, 0 , OPTION_DOC, N_("Get crc32 checksum of FILE."), 1},
498 {N_("blocklist FILE"), 0, 0, OPTION_DOC, N_("Display blocklist of FILE."), 1},
499 {N_("xnu_uuid DEVICE"), 0, 0, OPTION_DOC, N_("Compute XNU UUID of the device."), 1},
501 {"root", 'r', N_("DEVICE_NAME"), 0, N_("Set root device."), 2},
502 {"skip", 's', N_("NUM"), 0, N_("Skip N bytes from output file."), 2},
503 {"length", 'n', N_("NUM"), 0, N_("Handle N bytes in output file."), 2},
504 {"diskcount", 'c', N_("NUM"), 0, N_("Specify the number of input files."), 2},
505 {"debug", 'd', N_("STRING"), 0, N_("Set debug environment variable."), 2},
506 {"crypto", 'C', NULL, 0, N_("Mount crypto devices."), 2},
507 {"zfs-key", 'K',
508 /* TRANSLATORS: "prompt" is a keyword. */
509 N_("FILE|prompt"), 0, N_("Load zfs crypto key."), 2},
510 {"verbose", 'v', NULL, 0, N_("print verbose messages."), 2},
511 {"uncompress", 'u', NULL, 0, N_("Uncompress data."), 2},
512 {0, 0, 0, 0, 0, 0}
515 /* Print the version information. */
516 static void
517 print_version (FILE *stream, struct argp_state *state)
519 fprintf (stream, "%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION);
521 void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
523 static error_t
524 argp_parser (int key, char *arg, struct argp_state *state)
526 char *p;
528 switch (key)
530 case 'r':
531 root = arg;
532 return 0;
534 case 'K':
535 if (strcmp (arg, "prompt") == 0)
537 char buf[1024];
538 grub_puts_ (N_("Enter ZFS password: "));
539 if (grub_password_get (buf, 1023))
541 grub_zfs_add_key ((grub_uint8_t *) buf, grub_strlen (buf), 1);
544 else
546 FILE *f;
547 ssize_t real_size;
548 grub_uint8_t buf[1024];
549 f = fopen (arg, "rb");
550 if (!f)
552 printf (_("%s: error:"), program_name);
553 printf (_("cannot open `%s': %s"), arg, strerror (errno));
554 printf ("\n");
555 return 0;
557 real_size = fread (buf, 1, 1024, f);
558 if (real_size < 0)
560 printf (_("%s: error:"), program_name);
561 printf (_("cannot read `%s': %s"), arg, strerror (errno));
562 printf ("\n");
563 fclose (f);
564 return 0;
566 grub_zfs_add_key (buf, real_size, 0);
568 return 0;
570 case 'C':
571 mount_crypt = 1;
572 return 0;
574 case 's':
575 skip = grub_strtoul (arg, &p, 0);
576 if (*p == 's')
577 skip <<= GRUB_DISK_SECTOR_BITS;
578 return 0;
580 case 'n':
581 leng = grub_strtoul (arg, &p, 0);
582 if (*p == 's')
583 leng <<= GRUB_DISK_SECTOR_BITS;
584 return 0;
586 case 'c':
587 num_disks = grub_strtoul (arg, NULL, 0);
588 if (num_disks < 1)
590 fprintf (stderr, "%s", _("Invalid disk count.\n"));
591 argp_usage (state);
593 if (args_count != 0)
595 /* TRANSLATORS: disk count is optional but if it's there it must
596 be before disk list. So please don't imply disk count as mandatory.
598 fprintf (stderr, "%s", _("Disk count must precede disks list.\n"));
599 argp_usage (state);
601 return 0;
603 case 'd':
604 debug_str = arg;
605 return 0;
607 case 'v':
608 verbosity++;
609 return 0;
611 case 'u':
612 uncompress = 1;
613 return 0;
615 case ARGP_KEY_END:
616 if (args_count < num_disks)
618 fprintf (stderr, "%s", _("No command is specified.\n"));
619 argp_usage (state);
621 if (args_count - 1 - num_disks < nparm)
623 fprintf (stderr, "%s", _("Not enough parameters to command.\n"));
624 argp_usage (state);
626 return 0;
628 case ARGP_KEY_ARG:
629 break;
631 default:
632 return ARGP_ERR_UNKNOWN;
635 if (args_count < num_disks)
637 if (args_count == 0)
638 images = xmalloc (num_disks * sizeof (images[0]));
639 images[args_count] = canonicalize_file_name (arg);
640 args_count++;
641 return 0;
644 if (args_count == num_disks)
646 if (!grub_strcmp (arg, "ls"))
648 cmd = CMD_LS;
650 else if (!grub_strcmp (arg, "zfsinfo"))
652 cmd = CMD_ZFSINFO;
654 else if (!grub_strcmp (arg, "cp"))
656 cmd = CMD_CP;
657 nparm = 2;
659 else if (!grub_strcmp (arg, "cat"))
661 cmd = CMD_CAT;
662 nparm = 1;
664 else if (!grub_strcmp (arg, "cmp"))
666 cmd = CMD_CMP;
667 nparm = 2;
669 else if (!grub_strcmp (arg, "hex"))
671 cmd = CMD_HEX;
672 nparm = 1;
674 else if (!grub_strcmp (arg, "crc"))
676 cmd = CMD_CRC;
677 nparm = 1;
679 else if (!grub_strcmp (arg, "blocklist"))
681 cmd = CMD_BLOCKLIST;
682 nparm = 1;
684 else if (!grub_strcmp (arg, "testload"))
686 cmd = CMD_TESTLOAD;
687 nparm = 1;
689 else if (grub_strcmp (arg, "xnu_uuid") == 0)
691 cmd = CMD_XNU_UUID;
692 nparm = 0;
694 else
696 fprintf (stderr, _("Invalid command %s.\n"), arg);
697 argp_usage (state);
699 args_count++;
700 return 0;
703 args[args_count - 1 - num_disks] = xstrdup (arg);
704 args_count++;
705 return 0;
708 struct argp argp = {
709 options, argp_parser, N_("IMAGE_PATH COMMANDS"),
710 N_("Debug tool for filesystem driver."),
711 NULL, NULL, NULL
715 main (int argc, char *argv[])
717 const char *default_root;
718 char *alloc_root;
720 set_program_name (argv[0]);
722 grub_util_init_nls ();
724 args = xmalloc (argc * sizeof (args[0]));
726 argp_parse (&argp, argc, argv, 0, 0, 0);
728 /* Initialize all modules. */
729 grub_init_all ();
730 grub_gcry_init_all ();
732 if (debug_str)
733 grub_env_set ("debug", debug_str);
735 default_root = (num_disks == 1) ? "loop0" : "md0";
736 alloc_root = 0;
737 if (root)
739 if ((*root >= '0') && (*root <= '9'))
741 alloc_root = xmalloc (strlen (default_root) + strlen (root) + 2);
743 sprintf (alloc_root, "%s,%s", default_root, root);
744 root = alloc_root;
747 else
748 root = default_root;
750 grub_env_set ("root", root);
752 if (alloc_root)
753 free (alloc_root);
755 /* Do it. */
756 fstest (args_count - 1 - num_disks);
758 /* Free resources. */
759 grub_gcry_fini_all ();
760 grub_fini_all ();
762 return 0;