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/raid.h>
32 #include <grub/lib/hexdump.h>
33 #include <grub/lib/crc.h>
34 #include <grub/command.h>
36 #include <grub_fstest_init.h>
56 struct grub_handler_class grub_term_input_class
;
57 struct grub_handler_class grub_term_output_class
;
66 execute_command (char *name
, int n
, char **args
)
70 cmd
= grub_command_find (name
);
72 grub_util_error ("Can\'t find command %s", name
);
74 return (cmd
->func
) (cmd
, n
, args
);
82 #define CMD_BLOCKLIST 7
84 #define BUF_SIZE 32256
86 static grub_off_t skip
, leng
;
89 read_file (char *pathname
, int (*hook
) (grub_off_t ofs
, char *buf
, int len
))
91 static char buf
[BUF_SIZE
];
95 if ((pathname
[0] == '-') && (pathname
[1] == 0))
99 dev
= grub_device_open (0);
100 if ((! dev
) || (! dev
->disk
))
101 grub_util_error ("Can\'t open device.");
103 grub_util_info ("total sectors : %lld.",
104 (unsigned long long) dev
->disk
->total_sectors
);
107 leng
= (dev
->disk
->total_sectors
<< GRUB_DISK_SECTOR_BITS
) - skip
;
113 len
= (leng
> BUF_SIZE
) ? BUF_SIZE
: leng
;
115 if (grub_disk_read (dev
->disk
, 0, skip
, len
, buf
))
116 grub_util_error ("Disk read fails at offset %lld, length %d.",
119 if (hook (skip
, buf
, len
))
126 grub_device_close (dev
);
130 file
= grub_file_open (pathname
);
133 grub_util_error ("cannot open file %s.", pathname
);
137 grub_util_info ("file size : %lld.", (unsigned long long) file
->size
);
139 if (skip
> file
->size
)
141 grub_util_error ("invalid skip value %d.");
146 len
= file
->size
- skip
;
147 if ((leng
) && (leng
< len
))
156 sz
= grub_file_read (file
, buf
, (len
> BUF_SIZE
) ? BUF_SIZE
: len
);
159 grub_util_error ("read error at offset %llu.", ofs
);
163 if ((sz
== 0) || (hook (ofs
, buf
, sz
)))
170 grub_file_close (file
);
174 cmd_cp (char *src
, char *dest
)
178 auto int cp_hook (grub_off_t ofs
, char *buf
, int len
);
179 int cp_hook (grub_off_t ofs
, char *buf
, int len
)
183 if ((int) fwrite (buf
, 1, len
, ff
) != len
)
185 grub_util_error ("write error.");
192 ff
= fopen (dest
, "wb");
195 grub_util_error ("open error.");
198 read_file (src
, cp_hook
);
203 cmd_cmp (char *src
, char *dest
)
206 static char buf_1
[BUF_SIZE
];
208 auto int cmp_hook (grub_off_t ofs
, char *buf
, int len
);
209 int cmp_hook (grub_off_t ofs
, char *buf
, int len
)
211 if ((int) fread (buf_1
, 1, len
, ff
) != len
)
213 grub_util_error ("read error at offset %llu.", ofs
);
217 if (grub_memcmp (buf
, buf_1
, len
))
221 for (i
= 0; i
< len
; i
++, ofs
++)
222 if (buf_1
[i
] != buf
[i
])
224 grub_util_error ("compare fail at offset %llu.", ofs
);
231 ff
= fopen (dest
, "rb");
234 grub_util_error ("open error.");
238 if ((skip
) && (fseeko (ff
, skip
, SEEK_SET
)))
239 grub_util_error ("seek error.");
241 read_file (src
, cmp_hook
);
246 cmd_hex (char *pathname
)
248 auto int hex_hook (grub_off_t ofs
, char *buf
, int len
);
249 int hex_hook (grub_off_t ofs
, char *buf
, int len
)
251 hexdump (ofs
, buf
, len
);
255 read_file (pathname
, hex_hook
);
259 cmd_crc (char *pathname
)
261 grub_uint32_t crc
= 0;
263 auto int crc_hook (grub_off_t ofs
, char *buf
, int len
);
264 int crc_hook (grub_off_t ofs
, char *buf
, int len
)
268 crc
= grub_getcrc32 (crc
, buf
, len
);
272 read_file (pathname
, crc_hook
);
273 printf ("%08x\n", crc
);
277 fstest (char **images
, int num_disks
, int cmd
, int n
, char **args
)
281 char *argv
[3] = { "-p", loop_name
, host_file
};
284 for (i
= 0; i
< num_disks
; i
++)
286 if (grub_strlen (images
[i
]) + 7 > sizeof (host_file
))
287 grub_util_error ("Pathname %s too long.", images
[i
]);
289 grub_sprintf (loop_name
, "loop%d", i
);
290 grub_sprintf (host_file
, "(host)%s", images
[i
]);
292 if (execute_command ("loopback", 3, argv
))
293 grub_util_error ("loopback command fails.");
300 execute_command ("ls", n
, args
);
303 cmd_cp (args
[0], args
[1]);
306 cmd_cmp (args
[0], args
[1]);
315 execute_command ("blocklist", n
, args
);
321 for (i
= 0; i
< num_disks
; i
++)
323 grub_sprintf (loop_name
, "loop%d", i
);
324 execute_command ("loopback", 2, argv
);
328 static struct option options
[] = {
329 {"root", required_argument
, 0, 'r'},
330 {"skip", required_argument
, 0, 's'},
331 {"length", required_argument
, 0, 'n'},
332 {"diskcount", required_argument
, 0, 'c'},
333 {"debug", required_argument
, 0, 'd'},
334 {"help", no_argument
, 0, 'h'},
335 {"version", no_argument
, 0, 'V'},
336 {"verbose", no_argument
, 0, 'v'},
344 fprintf (stderr
, "Try ``grub-fstest --help'' for more information.\n");
347 Usage: grub-fstest [OPTION]... IMAGE_PATH COMMANDS\n\
349 Debug tool for filesystem driver.\n\
351 ls PATH list files in PATH\n\
352 cp FILE LOCAL copy FILE to local file LOCAL\n\
353 cmp FILE LOCAL compare FILE with local file LOCAL\n\
354 hex FILE Hex dump FILE\n\
355 crc FILE Get crc32 checksum of FILE\n\
356 blocklist FILE display blocklist of FILE\n\
358 -r, --root=DEVICE_NAME set root device\n\
359 -s, --skip=N skip N bytes from output file\n\
360 -n, --length=N handle N bytes in output file\n\
361 -c, --diskcount=N N input files\n\
362 -d, --debug=S Set debug environment variable\n\
363 -h, --help display this message and exit\n\
364 -V, --version print version information and exit\n\
365 -v, --verbose print verbose messages\n\
367 Report bugs to <%s>.\n", PACKAGE_BUGREPORT
);
373 main (int argc
, char *argv
[])
375 char *debug_str
= 0, *root
= 0, *default_root
, *alloc_root
;
376 int i
, cmd
, num_opts
, image_index
, num_disks
= 1;
378 progname
= "grub-fstest";
380 /* Find the first non option entry. */
381 for (num_opts
= 1; num_opts
< argc
; num_opts
++)
382 if (argv
[num_opts
][0] == '-')
384 if ((argv
[num_opts
][2] == 0) && (num_opts
< argc
- 1) &&
385 ((argv
[num_opts
][1] == 'r') ||
386 (argv
[num_opts
][1] == 's') ||
387 (argv
[num_opts
][1] == 'n') ||
388 (argv
[num_opts
][1] == 'c') ||
389 (argv
[num_opts
][1] == 'd')))
395 /* Check for options. */
398 int c
= getopt_long (num_opts
, argv
, "r:s:n:c:d:hVv", options
, 0);
411 skip
= grub_strtoul (optarg
, &p
, 0);
413 skip
<<= GRUB_DISK_SECTOR_BITS
;
417 leng
= grub_strtoul (optarg
, &p
, 0);
419 leng
<<= GRUB_DISK_SECTOR_BITS
;
423 num_disks
= grub_strtoul (optarg
, NULL
, 0);
426 fprintf (stderr
, "Invalid disk count.\n");
440 printf ("%s (%s) %s\n", progname
, PACKAGE_NAME
, PACKAGE_VERSION
);
454 if (optind
+ num_disks
- 1 >= argc
)
456 fprintf (stderr
, "Not enough pathname.\n");
460 image_index
= optind
;
461 for (i
= 0; i
< num_disks
; i
++, optind
++)
462 if (argv
[optind
][0] != '/')
464 fprintf (stderr
, "Must use absolute path.\n");
473 if (!grub_strcmp (argv
[optind
], "ls"))
477 else if (!grub_strcmp (argv
[optind
], "cp"))
482 else if (!grub_strcmp (argv
[optind
], "cmp"))
487 else if (!grub_strcmp (argv
[optind
], "hex"))
492 else if (!grub_strcmp (argv
[optind
], "crc"))
497 else if (!grub_strcmp (argv
[optind
], "blocklist"))
504 fprintf (stderr
, "Invalid command %s.\n", argv
[optind
]);
508 if (optind
+ 1 + nparm
> argc
)
510 fprintf (stderr
, "Invalid parameter for command %s.\n",
519 fprintf (stderr
, "No command is specified.\n");
523 /* Initialize all modules. */
527 grub_env_set ("debug", debug_str
);
529 default_root
= (num_disks
== 1) ? "loop0" : "md0";
533 if ((*root
>= '0') && (*root
<= '9'))
535 alloc_root
= xmalloc (strlen (default_root
) + strlen (root
) + 2);
537 sprintf (alloc_root
, "%s,%s", default_root
, root
);
544 grub_env_set ("root", root
);
550 fstest (argv
+ image_index
, num_disks
, cmd
, argc
- optind
, argv
+ optind
);
552 /* Free resources. */