2009-11-01 Felix Zielcke <fzielcke@z-51.de>
[grub2/phcoder/solaris.git] / util / grub-fstest.c
blob1bb37066fb77849f4b545b10dce81299222e2570
1 /* grub-fstest.c - debug tool for filesystem driver */
2 /*
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2008 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/util/misc.h>
23 #include <grub/misc.h>
24 #include <grub/device.h>
25 #include <grub/disk.h>
26 #include <grub/file.h>
27 #include <grub/fs.h>
28 #include <grub/env.h>
29 #include <grub/term.h>
30 #include <grub/mm.h>
31 #include <grub/lib/hexdump.h>
32 #include <grub/lib/crc.h>
33 #include <grub/command.h>
35 #include <grub_fstest_init.h>
37 #include <stdio.h>
38 #include <unistd.h>
39 #include <string.h>
40 #include <stdlib.h>
41 #include <getopt.h>
43 void
44 grub_putchar (int c)
46 putchar (c);
49 int
50 grub_getkey (void)
52 return -1;
55 struct grub_handler_class grub_term_input_class;
56 struct grub_handler_class grub_term_output_class;
58 void
59 grub_refresh (void)
61 fflush (stdout);
64 static grub_err_t
65 execute_command (char *name, int n, char **args)
67 grub_command_t cmd;
69 cmd = grub_command_find (name);
70 if (! cmd)
71 grub_util_error ("Can\'t find command %s", name);
73 return (cmd->func) (cmd, n, args);
76 #define CMD_LS 1
77 #define CMD_CP 2
78 #define CMD_CMP 3
79 #define CMD_HEX 4
80 #define CMD_CRC 6
81 #define CMD_BLOCKLIST 7
83 #define BUF_SIZE 32256
85 static grub_off_t skip, leng;
87 static void
88 read_file (char *pathname, int (*hook) (grub_off_t ofs, char *buf, int len))
90 static char buf[BUF_SIZE];
91 grub_file_t file;
92 grub_off_t ofs, len;
94 if ((pathname[0] == '-') && (pathname[1] == 0))
96 grub_device_t dev;
98 dev = grub_device_open (0);
99 if ((! dev) || (! dev->disk))
100 grub_util_error ("Can\'t open device.");
102 grub_util_info ("total sectors : %lld.",
103 (unsigned long long) dev->disk->total_sectors);
105 if (! leng)
106 leng = (dev->disk->total_sectors << GRUB_DISK_SECTOR_BITS) - skip;
108 while (leng)
110 grub_size_t len;
112 len = (leng > BUF_SIZE) ? BUF_SIZE : leng;
114 if (grub_disk_read (dev->disk, 0, skip, len, buf))
115 grub_util_error ("Disk read fails at offset %lld, length %d.",
116 skip, len);
118 if (hook (skip, buf, len))
119 break;
121 skip += len;
122 leng -= len;
125 grub_device_close (dev);
126 return;
129 file = grub_file_open (pathname);
130 if (!file)
132 grub_util_error ("cannot open file %s.", pathname);
133 return;
136 grub_util_info ("file size : %lld.", (unsigned long long) file->size);
138 if (skip > file->size)
140 grub_util_error ("invalid skip value %d.");
141 return;
144 ofs = skip;
145 len = file->size - skip;
146 if ((leng) && (leng < len))
147 len = leng;
149 file->offset = skip;
151 while (len)
153 grub_ssize_t sz;
155 sz = grub_file_read (file, buf, (len > BUF_SIZE) ? BUF_SIZE : len);
156 if (sz < 0)
158 grub_util_error ("read error at offset %llu.", ofs);
159 break;
162 if ((sz == 0) || (hook (ofs, buf, sz)))
163 break;
165 ofs += sz;
166 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 ("write error.");
185 return 1;
188 return 0;
191 ff = fopen (dest, "wb");
192 if (ff == NULL)
194 grub_util_error ("open error.");
195 return;
197 read_file (src, cp_hook);
198 fclose (ff);
201 static void
202 cmd_cmp (char *src, char *dest)
204 FILE *ff;
205 static char buf_1[BUF_SIZE];
207 auto int cmp_hook (grub_off_t ofs, char *buf, int len);
208 int cmp_hook (grub_off_t ofs, char *buf, int len)
210 if ((int) fread (buf_1, 1, len, ff) != len)
212 grub_util_error ("read error at offset %llu.", ofs);
213 return 1;
216 if (grub_memcmp (buf, buf_1, len))
218 int i;
220 for (i = 0; i < len; i++, ofs++)
221 if (buf_1[i] != buf[i])
223 grub_util_error ("compare fail at offset %llu.", ofs);
224 return 1;
227 return 0;
230 ff = fopen (dest, "rb");
231 if (ff == NULL)
233 grub_util_error ("open error.");
234 return;
237 if ((skip) && (fseeko (ff, skip, SEEK_SET)))
238 grub_util_error ("seek error.");
240 read_file (src, cmp_hook);
241 fclose (ff);
244 static void
245 cmd_hex (char *pathname)
247 auto int hex_hook (grub_off_t ofs, char *buf, int len);
248 int hex_hook (grub_off_t ofs, char *buf, int len)
250 hexdump (ofs, buf, len);
251 return 0;
254 read_file (pathname, hex_hook);
257 static void
258 cmd_crc (char *pathname)
260 grub_uint32_t crc = 0;
262 auto int crc_hook (grub_off_t ofs, char *buf, int len);
263 int crc_hook (grub_off_t ofs, char *buf, int len)
265 (void) ofs;
267 crc = grub_getcrc32 (crc, buf, len);
268 return 0;
271 read_file (pathname, crc_hook);
272 printf ("%08x\n", crc);
275 static void
276 fstest (char **images, int num_disks, int cmd, int n, char **args)
278 char host_file[128];
279 char loop_name[8];
280 char *argv[3] = { "-p", loop_name, host_file};
281 int i;
283 for (i = 0; i < num_disks; i++)
285 if (grub_strlen (images[i]) + 7 > sizeof (host_file))
286 grub_util_error ("Pathname %s too long.", images[i]);
288 grub_sprintf (loop_name, "loop%d", i);
289 grub_sprintf (host_file, "(host)%s", images[i]);
291 if (execute_command ("loopback", 3, argv))
292 grub_util_error ("loopback command fails.");
295 grub_lvm_fini ();
296 grub_mdraid_fini ();
297 grub_raid_fini ();
298 grub_raid_init ();
299 grub_mdraid_init ();
300 grub_lvm_init ();
302 switch (cmd)
304 case CMD_LS:
305 execute_command ("ls", n, args);
306 break;
307 case CMD_CP:
308 cmd_cp (args[0], args[1]);
309 break;
310 case CMD_CMP:
311 cmd_cmp (args[0], args[1]);
312 break;
313 case CMD_HEX:
314 cmd_hex (args[0]);
315 break;
316 case CMD_CRC:
317 cmd_crc (args[0]);
318 break;
319 case CMD_BLOCKLIST:
320 execute_command ("blocklist", n, args);
321 grub_printf ("\n");
324 argv[0] = "-d";
326 for (i = 0; i < num_disks; i++)
328 grub_sprintf (loop_name, "loop%d", i);
329 execute_command ("loopback", 2, argv);
333 static struct option options[] = {
334 {"root", required_argument, 0, 'r'},
335 {"skip", required_argument, 0, 's'},
336 {"length", required_argument, 0, 'n'},
337 {"diskcount", required_argument, 0, 'c'},
338 {"debug", required_argument, 0, 'd'},
339 {"help", no_argument, 0, 'h'},
340 {"version", no_argument, 0, 'V'},
341 {"verbose", no_argument, 0, 'v'},
342 {0, 0, 0, 0}
345 static void
346 usage (int status)
348 if (status)
349 fprintf (stderr, "Try ``grub-fstest --help'' for more information.\n");
350 else
351 printf ("\
352 Usage: grub-fstest [OPTION]... IMAGE_PATH COMMANDS\n\
354 Debug tool for filesystem driver.\n\
355 \nCommands:\n\
356 ls PATH list files in PATH\n\
357 cp FILE LOCAL copy FILE to local file LOCAL\n\
358 cmp FILE LOCAL compare FILE with local file LOCAL\n\
359 hex FILE Hex dump FILE\n\
360 crc FILE Get crc32 checksum of FILE\n\
361 blocklist FILE display blocklist of FILE\n\
362 \nOptions:\n\
363 -r, --root=DEVICE_NAME set root device\n\
364 -s, --skip=N skip N bytes from output file\n\
365 -n, --length=N handle N bytes in output file\n\
366 -c, --diskcount=N N input files\n\
367 -d, --debug=S Set debug environment variable\n\
368 -h, --help display this message and exit\n\
369 -V, --version print version information and exit\n\
370 -v, --verbose print verbose messages\n\
372 Report bugs to <%s>.\n", PACKAGE_BUGREPORT);
374 exit (status);
378 main (int argc, char *argv[])
380 char *debug_str = 0, *root = 0, *default_root, *alloc_root;
381 int i, cmd, num_opts, image_index, num_disks = 1;
383 progname = "grub-fstest";
385 /* Find the first non option entry. */
386 for (num_opts = 1; num_opts < argc; num_opts++)
387 if (argv[num_opts][0] == '-')
389 if ((argv[num_opts][2] == 0) && (num_opts < argc - 1) &&
390 ((argv[num_opts][1] == 'r') ||
391 (argv[num_opts][1] == 's') ||
392 (argv[num_opts][1] == 'n') ||
393 (argv[num_opts][1] == 'c') ||
394 (argv[num_opts][1] == 'd')))
395 num_opts++;
397 else
398 break;
400 /* Check for options. */
401 while (1)
403 int c = getopt_long (num_opts, argv, "r:s:n:c:d:hVv", options, 0);
404 char *p;
406 if (c == -1)
407 break;
408 else
409 switch (c)
411 case 'r':
412 root = optarg;
413 break;
415 case 's':
416 skip = grub_strtoul (optarg, &p, 0);
417 if (*p == 's')
418 skip <<= GRUB_DISK_SECTOR_BITS;
419 break;
421 case 'n':
422 leng = grub_strtoul (optarg, &p, 0);
423 if (*p == 's')
424 leng <<= GRUB_DISK_SECTOR_BITS;
425 break;
427 case 'c':
428 num_disks = grub_strtoul (optarg, NULL, 0);
429 if (num_disks < 1)
431 fprintf (stderr, "Invalid disk count.\n");
432 usage (1);
434 break;
436 case 'd':
437 debug_str = optarg;
438 break;
440 case 'h':
441 usage (0);
442 break;
444 case 'V':
445 printf ("%s (%s) %s\n", progname, PACKAGE_NAME, PACKAGE_VERSION);
446 return 0;
448 case 'v':
449 verbosity++;
450 break;
452 default:
453 usage (1);
454 break;
458 /* Obtain PATH. */
459 if (optind + num_disks - 1 >= argc)
461 fprintf (stderr, "Not enough pathname.\n");
462 usage (1);
465 image_index = optind;
466 for (i = 0; i < num_disks; i++, optind++)
467 if (argv[optind][0] != '/')
469 fprintf (stderr, "Must use absolute path.\n");
470 usage (1);
473 cmd = 0;
474 if (optind < argc)
476 int nparm = 0;
478 if (!grub_strcmp (argv[optind], "ls"))
480 cmd = CMD_LS;
482 else if (!grub_strcmp (argv[optind], "cp"))
484 cmd = CMD_CP;
485 nparm = 2;
487 else if (!grub_strcmp (argv[optind], "cmp"))
489 cmd = CMD_CMP;
490 nparm = 2;
492 else if (!grub_strcmp (argv[optind], "hex"))
494 cmd = CMD_HEX;
495 nparm = 1;
497 else if (!grub_strcmp (argv[optind], "crc"))
499 cmd = CMD_CRC;
500 nparm = 1;
502 else if (!grub_strcmp (argv[optind], "blocklist"))
504 cmd = CMD_BLOCKLIST;
505 nparm = 1;
507 else
509 fprintf (stderr, "Invalid command %s.\n", argv[optind]);
510 usage (1);
513 if (optind + 1 + nparm > argc)
515 fprintf (stderr, "Invalid parameter for command %s.\n",
516 argv[optind]);
517 usage (1);
520 optind++;
522 else
524 fprintf (stderr, "No command is specified.\n");
525 usage (1);
528 /* Initialize all modules. */
529 grub_init_all ();
531 if (debug_str)
532 grub_env_set ("debug", debug_str);
534 default_root = (num_disks == 1) ? "loop0" : "md0";
535 alloc_root = 0;
536 if (root)
538 if ((*root >= '0') && (*root <= '9'))
540 alloc_root = xmalloc (strlen (default_root) + strlen (root) + 2);
542 sprintf (alloc_root, "%s,%s", default_root, root);
543 root = alloc_root;
546 else
547 root = default_root;
549 grub_env_set ("root", root);
551 if (alloc_root)
552 free (alloc_root);
554 /* Do it. */
555 fstest (argv + image_index, num_disks, cmd, argc - optind, argv + optind);
557 /* Free resources. */
558 grub_fini_all ();
560 return 0;