Indentation fix, cleanup.
[AROS.git] / arch / all-pc / boot / grub2-aros / util / grub-fstest.c
blob02cd3e3e2855f95ec18014aab707acec961ba8b4
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>
37 #include <grub/emu/hostfile.h>
39 #include <stdio.h>
40 #include <errno.h>
41 #include <string.h>
43 #include "progname.h"
44 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
45 #pragma GCC diagnostic ignored "-Wmissing-declarations"
46 #include "argp.h"
47 #pragma GCC diagnostic error "-Wmissing-prototypes"
48 #pragma GCC diagnostic error "-Wmissing-declarations"
50 static grub_err_t
51 execute_command (const char *name, int n, char **args)
53 grub_command_t cmd;
55 cmd = grub_command_find (name);
56 if (! cmd)
57 grub_util_error (_("can't find command `%s'"), name);
59 return (cmd->func) (cmd, n, args);
62 enum {
63 CMD_LS = 1,
64 CMD_CP,
65 CMD_CAT,
66 CMD_CMP,
67 CMD_HEX,
68 CMD_CRC,
69 CMD_BLOCKLIST,
70 CMD_TESTLOAD,
71 CMD_ZFSINFO,
72 CMD_XNU_UUID
74 #define BUF_SIZE 32256
76 static grub_disk_addr_t skip, leng;
77 static int uncompress = 0;
79 static void
80 read_file (char *pathname, int (*hook) (grub_off_t ofs, char *buf, int len, void *hook_arg), void *hook_arg)
82 static char buf[BUF_SIZE];
83 grub_file_t file;
85 if ((pathname[0] == '-') && (pathname[1] == 0))
87 grub_device_t dev;
89 dev = grub_device_open (0);
90 if ((! dev) || (! dev->disk))
91 grub_util_error ("%s", grub_errmsg);
93 grub_util_info ("total sectors : %" GRUB_HOST_PRIuLONG_LONG,
94 (unsigned long long) dev->disk->total_sectors);
96 if (! leng)
97 leng = (dev->disk->total_sectors << GRUB_DISK_SECTOR_BITS) - skip;
99 while (leng)
101 grub_size_t len;
103 len = (leng > BUF_SIZE) ? BUF_SIZE : leng;
105 if (grub_disk_read (dev->disk, 0, skip, len, buf))
107 char *msg = grub_xasprintf (_("disk read fails at offset %lld, length %lld"),
108 (long long) skip, (long long) len);
109 grub_util_error ("%s", msg);
112 if (hook (skip, buf, len, hook_arg))
113 break;
115 skip += len;
116 leng -= len;
119 grub_device_close (dev);
120 return;
123 if (uncompress == 0)
124 grub_file_filter_disable_compression ();
125 file = grub_file_open (pathname);
126 if (!file)
128 grub_util_error (_("cannot open `%s': %s"), pathname,
129 grub_errmsg);
130 return;
133 grub_util_info ("file size : %" GRUB_HOST_PRIuLONG_LONG,
134 (unsigned long long) file->size);
136 if (skip > file->size)
138 char *msg = grub_xasprintf (_("invalid skip value %lld"),
139 (unsigned long long) skip);
140 grub_util_error ("%s", msg);
141 return;
145 grub_off_t ofs, len;
146 ofs = skip;
147 len = file->size - skip;
148 if ((leng) && (leng < len))
149 len = leng;
151 file->offset = skip;
153 while (len)
155 grub_ssize_t sz;
157 sz = grub_file_read (file, buf, (len > BUF_SIZE) ? BUF_SIZE : len);
158 if (sz < 0)
160 char *msg = grub_xasprintf (_("read error at offset %llu: %s"),
161 (unsigned long long) ofs, grub_errmsg);
162 grub_util_error ("%s", msg);
163 break;
166 if ((sz == 0) || (hook (ofs, buf, sz, hook_arg)))
167 break;
169 ofs += sz;
170 len -= sz;
174 grub_file_close (file);
177 struct cp_hook_ctx
179 FILE *ff;
180 const char *dest;
183 static int
184 cp_hook (grub_off_t ofs, char *buf, int len, void *_ctx)
186 struct cp_hook_ctx *ctx = _ctx;
187 (void) ofs;
189 if ((int) fwrite (buf, 1, len, ctx->ff) != len)
191 grub_util_error (_("cannot write to `%s': %s"),
192 ctx->dest, strerror (errno));
193 return 1;
196 return 0;
199 static void
200 cmd_cp (char *src, const char *dest)
202 struct cp_hook_ctx ctx =
204 .dest = dest
207 ctx.ff = grub_util_fopen (dest, "wb");
208 if (ctx.ff == NULL)
210 grub_util_error (_("cannot open OS file `%s': %s"), dest,
211 strerror (errno));
212 return;
214 read_file (src, cp_hook, &ctx);
215 fclose (ctx.ff);
218 static int
219 cat_hook (grub_off_t ofs, char *buf, int len, void *_arg __attribute__ ((unused)))
221 (void) ofs;
223 if ((int) fwrite (buf, 1, len, stdout) != len)
225 grub_util_error (_("cannot write to the stdout: %s"),
226 strerror (errno));
227 return 1;
230 return 0;
233 static void
234 cmd_cat (char *src)
236 read_file (src, cat_hook, 0);
239 static int
240 cmp_hook (grub_off_t ofs, char *buf, int len, void *ff_in)
242 FILE *ff = ff_in;
243 static char buf_1[BUF_SIZE];
244 if ((int) fread (buf_1, 1, len, ff) != len)
246 char *msg = grub_xasprintf (_("read error at offset %llu: %s"),
247 (unsigned long long) ofs, grub_errmsg);
248 grub_util_error ("%s", msg);
249 return 1;
252 if (grub_memcmp (buf, buf_1, len) != 0)
254 int i;
256 for (i = 0; i < len; i++, ofs++)
257 if (buf_1[i] != buf[i])
259 char *msg = grub_xasprintf (_("compare fail at offset %llu"),
260 (unsigned long long) ofs);
261 grub_util_error ("%s", msg);
262 return 1;
265 return 0;
269 static void
270 cmd_cmp (char *src, char *dest)
272 FILE *ff;
274 if (grub_util_is_directory (dest))
276 grub_util_fd_dir_t dir = grub_util_fd_opendir (dest);
277 grub_util_fd_dirent_t entry;
278 if (dir == NULL)
280 grub_util_error (_("OS file %s open error: %s"), dest,
281 grub_util_fd_strerror ());
282 return;
284 while ((entry = grub_util_fd_readdir (dir)))
286 char *srcnew, *destnew;
287 char *ptr;
288 if (strcmp (entry->d_name, ".") == 0
289 || strcmp (entry->d_name, "..") == 0)
290 continue;
291 srcnew = xmalloc (strlen (src) + sizeof ("/")
292 + strlen (entry->d_name));
293 destnew = xmalloc (strlen (dest) + sizeof ("/")
294 + strlen (entry->d_name));
295 ptr = grub_stpcpy (srcnew, src);
296 *ptr++ = '/';
297 strcpy (ptr, entry->d_name);
298 ptr = grub_stpcpy (destnew, dest);
299 *ptr++ = '/';
300 strcpy (ptr, entry->d_name);
302 if (grub_util_is_special_file (destnew))
303 continue;
305 cmd_cmp (srcnew, destnew);
307 grub_util_fd_closedir (dir);
308 return;
311 ff = grub_util_fopen (dest, "rb");
312 if (ff == NULL)
314 grub_util_error (_("OS file %s open error: %s"), dest,
315 strerror (errno));
316 return;
319 if ((skip) && (fseeko (ff, skip, SEEK_SET)))
320 grub_util_error (_("cannot seek `%s': %s"), dest,
321 strerror (errno));
323 read_file (src, cmp_hook, ff);
326 grub_uint64_t pre;
327 pre = ftell (ff);
328 fseek (ff, 0, SEEK_END);
329 if (pre != ftell (ff))
330 grub_util_error ("%s", _("unexpected end of file"));
332 fclose (ff);
335 static int
336 hex_hook (grub_off_t ofs, char *buf, int len, void *arg __attribute__ ((unused)))
338 hexdump (ofs, buf, len);
339 return 0;
342 static void
343 cmd_hex (char *pathname)
345 read_file (pathname, hex_hook, 0);
348 static int
349 crc_hook (grub_off_t ofs, char *buf, int len, void *crc_ctx)
351 (void) ofs;
353 GRUB_MD_CRC32->write(crc_ctx, buf, len);
354 return 0;
357 static void
358 cmd_crc (char *pathname)
360 grub_uint8_t *crc32_context = xmalloc (GRUB_MD_CRC32->contextsize);
361 GRUB_MD_CRC32->init(crc32_context);
363 read_file (pathname, crc_hook, crc32_context);
364 GRUB_MD_CRC32->final(crc32_context);
365 printf ("%08x\n",
366 grub_be_to_cpu32 (grub_get_unaligned32 (GRUB_MD_CRC32->read (crc32_context))));
367 free (crc32_context);
370 static const char *root = NULL;
371 static int args_count = 0;
372 static int nparm = 0;
373 static int num_disks = 1;
374 static char **images = NULL;
375 static int cmd = 0;
376 static char *debug_str = NULL;
377 static char **args = NULL;
378 static int mount_crypt = 0;
380 static void
381 fstest (int n)
383 char *host_file;
384 char *loop_name;
385 int i;
387 for (i = 0; i < num_disks; i++)
389 char *argv[2];
390 loop_name = grub_xasprintf ("loop%d", i);
391 if (!loop_name)
392 grub_util_error ("%s", grub_errmsg);
394 host_file = grub_xasprintf ("(host)%s", images[i]);
395 if (!host_file)
396 grub_util_error ("%s", grub_errmsg);
398 argv[0] = loop_name;
399 argv[1] = host_file;
401 if (execute_command ("loopback", 2, argv))
402 grub_util_error (_("`loopback' command fails: %s"), grub_errmsg);
404 grub_free (loop_name);
405 grub_free (host_file);
409 if (mount_crypt)
411 char *argv[2] = { xstrdup ("-a"), NULL};
412 if (execute_command ("cryptomount", 1, argv))
413 grub_util_error (_("`cryptomount' command fails: %s"),
414 grub_errmsg);
415 free (argv[0]);
419 grub_ldm_fini ();
420 grub_lvm_fini ();
421 grub_mdraid09_fini ();
422 grub_mdraid1x_fini ();
423 grub_diskfilter_fini ();
424 grub_diskfilter_init ();
425 grub_mdraid09_init ();
426 grub_mdraid1x_init ();
427 grub_lvm_init ();
428 grub_ldm_init ();
430 switch (cmd)
432 case CMD_LS:
433 execute_command ("ls", n, args);
434 break;
435 case CMD_ZFSINFO:
436 execute_command ("zfsinfo", n, args);
437 break;
438 case CMD_CP:
439 cmd_cp (args[0], args[1]);
440 break;
441 case CMD_CAT:
442 cmd_cat (args[0]);
443 break;
444 case CMD_CMP:
445 cmd_cmp (args[0], args[1]);
446 break;
447 case CMD_HEX:
448 cmd_hex (args[0]);
449 break;
450 case CMD_CRC:
451 cmd_crc (args[0]);
452 break;
453 case CMD_BLOCKLIST:
454 execute_command ("blocklist", n, args);
455 grub_printf ("\n");
456 break;
457 case CMD_TESTLOAD:
458 execute_command ("testload", n, args);
459 grub_printf ("\n");
460 break;
461 case CMD_XNU_UUID:
463 grub_device_t dev;
464 grub_fs_t fs;
465 char *uuid = 0;
466 char *argv[3] = { xstrdup ("-l"), NULL, NULL};
467 dev = grub_device_open (n ? args[0] : 0);
468 if (!dev)
469 grub_util_error ("%s", grub_errmsg);
470 fs = grub_fs_probe (dev);
471 if (!fs)
472 grub_util_error ("%s", grub_errmsg);
473 if (!fs->uuid)
474 grub_util_error ("%s", _("couldn't retrieve UUID"));
475 if (fs->uuid (dev, &uuid))
476 grub_util_error ("%s", grub_errmsg);
477 if (!uuid)
478 grub_util_error ("%s", _("couldn't retrieve UUID"));
479 argv[1] = uuid;
480 execute_command ("xnu_uuid", 2, argv);
481 grub_free (argv[0]);
482 grub_free (uuid);
483 grub_device_close (dev);
487 for (i = 0; i < num_disks; i++)
489 char *argv[2];
491 loop_name = grub_xasprintf ("loop%d", i);
492 if (!loop_name)
493 grub_util_error ("%s", grub_errmsg);
495 argv[0] = xstrdup ("-d");
496 argv[1] = loop_name;
498 execute_command ("loopback", 2, argv);
500 grub_free (loop_name);
501 grub_free (argv[0]);
505 static struct argp_option options[] = {
506 {0, 0, 0 , OPTION_DOC, N_("Commands:"), 1},
507 {N_("ls PATH"), 0, 0 , OPTION_DOC, N_("List files in PATH."), 1},
508 {N_("cp FILE LOCAL"), 0, 0, OPTION_DOC, N_("Copy FILE to local file LOCAL."), 1},
509 {N_("cat FILE"), 0, 0 , OPTION_DOC, N_("Copy FILE to standard output."), 1},
510 {N_("cmp FILE LOCAL"), 0, 0, OPTION_DOC, N_("Compare FILE with local file LOCAL."), 1},
511 {N_("hex FILE"), 0, 0 , OPTION_DOC, N_("Show contents of FILE in hex."), 1},
512 {N_("crc FILE"), 0, 0 , OPTION_DOC, N_("Get crc32 checksum of FILE."), 1},
513 {N_("blocklist FILE"), 0, 0, OPTION_DOC, N_("Display blocklist of FILE."), 1},
514 {N_("xnu_uuid DEVICE"), 0, 0, OPTION_DOC, N_("Compute XNU UUID of the device."), 1},
516 {"root", 'r', N_("DEVICE_NAME"), 0, N_("Set root device."), 2},
517 {"skip", 's', N_("NUM"), 0, N_("Skip N bytes from output file."), 2},
518 {"length", 'n', N_("NUM"), 0, N_("Handle N bytes in output file."), 2},
519 {"diskcount", 'c', N_("NUM"), 0, N_("Specify the number of input files."), 2},
520 {"debug", 'd', N_("STRING"), 0, N_("Set debug environment variable."), 2},
521 {"crypto", 'C', NULL, 0, N_("Mount crypto devices."), 2},
522 {"zfs-key", 'K',
523 /* TRANSLATORS: "prompt" is a keyword. */
524 N_("FILE|prompt"), 0, N_("Load zfs crypto key."), 2},
525 {"verbose", 'v', NULL, 0, N_("print verbose messages."), 2},
526 {"uncompress", 'u', NULL, 0, N_("Uncompress data."), 2},
527 {0, 0, 0, 0, 0, 0}
530 /* Print the version information. */
531 static void
532 print_version (FILE *stream, struct argp_state *state)
534 fprintf (stream, "%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION);
536 void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
538 static error_t
539 argp_parser (int key, char *arg, struct argp_state *state)
541 char *p;
543 switch (key)
545 case 'r':
546 root = arg;
547 return 0;
549 case 'K':
550 if (strcmp (arg, "prompt") == 0)
552 char buf[1024];
553 grub_puts_ (N_("Enter ZFS password: "));
554 if (grub_password_get (buf, 1023))
556 grub_zfs_add_key ((grub_uint8_t *) buf, grub_strlen (buf), 1);
559 else
561 FILE *f;
562 ssize_t real_size;
563 grub_uint8_t buf[1024];
564 f = grub_util_fopen (arg, "rb");
565 if (!f)
567 printf (_("%s: error:"), program_name);
568 printf (_("cannot open `%s': %s"), arg, strerror (errno));
569 printf ("\n");
570 return 0;
572 real_size = fread (buf, 1, 1024, f);
573 fclose (f);
574 if (real_size < 0)
576 printf (_("%s: error:"), program_name);
577 printf (_("cannot read `%s': %s"), arg, strerror (errno));
578 printf ("\n");
579 return 0;
581 grub_zfs_add_key (buf, real_size, 0);
583 return 0;
585 case 'C':
586 mount_crypt = 1;
587 return 0;
589 case 's':
590 skip = grub_strtoul (arg, &p, 0);
591 if (*p == 's')
592 skip <<= GRUB_DISK_SECTOR_BITS;
593 return 0;
595 case 'n':
596 leng = grub_strtoul (arg, &p, 0);
597 if (*p == 's')
598 leng <<= GRUB_DISK_SECTOR_BITS;
599 return 0;
601 case 'c':
602 num_disks = grub_strtoul (arg, NULL, 0);
603 if (num_disks < 1)
605 fprintf (stderr, "%s", _("Invalid disk count.\n"));
606 argp_usage (state);
608 if (args_count != 0)
610 /* TRANSLATORS: disk count is optional but if it's there it must
611 be before disk list. So please don't imply disk count as mandatory.
613 fprintf (stderr, "%s", _("Disk count must precede disks list.\n"));
614 argp_usage (state);
616 return 0;
618 case 'd':
619 debug_str = arg;
620 return 0;
622 case 'v':
623 verbosity++;
624 return 0;
626 case 'u':
627 uncompress = 1;
628 return 0;
630 case ARGP_KEY_END:
631 if (args_count < num_disks)
633 fprintf (stderr, "%s", _("No command is specified.\n"));
634 argp_usage (state);
636 if (args_count - 1 - num_disks < nparm)
638 fprintf (stderr, "%s", _("Not enough parameters to command.\n"));
639 argp_usage (state);
641 return 0;
643 case ARGP_KEY_ARG:
644 break;
646 default:
647 return ARGP_ERR_UNKNOWN;
650 if (args_count < num_disks)
652 if (args_count == 0)
653 images = xmalloc (num_disks * sizeof (images[0]));
654 images[args_count] = canonicalize_file_name (arg);
655 args_count++;
656 return 0;
659 if (args_count == num_disks)
661 if (!grub_strcmp (arg, "ls"))
663 cmd = CMD_LS;
665 else if (!grub_strcmp (arg, "zfsinfo"))
667 cmd = CMD_ZFSINFO;
669 else if (!grub_strcmp (arg, "cp"))
671 cmd = CMD_CP;
672 nparm = 2;
674 else if (!grub_strcmp (arg, "cat"))
676 cmd = CMD_CAT;
677 nparm = 1;
679 else if (!grub_strcmp (arg, "cmp"))
681 cmd = CMD_CMP;
682 nparm = 2;
684 else if (!grub_strcmp (arg, "hex"))
686 cmd = CMD_HEX;
687 nparm = 1;
689 else if (!grub_strcmp (arg, "crc"))
691 cmd = CMD_CRC;
692 nparm = 1;
694 else if (!grub_strcmp (arg, "blocklist"))
696 cmd = CMD_BLOCKLIST;
697 nparm = 1;
699 else if (!grub_strcmp (arg, "testload"))
701 cmd = CMD_TESTLOAD;
702 nparm = 1;
704 else if (grub_strcmp (arg, "xnu_uuid") == 0)
706 cmd = CMD_XNU_UUID;
707 nparm = 0;
709 else
711 fprintf (stderr, _("Invalid command %s.\n"), arg);
712 argp_usage (state);
714 args_count++;
715 return 0;
718 args[args_count - 1 - num_disks] = xstrdup (arg);
719 args_count++;
720 return 0;
723 struct argp argp = {
724 options, argp_parser, N_("IMAGE_PATH COMMANDS"),
725 N_("Debug tool for filesystem driver."),
726 NULL, NULL, NULL
730 main (int argc, char *argv[])
732 const char *default_root;
733 char *alloc_root;
735 grub_util_host_init (&argc, &argv);
737 args = xmalloc (argc * sizeof (args[0]));
739 argp_parse (&argp, argc, argv, 0, 0, 0);
741 /* Initialize all modules. */
742 grub_init_all ();
743 grub_gcry_init_all ();
745 if (debug_str)
746 grub_env_set ("debug", debug_str);
748 default_root = (num_disks == 1) ? "loop0" : "md0";
749 alloc_root = 0;
750 if (root)
752 if ((*root >= '0') && (*root <= '9'))
754 alloc_root = xmalloc (strlen (default_root) + strlen (root) + 2);
756 sprintf (alloc_root, "%s,%s", default_root, root);
757 root = alloc_root;
760 else
761 root = default_root;
763 grub_env_set ("root", root);
765 if (alloc_root)
766 free (alloc_root);
768 /* Do it. */
769 fstest (args_count - 1 - num_disks);
771 /* Free resources. */
772 grub_gcry_fini_all ();
773 grub_fini_all ();
775 return 0;