[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: grub-fstest: debug tool for filesystem driver
From: |
Bean |
Subject: |
Re: grub-fstest: debug tool for filesystem driver |
Date: |
Tue, 29 Jan 2008 18:18:35 +0800 |
Some changes in this new patch:
Remove the _GNU_SOURCE line.
Partition number is now string, so that you can use bsd sub partition.
Code cleanup for function fstest.
2008-01-29 Bean <address@hidden>
* Makefile.in (enable_grub_fstest): New variable.
* conf/common.rmk (grub_fstest_init.lst): New rule.
(grub_fstest_init.h): Likewise.
(grub_fstest_init.c): Likewise.
* i396-pc.rmk (util/grub-fstest.c_DEPENDENCIES): New variable.
(grub_fstest_SOURCES): Likewise.
* configure.ac (enable_grub_fstest): New test.
* util/grub-fstest.c: New file.
diff --git a/Makefile.in b/Makefile.in
index 84b4e9c..ba07577 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -79,6 +79,7 @@ UNIFONT_HEX = @UNIFONT_HEX@
# Options.
enable_grub_emu = @enable_grub_emu@
+enable_grub_fstest = @enable_grub_fstest@
### General variables.
diff --git a/conf/common.rmk b/conf/common.rmk
index c1f367b..6e06a3e 100644
--- a/conf/common.rmk
+++ b/conf/common.rmk
@@ -44,6 +44,19 @@ grub_setup_init.c: grub_setup_init.lst $(filter-out
grub_setup_init.c,$(grub_set
rm -f $@; sh $(srcdir)/geninit.sh $< $(filter %.c,$^) > $@
DISTCLEANFILES += grub_setup_init.c
+# For grub-fstest.
+grub_fstest_init.lst: geninit.sh $(filter-out
grub_fstest_init.c,$(grub_fstest_SOURCES))
+ rm -f $@; grep GRUB_MOD_INIT $(filter %.c,$^) /dev/null > $@
+DISTCLEANFILES += grub_fstest_init.lst
+
+grub_fstest_init.h: grub_fstest_init.lst $(filter-out
grub_fstest_init.c,$(grub_fstest_SOURCES)) geninitheader.sh
+ rm -f $@; sh $(srcdir)/geninitheader.sh $< > $@
+DISTCLEANFILES += grub_fstest_init.h
+
+grub_fstest_init.c: grub_fstest_init.lst $(filter-out
grub_fstest_init.c,$(grub_fstest_SOURCES)) geninit.sh
grub_fstest_init.h
+ rm -f $@; sh $(srcdir)/geninit.sh $< $(filter %.c,$^) > $@
+DISTCLEANFILES += grub_fstest_init.c
+
# For update-grub
update-grub: util/update-grub.in config.status
./config.status --file=$@:$<
diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
index ff02332..5902608 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -61,6 +61,9 @@ sbin_UTILITIES = grub-setup grub-mkdevicemap grub-probe
ifeq ($(enable_grub_emu), yes)
sbin_UTILITIES += grub-emu
endif
+ifeq ($(enable_grub_fstest), yes)
+bin_UTILITIES += grub-fstest
+endif
# For grub-mkimage.
grub_mkimage_SOURCES = util/i386/pc/grub-mkimage.c util/misc.c \
@@ -139,6 +142,22 @@ grub_emu_SOURCES = commands/boot.c commands/cat.c
commands/cmp.c \
grub_emu_LDFLAGS = $(LIBCURSES)
+# For grub-fstest.
+util/grub-fstest.c_DEPENDENCIES = grub_fstest_init.h
+grub_fstest_SOURCES = util/grub-fstest.c util/hostfs.c util/misc.c \
+ kern/file.c kern/device.c kern/disk.c kern/err.c kern/misc.c \
+ disk/host.c disk/loopback.c normal/arg.c normal/misc.c \
+ io/gzio.c commands/hexdump.c commands/blocklist.c commands/ls.c \
+ \
+ fs/affs.c fs/cpio.c fs/ext2.c fs/fat.c fs/hfs.c \
+ fs/hfsplus.c fs/iso9660.c fs/jfs.c fs/minix.c \
+ fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c fs/sfs.c \
+ fs/ufs.c fs/xfs.c \
+ \
+ kern/partition.c partmap/pc.c partmap/apple.c partmap/gpt.c \
+ kern/fs.c kern/env.c fs/fshelp.c disk/lvm.c disk/raid.c \
+ grub_fstest_init.c
+
# Scripts.
sbin_SCRIPTS = grub-install
bin_SCRIPTS = grub-mkrescue
diff --git a/configure b/configure
index d272ea6..d1918ca 100755
--- a/configure
+++ b/configure
@@ -695,6 +695,7 @@ TARGET_CPPFLAGS
TARGET_LDFLAGS
LIBCURSES
enable_grub_emu
+enable_grub_fstest
LIBOBJS
LTLIBOBJS'
ac_subst_files=''
@@ -1290,6 +1291,8 @@ Optional Features:
--disable-largefile omit support for large files
--enable-mm-debug include memory manager debugging
--enable-grub-emu build and install the `grub-emu' debugging utility
+ --enable-grub-fstest build and install the `grub-fstest' debugging
+ utility
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
@@ -8142,6 +8145,13 @@ done
fi
+# Check whether --enable-grub-fstest was given.
+if test "${enable_grub_fstest+set}" = set; then
+ enableval=$enable_grub_fstest;
+fi
+
+
+
# Output files.
ac_config_links="$ac_config_links
include/grub/cpu:include/grub/$target_cpu
include/grub/machine:include/grub/$target_cpu/$platform"
@@ -8855,11 +8865,12 @@ TARGET_CPPFLAGS!$TARGET_CPPFLAGS$ac_delim
TARGET_LDFLAGS!$TARGET_LDFLAGS$ac_delim
LIBCURSES!$LIBCURSES$ac_delim
enable_grub_emu!$enable_grub_emu$ac_delim
+enable_grub_fstest!$enable_grub_fstest$ac_delim
LIBOBJS!$LIBOBJS$ac_delim
LTLIBOBJS!$LTLIBOBJS$ac_delim
_ACEOF
- if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 82; then
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 83; then
break
elif $ac_last_try; then
{ { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
diff --git a/configure.ac b/configure.ac
index b3f73e0..3546cc0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -320,6 +320,11 @@ AC_ARG_ENABLE([grub-emu],
[fi]
AC_SUBST([enable_grub_emu])
+AC_ARG_ENABLE([grub-fstest],
+ [AS_HELP_STRING([--enable-grub-fstest],
+ [build and install the `grub-fstest'
debugging utility])])
+AC_SUBST([enable_grub_fstest])
+
# Output files.
AC_CONFIG_LINKS([include/grub/cpu:include/grub/$target_cpu
include/grub/machine:include/grub/$target_cpu/$platform])
diff --git a/util/grub-fstest.c b/util/grub-fstest.c
new file mode 100644
index 0000000..76574fa
--- /dev/null
+++ b/util/grub-fstest.c
@@ -0,0 +1,514 @@
+/* grub-fstest.c - debug tool for filesystem driver */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2008 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <grub/types.h>
+#include <grub/util/misc.h>
+#include <grub/misc.h>
+#include <grub/device.h>
+#include <grub/disk.h>
+#include <grub/file.h>
+#include <grub/fs.h>
+#include <grub/env.h>
+#include <grub/term.h>
+#include <grub/mm.h>
+#include <grub/normal.h>
+#include <grub/script.h>
+#include <grub/hexdump.h>
+
+#include <grub_fstest_init.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+void
+grub_putchar (int c)
+{
+ putchar (c);
+}
+
+int
+grub_getkey (void)
+{
+ return -1;
+}
+
+grub_term_t
+grub_term_get_current (void)
+{
+ return 0;
+}
+
+void
+grub_refresh (void)
+{
+}
+
+static struct grub_command cmd_loopback;
+static struct grub_command cmd_blocklist;
+static struct grub_command cmd_ls;
+
+grub_command_t
+grub_register_command (const char *name,
+ grub_err_t (*func) (struct grub_arg_list * state,
+ int argc, char **args),
+ unsigned flags,
+ const char *summary __attribute__ ((unused)),
+ const char *description __attribute__ ((unused)),
+ const struct grub_arg_option *options)
+{
+ grub_command_t cmd = 0;
+
+ if (!grub_strcmp (name, "loopback"))
+ cmd = &cmd_loopback;
+ else if (!grub_strcmp (name, "blocklist"))
+ cmd = &cmd_blocklist;
+ else if (!grub_strcmp (name, "ls"))
+ cmd = &cmd_ls;
+
+ if (cmd)
+ {
+ cmd->func = func;
+ cmd->flags = flags;
+ cmd->options = options;
+ }
+ return NULL;
+}
+
+grub_err_t
+execute_command (grub_command_t cmd, int n, char **args)
+{
+ int maxargs = 0;
+ grub_err_t ret = 0;
+ struct grub_arg_list *state;
+ struct grub_arg_option *parser;
+ char **parsed_arglist;
+ int numargs;
+
+ /* Count the amount of options the command has. */
+ parser = (struct grub_arg_option *) cmd->options;
+ while (parser && (parser++)->doc)
+ maxargs++;
+
+ /* Set up the option state. */
+ state = grub_malloc (sizeof (struct grub_arg_list) * maxargs);
+ grub_memset (state, 0, sizeof (struct grub_arg_list) * maxargs);
+
+ /* Start the command. */
+ if (!(cmd->flags & GRUB_COMMAND_FLAG_NO_ARG_PARSE))
+ {
+ if (grub_arg_parse (cmd, n, args, state, &parsed_arglist, &numargs))
+ ret = (cmd->func) (state, numargs, parsed_arglist);
+ }
+ else
+ ret = (cmd->func) (state, n, args);
+
+ grub_free (state);
+
+ return ret;
+}
+
+void
+grub_unregister_command (const char *name __attribute__ ((unused)))
+{
+}
+
+#define CMD_LS 1
+#define CMD_CP 2
+#define CMD_CMP 3
+#define CMD_HEX 4
+#define CMD_BLOCKLIST 5
+
+#define BUF_SIZE 32256
+
+static grub_off_t skip, leng;
+static char *part;
+
+static void
+read_file (char *pathname, int (*hook) (grub_off_t ofs, char *buf, int len))
+{
+ static char buf[BUF_SIZE];
+ grub_file_t file;
+ grub_off_t ofs, len;
+
+ file = grub_file_open (pathname);
+ if (!file)
+ {
+ grub_util_error ("cannot open file %s.\n", pathname);
+ return;
+ }
+
+ if (skip > file->size)
+ {
+ grub_util_error ("invalid skip value %d.\n");
+ return;
+ }
+
+ ofs = skip;
+ len = file->size - skip;
+ if ((leng) && (leng < len))
+ len = leng;
+
+ file->offset = skip;
+
+ while (len)
+ {
+ grub_ssize_t sz;
+
+ sz = grub_file_read (file, buf, (len > BUF_SIZE) ? BUF_SIZE : len);
+ if (sz < 0)
+ {
+ grub_util_error ("read error at offset %llu.\n", ofs);
+ break;
+ }
+
+ if ((sz == 0) || (hook (ofs, buf, sz)))
+ break;
+
+ ofs += sz;
+ len -= sz;
+ }
+
+ grub_file_close (file);
+}
+
+static void
+cmd_cp (char *src, char *dest)
+{
+ FILE *ff;
+
+ auto int cp_hook (grub_off_t ofs, char *buf, int len);
+ int cp_hook (grub_off_t ofs, char *buf, int len)
+ {
+ (void) ofs;
+
+ if ((int) fwrite (buf, 1, len, ff) != len)
+ {
+ grub_util_error ("write error.\n");
+ return 1;
+ }
+
+ return 0;
+ }
+
+ ff = fopen (dest, "w");
+ if (ff == NULL)
+ {
+ grub_util_error ("open error.\n");
+ return;
+ }
+ read_file (src, cp_hook);
+ fclose (ff);
+}
+
+static void
+cmd_cmp (char *src, char *dest)
+{
+ FILE *ff;
+ static char buf_1[BUF_SIZE];
+
+ auto int cmp_hook (grub_off_t ofs, char *buf, int len);
+ int cmp_hook (grub_off_t ofs, char *buf, int len)
+ {
+ if ((int) fread (buf_1, 1, len, ff) != len)
+ {
+ grub_util_error ("read error at offset %llu.\n", ofs);
+ return 1;
+ }
+
+ if (grub_memcmp (buf, buf_1, len))
+ {
+ int i;
+
+ for (i = 0; i < len; i++, ofs++)
+ if (buf_1[i] != buf[i])
+ {
+ grub_util_error ("compare fail at offset %llu.\n", ofs);
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ ff = fopen (dest, "r");
+ if (ff == NULL)
+ {
+ grub_util_error ("open error.\n");
+ return;
+ }
+
+ if ((skip) && (fseek (ff, skip, SEEK_SET)))
+ grub_util_error ("fseek error.\n");
+
+ read_file (src, cmp_hook);
+ fclose (ff);
+}
+
+static void
+cmd_hex (char *pathname)
+{
+ auto int hex_hook (grub_off_t ofs, char *buf, int len);
+ int hex_hook (grub_off_t ofs, char *buf, int len)
+ {
+ hexdump (ofs, buf, len);
+ return 0;
+ }
+
+ read_file (pathname, hex_hook);
+}
+
+static void
+fstest (char *image_path, int cmd, int n, char **args)
+{
+ char host_file[7 + grub_strlen (image_path) + 1];
+ char device_name[(part) ? (6 + grub_strlen (part)) : 5];
+ char *argv[3] = { "-p", "loop", host_file };
+
+
+ grub_sprintf (host_file, "(host)/%s", image_path);
+
+ if (execute_command (&cmd_loopback, 3, argv))
+ {
+ grub_util_error ("loopback command fails.\n");
+ goto fail;
+ }
+
+ if (part)
+ grub_sprintf (device_name, "loop,%s", part);
+ else
+ grub_strcpy (device_name, "loop");
+
+ grub_env_set ("root", device_name);
+
+ switch (cmd)
+ {
+ case CMD_LS:
+ execute_command (&cmd_ls, n, args);
+ break;
+ case CMD_CP:
+ cmd_cp (args[0], args[1]);
+ break;
+ case CMD_CMP:
+ cmd_cmp (args[0], args[1]);
+ break;
+ case CMD_HEX:
+ cmd_hex (args[0]);
+ break;
+ case CMD_BLOCKLIST:
+ execute_command (&cmd_blocklist, n, args);
+ grub_printf ("\n");
+ }
+
+fail:
+
+ argv[0] = "-d";
+
+ execute_command (&cmd_loopback, 2, argv);
+}
+
+static struct option options[] = {
+ {"part", required_argument, 0, 'p'},
+ {"skip", required_argument, 0, 's'},
+ {"length", required_argument, 0, 'n'},
+ {"raw", no_argument, 0, 'r'},
+ {"long", no_argument, 0, 'l'},
+ {"help", no_argument, 0, 'h'},
+ {"version", no_argument, 0, 'V'},
+ {"verbose", no_argument, 0, 'v'},
+
+ {0, 0, 0, 0}
+};
+
+static void
+usage (int status)
+{
+ if (status)
+ fprintf (stderr, "Try ``grub-fstest --help'' for more information.\n");
+ else
+ printf ("\
+Usage: grub-fstest [OPTION]... IMAGE_PATH COMMANDS\n\
+\n\
+Debug tool for filesystem driver.\n\
+\nCommands:\n\
+ ls PATH list files in PATH\n\
+ cp SRC DEST copy file to local system\n\
+ cmp SRC DEST compare files\n\
+ hex FILE hex dump FILE\n\
+ blocklist FILE display blocklist of FILE\n\
+\nOptions:\n\
+ -p, --part=NUM select partition NUM\n\
+ -s, --skip=N skip N bytes from output file\n\
+ -n, --length=N handle N bytes in output file\n\
+ -r, --raw disable auto decompression\n\
+ -l, --long show long directory list\n\
+ -h, --help display this message and exit\n\
+ -V, --version print version information and exit\n\
+ -v, --verbose print verbose messages\n\
+\n\
+Report bugs to <%s>.\n", PACKAGE_BUGREPORT);
+
+ exit (status);
+}
+
+int
+main (int argc, char *argv[])
+{
+ char *image_path;
+ int cmd, is_raw = 0, is_long = 0;
+
+ progname = "grub-fstest";
+
+ /* Check for options. */
+ while (1)
+ {
+ int c = getopt_long (argc, argv, "p:s:n:rlhVv", options, 0);
+
+ if (c == -1)
+ break;
+ else
+ switch (c)
+ {
+ case 'p':
+ part = optarg;
+ break;
+
+ case 's':
+ skip = grub_strtoul (optarg, NULL, 0);
+ break;
+
+ case 'n':
+ leng = grub_strtoul (optarg, NULL, 0);
+ break;
+
+ case 'r':
+ is_raw = 1;
+ break;
+
+ case 'l':
+ is_long = 1;
+ break;
+
+ case 'h':
+ usage (0);
+ break;
+
+ case 'V':
+ printf ("%s (%s) %s\n", progname, PACKAGE_NAME, PACKAGE_VERSION);
+ return 0;
+
+ case 'v':
+ verbosity++;
+ break;
+
+ default:
+ usage (1);
+ break;
+ }
+ }
+
+ /* Obtain PATH. */
+ if (optind >= argc)
+ {
+ fprintf (stderr, "No path is specified.\n");
+ usage (1);
+ }
+
+ image_path = argv[optind];
+
+ if (*image_path != '/')
+ {
+ fprintf (stderr, "Must use absolute path.\n");
+ usage (1);
+ }
+
+ optind++;
+
+ cmd = 0;
+ if (optind < argc)
+ {
+ int nparm = 1;
+
+ if (!grub_strcmp (argv[optind], "ls"))
+ {
+ cmd = CMD_LS;
+ if (is_long)
+ argv[optind--] = "-l";
+ else
+ nparm = 0;
+ }
+ else if (!grub_strcmp (argv[optind], "cp"))
+ {
+ cmd = CMD_CP;
+ nparm = 2;
+ }
+ else if (!grub_strcmp (argv[optind], "cmp"))
+ {
+ cmd = CMD_CMP;
+ nparm = 2;
+ }
+ else if (!grub_strcmp (argv[optind], "hex"))
+ {
+ cmd = CMD_HEX;
+ }
+ else if (!grub_strcmp (argv[optind], "blocklist"))
+ {
+ cmd = CMD_BLOCKLIST;
+ }
+ else
+ {
+ fprintf (stderr, "Invalid command %s.\n", argv[optind]);
+ usage (1);
+ }
+
+ if (optind + 1 + nparm > argc)
+ {
+ fprintf (stderr, "Invalid parameter for command %s.\n",
+ argv[optind]);
+ usage (1);
+ }
+
+ optind++;
+ }
+ else
+ {
+ fprintf (stderr, "No command is specified.\n");
+ usage (1);
+ }
+
+ grub_hostfs_init ();
+
+ /* Initialize all modules. */
+ grub_init_all ();
+
+ if (is_raw)
+ grub_env_set ("filehook", "0");
+
+ /* Do it. */
+ fstest (image_path + 1, cmd, argc - optind, argv + optind);
+
+ /* Free resources. */
+ grub_fini_all ();
+
+ grub_hostfs_fini ();
+
+ return 0;
+}
if no other problems, i'd like to check it in.
--
Bean
- Re: grub-fstest: debug tool for filesystem driver, (continued)
- Re: grub-fstest: debug tool for filesystem driver, Robert Millan, 2008/01/04
- Re: grub-fstest: debug tool for filesystem driver, Bean, 2008/01/04
- Re: grub-fstest: debug tool for filesystem driver, Bean, 2008/01/05
- Re: grub-fstest: debug tool for filesystem driver, Robert Millan, 2008/01/05
- Re: grub-fstest: debug tool for filesystem driver, Bean, 2008/01/05
- Re: grub-fstest: debug tool for filesystem driver, Robert Millan, 2008/01/28
- Re: grub-fstest: debug tool for filesystem driver, Bean, 2008/01/28
- Re: grub-fstest: debug tool for filesystem driver, Robert Millan, 2008/01/28
- Re: grub-fstest: debug tool for filesystem driver, Bean, 2008/01/28
- Re: grub-fstest: debug tool for filesystem driver, Robert Millan, 2008/01/28
- Re: grub-fstest: debug tool for filesystem driver,
Bean <=
- Re: grub-fstest: debug tool for filesystem driver, Robert Millan, 2008/01/29
- Re: grub-fstest: debug tool for filesystem driver, Bean, 2008/01/29