1 /* grub-fstest.c - debug tool for filesystem driver */
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/>.
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>
29 #include <grub/term.h>
31 #include <grub/lib/hexdump.h>
32 #include <grub/lib/crc.h>
33 #include <grub/command.h>
35 #include <grub_fstest_init.h>
55 struct grub_handler_class grub_term_input_class
;
56 struct grub_handler_class grub_term_output_class
;
65 execute_command (char *name
, int n
, char **args
)
69 cmd
= grub_command_find (name
);
71 grub_util_error ("Can\'t find command %s", name
);
73 return (cmd
->func
) (cmd
, n
, args
);
81 #define CMD_BLOCKLIST 7
83 #define BUF_SIZE 32256
85 static grub_off_t skip
, leng
;
88 read_file (char *pathname
, int (*hook
) (grub_off_t ofs
, char *buf
, int len
))
90 static char buf
[BUF_SIZE
];
94 if ((pathname
[0] == '-') && (pathname
[1] == 0))
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
);
106 leng
= (dev
->disk
->total_sectors
<< GRUB_DISK_SECTOR_BITS
) - skip
;
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.",
118 if (hook (skip
, buf
, len
))
125 grub_device_close (dev
);
129 file
= grub_file_open (pathname
);
132 grub_util_error ("cannot open file %s.", pathname
);
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.");
145 len
= file
->size
- skip
;
146 if ((leng
) && (leng
< len
))
155 sz
= grub_file_read (file
, buf
, (len
> BUF_SIZE
) ? BUF_SIZE
: len
);
158 grub_util_error ("read error at offset %llu.", ofs
);
162 if ((sz
== 0) || (hook (ofs
, buf
, sz
)))
169 grub_file_close (file
);
173 cmd_cp (char *src
, char *dest
)
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
)
182 if ((int) fwrite (buf
, 1, len
, ff
) != len
)
184 grub_util_error ("write error.");
191 ff
= fopen (dest
, "wb");
194 grub_util_error ("open error.");
197 read_file (src
, cp_hook
);
202 cmd_cmp (char *src
, char *dest
)
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
);
216 if (grub_memcmp (buf
, buf_1
, len
))
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
);
230 ff
= fopen (dest
, "rb");
233 grub_util_error ("open error.");
237 if ((skip
) && (fseeko (ff
, skip
, SEEK_SET
)))
238 grub_util_error ("seek error.");
240 read_file (src
, cmp_hook
);
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
);
254 read_file (pathname
, hex_hook
);
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
)
267 crc
= grub_getcrc32 (crc
, buf
, len
);
271 read_file (pathname
, crc_hook
);
272 printf ("%08x\n", crc
);
276 fstest (char **images
, int num_disks
, int cmd
, int n
, char **args
)
280 char *argv
[3] = { "-p", loop_name
, host_file
};
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.");
305 execute_command ("ls", n
, args
);
308 cmd_cp (args
[0], args
[1]);
311 cmd_cmp (args
[0], args
[1]);
320 execute_command ("blocklist", n
, args
);
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'},
349 fprintf (stderr
, "Try ``grub-fstest --help'' for more information.\n");
352 Usage: grub-fstest [OPTION]... IMAGE_PATH COMMANDS\n\
354 Debug tool for filesystem driver.\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\
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
);
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')))
400 /* Check for options. */
403 int c
= getopt_long (num_opts
, argv
, "r:s:n:c:d:hVv", options
, 0);
416 skip
= grub_strtoul (optarg
, &p
, 0);
418 skip
<<= GRUB_DISK_SECTOR_BITS
;
422 leng
= grub_strtoul (optarg
, &p
, 0);
424 leng
<<= GRUB_DISK_SECTOR_BITS
;
428 num_disks
= grub_strtoul (optarg
, NULL
, 0);
431 fprintf (stderr
, "Invalid disk count.\n");
445 printf ("%s (%s) %s\n", progname
, PACKAGE_NAME
, PACKAGE_VERSION
);
459 if (optind
+ num_disks
- 1 >= argc
)
461 fprintf (stderr
, "Not enough pathname.\n");
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");
478 if (!grub_strcmp (argv
[optind
], "ls"))
482 else if (!grub_strcmp (argv
[optind
], "cp"))
487 else if (!grub_strcmp (argv
[optind
], "cmp"))
492 else if (!grub_strcmp (argv
[optind
], "hex"))
497 else if (!grub_strcmp (argv
[optind
], "crc"))
502 else if (!grub_strcmp (argv
[optind
], "blocklist"))
509 fprintf (stderr
, "Invalid command %s.\n", argv
[optind
]);
513 if (optind
+ 1 + nparm
> argc
)
515 fprintf (stderr
, "Invalid parameter for command %s.\n",
524 fprintf (stderr
, "No command is specified.\n");
528 /* Initialize all modules. */
532 grub_env_set ("debug", debug_str
);
534 default_root
= (num_disks
== 1) ? "loop0" : "md0";
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
);
549 grub_env_set ("root", root
);
555 fstest (argv
+ image_index
, num_disks
, cmd
, argc
- optind
, argv
+ optind
);
557 /* Free resources. */