All of lore.kernel.org
 help / color / mirror / Atom feed
* grub-fstest: debug tool for filesystem driver
@ 2008-01-02 17:11 Bean
  2008-01-04 11:53 ` Robert Millan
  0 siblings, 1 reply; 16+ messages in thread
From: Bean @ 2008-01-02 17:11 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 1415 bytes --]

Hi,

I've written a new tool grub-fstest which can be useful in debuging
filesystem drivers. To build grub-fstest, you must use option
--enable-grub-fstest:

./configure --enable-grub-fstest

Usage:

fstest [OPTIONS] IMAGE_PATH COMMANDS

IMAGE_PATH is the absolute path to an image file, COMMANDS is one of
the following commands:

ls PATH
list files in PATH

cp SRC DEST
copy file SRC in the image file to DEST in the local system.

cmp SRC DEST
compare file SRC in the image file with DEST in the local system.

dump FILE
hexdump FILE in the image file

blst FILE
display the blocklist of FILE in the image file

Options:
-s, --skip=N
set the number of bytes to skip in command cp, cmp and dump.

-n, --length=N
set the number of bytes to process in command cp, cmp and dump.

-r, --raw
disable auto decompression

-p, --part=N
if IMAGE_FILE contain partition map, use the option to select partition.

Examples:

./grub-fstest /path/aa.iso ls /
List files in aa.iso

./grub-fstest -p 1 /path/aa.dsk cp /bb cc
Copy file /bb in the first partition of aa.dsk to cc in the current directory

./grub-fstest -p 1 /path/aa.dsk cmp /bb cc
Compare file /bb in the first partition of aa.dsk with cc in the
current directory

./grub-fstest -s 10 -n 20 /path/aa.tar dump /bb
Hexdump file /bb in aa.tar, skip 10 bytes, print 20 bytes.

./grub-fstest /path/aa.iso blst /bb
display the blocklist of file /bb in aa.iso

-- 
Bean

[-- Attachment #2: grub2-fstest.diff --]
[-- Type: application/octet-stream, Size: 15939 bytes --]

diff --git a/Makefile.in b/Makefile.in
index c6a04c9..c4b8835 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 4773f7d..45dfeef 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 2638ee5..a25dd76 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -59,6 +59,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 \
@@ -121,6 +124,18 @@ 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 commands/hexdump.c io/gzio.c	\
+	commands/blocklist.c fs/fat.c fs/ext2.c kern/parser.c		\
+	kern/partition.c partmap/pc.c partmap/apple.c partmap/gpt.c 	\
+	fs/ufs.c fs/minix.c fs/hfs.c fs/jfs.c fs/ntfs.c kern/fs.c	\
+	kern/env.c fs/fshelp.c fs/xfs.c fs/affs.c fs/sfs.c fs/hfsplus.c	\
+	fs/ntfscomp.c fs/iso9660.c fs/cpio.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 bd2d745..8ca04d5 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]
@@ -8141,6 +8144,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"
 
@@ -8854,11 +8864,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 fb6e026..451230f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -319,6 +319,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 100755
index 0000000..7621af6
--- /dev/null
+++ b/util/grub-fstest.c
@@ -0,0 +1,540 @@
+/* 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/normal.h>
+#include <grub/hexdump.h>
+
+#include <grub_fstest_init.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define _GNU_SOURCE	1
+#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 grub_err_t (*loopfunc) (struct grub_arg_list * state, int argc,
+			       char **args);
+static grub_err_t (*blstfunc) (struct grub_arg_list * state, int argc,
+			       char **args);
+
+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,
+		       const char *description,
+		       const struct grub_arg_option *options)
+{
+  (void) flags;
+  (void) summary;
+  (void) description;
+  (void) options;
+
+  if (!grub_strcmp (name, "loopback"))
+    loopfunc = func;
+  else if (!grub_strcmp (name, "blocklist"))
+    blstfunc = func;
+
+  return NULL;
+}
+
+void
+grub_unregister_command (const char *name)
+{
+  (void) name;
+}
+
+#define CMD_LIST  1
+#define CMD_COPY  2
+#define CMD_COMP  3
+#define CMD_DUMP  4
+#define CMD_BLST  5
+
+#define BUF_SIZE  32256
+
+static grub_off_t skip, leng;
+static int part;
+
+static void
+cmd_list (grub_fs_t fs, grub_device_t dev, char *dirname)
+{
+  auto int print_files_long (const char *filename, int dir);
+  int print_files_long (const char *filename, int dir)
+  {
+    char pathname[grub_strlen (dirname) + grub_strlen (filename) + 1];
+
+    if (!dir)
+      {
+	grub_file_t file;
+
+	if (dirname[grub_strlen (dirname) - 1] == '/')
+	  grub_sprintf (pathname, "%s%s", dirname, filename);
+	else
+	  grub_sprintf (pathname, "%s/%s", dirname, filename);
+
+	file = grub_file_open (pathname);
+	if (!file)
+	  {
+	    grub_errno = 0;
+	    return 0;
+	  }
+
+	grub_printf ("%-12llu", file->size);
+	grub_file_close (file);
+      }
+    else
+      grub_printf ("%-12s", "DIR");
+
+    grub_printf ("%s%s\n", filename, dir ? "/" : "");
+
+    return 0;
+  }
+
+  fs->dir (dev, dirname, print_files_long);
+}
+
+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_copy (char *src, char *dest)
+{
+  FILE *ff;
+
+  auto int copy_hook (grub_off_t ofs, char *buf, int len);
+  int copy_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, copy_hook);
+  fclose (ff);
+}
+
+static void
+cmd_comp (char *src, char *dest)
+{
+  FILE *ff;
+  static char buf_1[BUF_SIZE];
+
+  auto int comp_hook (grub_off_t ofs, char *buf, int len);
+  int comp_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, comp_hook);
+  fclose (ff);
+}
+
+static void
+cmd_dump (char *pathname)
+{
+  auto int dump_hook (grub_off_t ofs, char *buf, int len);
+  int dump_hook (grub_off_t ofs, char *buf, int len)
+  {
+    hexdump (ofs, buf, len);
+    return 0;
+  }
+
+  read_file (pathname, dump_hook);
+}
+
+static void
+cmd_blst (char *pathname)
+{
+  char *argv[1];
+
+  argv[0] = pathname;
+  if (blstfunc (NULL, 1, argv))
+    grub_util_error ("blocklist command fails.\n");
+  else
+    grub_printf ("\n");
+}
+
+static void
+fstest (char *image_path, int cmd, char **parm)
+{
+  grub_device_t dev = 0;
+  grub_fs_t fs;
+  char host_file[7 + grub_strlen (image_path) + 1];
+  struct grub_arg_list state[2];
+  char *argv[2];
+  char device_name[10];
+
+  grub_memset (&state, 0, sizeof (state));
+  state[1].set = (part != 0);
+
+  argv[0] = "loop";
+  grub_sprintf (host_file, "(host)/%s", image_path);
+  argv[1] = host_file;
+
+  if (loopfunc (state, 2, argv))
+    {
+      grub_util_error ("loopback command fails.\n");
+      goto fail;
+    }
+
+  if (part)
+    grub_sprintf (device_name, "loop,%d", part);
+  else
+    grub_strcpy (device_name, "loop");
+
+  dev = grub_device_open (device_name);
+  if (!dev)
+    {
+      grub_util_error ("cannot open device (%s).\n", device_name);
+      goto fail;
+    }
+
+  grub_env_set ("root", device_name);
+
+  fs = grub_fs_probe (dev);
+  if (!fs)
+    {
+      grub_util_error ("Unknown fs.\n");
+      goto fail;
+    }
+
+  grub_util_info ("filesystem %s.", fs->name);
+
+  switch (cmd)
+    {
+    case CMD_LIST:
+      cmd_list (fs, dev, parm[0]);
+      break;
+    case CMD_COPY:
+      cmd_copy (parm[0], parm[1]);
+      break;
+    case CMD_COMP:
+      cmd_comp (parm[0], parm[1]);
+      break;
+    case CMD_DUMP:
+      cmd_dump (parm[0]);
+      break;
+    case CMD_BLST:
+      cmd_blst (parm[0]);
+    }
+
+fail:
+  state[0].set = 1;
+  loopfunc (state, 1, argv);
+
+  if (dev)
+    grub_device_close (dev);
+}
+
+static struct option options[] = {
+  {"part", required_argument, 0, 'p'},
+  {"skip", required_argument, 0, 's'},
+  {"length", required_argument, 0, 'n'},
+  {"raw", required_argument, 0, 'r'},
+  {"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\
+  dump FILE                 hexdump FILE\n\
+  blst 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\
+  -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, raw = 0;
+
+  progname = "grub-fstest";
+
+  /* Check for options.  */
+  while (1)
+    {
+      int c = getopt_long (argc, argv, "p:s:n:rhVv", options, 0);
+
+      if (c == -1)
+	break;
+      else
+	switch (c)
+	  {
+	  case 'p':
+	    part = grub_strtoul (optarg, NULL, 0);
+	    break;
+
+	  case 's':
+	    skip = grub_strtoul (optarg, NULL, 0);
+	    break;
+
+	  case 'n':
+	    leng = grub_strtoul (optarg, NULL, 0);
+	    break;
+
+	  case 'r':
+	    raw = 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_LIST;
+	}
+      else if (!grub_strcmp (argv[optind], "cp"))
+	{
+	  cmd = CMD_COPY;
+	  nparm = 2;
+	}
+      else if (!grub_strcmp (argv[optind], "cmp"))
+	{
+	  cmd = CMD_COMP;
+	  nparm = 2;
+	}
+      else if (!grub_strcmp (argv[optind], "dump"))
+	{
+	  cmd = CMD_DUMP;
+	}
+      else if (!grub_strcmp (argv[optind], "blst"))
+	{
+	  cmd = CMD_BLST;
+	}
+      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 (raw)
+    grub_env_set ("nofshook", "1");
+
+  /* Do it.  */
+  fstest (image_path + 1, cmd, argv + optind);
+
+  /* Free resources.  */
+  grub_fini_all ();
+
+  grub_hostfs_fini ();
+
+  return 0;
+}

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: grub-fstest: debug tool for filesystem driver
  2008-01-02 17:11 grub-fstest: debug tool for filesystem driver Bean
@ 2008-01-04 11:53 ` Robert Millan
  2008-01-04 12:08   ` Bean
  0 siblings, 1 reply; 16+ messages in thread
From: Robert Millan @ 2008-01-04 11:53 UTC (permalink / raw)
  To: The development of GRUB 2

On Thu, Jan 03, 2008 at 01:11:32AM +0800, Bean wrote:
> blst FILE
> display the blocklist of FILE in the image file

Is this `blst' analogous to the `blocklist' command we already have?  In
that case, I'd suggest giving it the same name.

-- 
Robert Millan

<GPLv2> I know my rights; I want my phone call!
<DRM> What use is a phone call, if you are unable to speak?
(as seen on /.)



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: grub-fstest: debug tool for filesystem driver
  2008-01-04 11:53 ` Robert Millan
@ 2008-01-04 12:08   ` Bean
  2008-01-05  7:37     ` Bean
  0 siblings, 1 reply; 16+ messages in thread
From: Bean @ 2008-01-04 12:08 UTC (permalink / raw)
  To: The development of GRUB 2

On Jan 4, 2008 7:53 PM, Robert Millan <rmh@aybabtu.com> wrote:
> On Thu, Jan 03, 2008 at 01:11:32AM +0800, Bean wrote:
> > blst FILE
> > display the blocklist of FILE in the image file
>
> Is this `blst' analogous to the `blocklist' command we already have?  In
> that case, I'd suggest giving it the same name.

yep, it's the same.

-- 
Bean



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: grub-fstest: debug tool for filesystem driver
  2008-01-04 12:08   ` Bean
@ 2008-01-05  7:37     ` Bean
  2008-01-05 11:52       ` Robert Millan
  0 siblings, 1 reply; 16+ messages in thread
From: Bean @ 2008-01-05  7:37 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 555 bytes --]

On Jan 4, 2008 8:08 PM, Bean <bean123ch@gmail.com> wrote:
> On Jan 4, 2008 7:53 PM, Robert Millan <rmh@aybabtu.com> wrote:
> > On Thu, Jan 03, 2008 at 01:11:32AM +0800, Bean wrote:
> > > blst FILE
> > > display the blocklist of FILE in the image file
> >
> > Is this `blst' analogous to the `blocklist' command we already have?  In
> > that case, I'd suggest giving it the same name.
>
> yep, it's the same.

Change command names:

dump -> hex
blst -> blocklist

Also replace grub_file_open with grub_file_open_ex from my latest
filehook patch.

-- 
Bean

[-- Attachment #2: grub2-fstest2.diff --]
[-- Type: application/octet-stream, Size: 16365 bytes --]

2008-01-05  Bean <bean123ch@gmail.com>

	* 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 c6a04c9..c4b8835 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 4773f7d..45dfeef 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 2638ee5..a25dd76 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -59,6 +59,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 \
@@ -121,6 +124,18 @@ 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 commands/hexdump.c io/gzio.c	\
+	commands/blocklist.c fs/fat.c fs/ext2.c kern/parser.c		\
+	kern/partition.c partmap/pc.c partmap/apple.c partmap/gpt.c 	\
+	fs/ufs.c fs/minix.c fs/hfs.c fs/jfs.c fs/ntfs.c kern/fs.c	\
+	kern/env.c fs/fshelp.c fs/xfs.c fs/affs.c fs/sfs.c fs/hfsplus.c	\
+	fs/ntfscomp.c fs/iso9660.c fs/cpio.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 bd2d745..8ca04d5 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]
@@ -8141,6 +8144,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"
 
@@ -8854,11 +8864,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 fb6e026..451230f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -319,6 +319,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 100755
index 0000000..c255dbb
--- /dev/null
+++ b/util/grub-fstest.c
@@ -0,0 +1,540 @@
+/* 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/normal.h>
+#include <grub/hexdump.h>
+
+#include <grub_fstest_init.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define _GNU_SOURCE	1
+#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 grub_err_t (*loopfunc) (struct grub_arg_list * state, int argc,
+			       char **args);
+static grub_err_t (*blstfunc) (struct grub_arg_list * state, int argc,
+			       char **args);
+
+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,
+		       const char *description,
+		       const struct grub_arg_option *options)
+{
+  (void) flags;
+  (void) summary;
+  (void) description;
+  (void) options;
+
+  if (!grub_strcmp (name, "loopback"))
+    loopfunc = func;
+  else if (!grub_strcmp (name, "blocklist"))
+    blstfunc = func;
+
+  return NULL;
+}
+
+void
+grub_unregister_command (const char *name)
+{
+  (void) name;
+}
+
+#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 int part;
+
+static void
+cmd_ls (grub_fs_t fs, grub_device_t dev, char *dirname)
+{
+  auto int print_files_long (const char *filename, int dir);
+  int print_files_long (const char *filename, int dir)
+  {
+    char pathname[grub_strlen (dirname) + grub_strlen (filename) + 1];
+
+    if (!dir)
+      {
+	grub_file_t file;
+
+	if (dirname[grub_strlen (dirname) - 1] == '/')
+	  grub_sprintf (pathname, "%s%s", dirname, filename);
+	else
+	  grub_sprintf (pathname, "%s/%s", dirname, filename);
+
+	file = grub_file_open_ex (pathname, 1);
+	if (!file)
+	  {
+	    grub_errno = 0;
+	    return 0;
+	  }
+
+	grub_printf ("%-12llu", file->size);
+	grub_file_close (file);
+      }
+    else
+      grub_printf ("%-12s", "DIR");
+
+    grub_printf ("%s%s\n", filename, dir ? "/" : "");
+
+    return 0;
+  }
+
+  fs->dir (dev, dirname, print_files_long);
+}
+
+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_ex (pathname, 1);
+  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
+cmd_blocklist (char *pathname)
+{
+  char *argv[1];
+
+  argv[0] = pathname;
+  if (blstfunc (NULL, 1, argv))
+    grub_util_error ("blocklist command fails.\n");
+  else
+    grub_printf ("\n");
+}
+
+static void
+fstest (char *image_path, int cmd, char **parm)
+{
+  grub_device_t dev = 0;
+  grub_fs_t fs;
+  char host_file[7 + grub_strlen (image_path) + 1];
+  struct grub_arg_list state[2];
+  char *argv[2];
+  char device_name[10];
+
+  grub_memset (&state, 0, sizeof (state));
+  state[1].set = (part != 0);
+
+  argv[0] = "loop";
+  grub_sprintf (host_file, "(host)/%s", image_path);
+  argv[1] = host_file;
+
+  if (loopfunc (state, 2, argv))
+    {
+      grub_util_error ("loopback command fails.\n");
+      goto fail;
+    }
+
+  if (part)
+    grub_sprintf (device_name, "loop,%d", part);
+  else
+    grub_strcpy (device_name, "loop");
+
+  dev = grub_device_open (device_name);
+  if (!dev)
+    {
+      grub_util_error ("cannot open device (%s).\n", device_name);
+      goto fail;
+    }
+
+  grub_env_set ("root", device_name);
+
+  fs = grub_fs_probe (dev);
+  if (!fs)
+    {
+      grub_util_error ("Unknown fs.\n");
+      goto fail;
+    }
+
+  grub_util_info ("filesystem %s.", fs->name);
+
+  switch (cmd)
+    {
+    case CMD_LS:
+      cmd_ls (fs, dev, parm[0]);
+      break;
+    case CMD_CP:
+      cmd_cp (parm[0], parm[1]);
+      break;
+    case CMD_CMP:
+      cmd_cmp (parm[0], parm[1]);
+      break;
+    case CMD_HEX:
+      cmd_hex (parm[0]);
+      break;
+    case CMD_BLOCKLIST:
+      cmd_blocklist (parm[0]);
+    }
+
+fail:
+  state[0].set = 1;
+  loopfunc (state, 1, argv);
+
+  if (dev)
+    grub_device_close (dev);
+}
+
+static struct option options[] = {
+  {"part", required_argument, 0, 'p'},
+  {"skip", required_argument, 0, 's'},
+  {"length", required_argument, 0, 'n'},
+  {"raw", required_argument, 0, 'r'},
+  {"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\
+  -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, raw = 0;
+
+  progname = "grub-fstest";
+
+  /* Check for options.  */
+  while (1)
+    {
+      int c = getopt_long (argc, argv, "p:s:n:rhVv", options, 0);
+
+      if (c == -1)
+	break;
+      else
+	switch (c)
+	  {
+	  case 'p':
+	    part = grub_strtoul (optarg, NULL, 0);
+	    break;
+
+	  case 's':
+	    skip = grub_strtoul (optarg, NULL, 0);
+	    break;
+
+	  case 'n':
+	    leng = grub_strtoul (optarg, NULL, 0);
+	    break;
+
+	  case 'r':
+	    raw = 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;
+	}
+      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 (raw)
+    grub_env_set ("filehook", "0");
+
+  /* Do it.  */
+  fstest (image_path + 1, cmd, argv + optind);
+
+  /* Free resources.  */
+  grub_fini_all ();
+
+  grub_hostfs_fini ();
+
+  return 0;
+}

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: grub-fstest: debug tool for filesystem driver
  2008-01-05  7:37     ` Bean
@ 2008-01-05 11:52       ` Robert Millan
  2008-01-05 12:11         ` Bean
  0 siblings, 1 reply; 16+ messages in thread
From: Robert Millan @ 2008-01-05 11:52 UTC (permalink / raw)
  To: The development of GRUB 2


Would be nice if you could include inline attachments without base64 encoding;
that'd make it easier for context-reply.  At least in mutt.

On Sat, Jan 05, 2008 at 03:37:23PM +0800, Bean wrote:
> On Jan 4, 2008 8:08 PM, Bean <bean123ch@gmail.com> wrote:
> > On Jan 4, 2008 7:53 PM, Robert Millan <rmh@aybabtu.com> wrote:
> > > On Thu, Jan 03, 2008 at 01:11:32AM +0800, Bean wrote:
> > > > blst FILE
> > > > display the blocklist of FILE in the image file
> > >
> > > Is this `blst' analogous to the `blocklist' command we already have?  In
> > > that case, I'd suggest giving it the same name.
> >
> > yep, it's the same.
> 
> Change command names:
> 
> dump -> hex
> blst -> blocklist
> 
> Also replace grub_file_open with grub_file_open_ex from my latest
> filehook patch.
> 
> -- 
> Bean


> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel


-- 
Robert Millan

<GPLv2> I know my rights; I want my phone call!
<DRM> What use is a phone call, if you are unable to speak?
(as seen on /.)



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: grub-fstest: debug tool for filesystem driver
  2008-01-05 11:52       ` Robert Millan
@ 2008-01-05 12:11         ` Bean
  2008-01-28 10:45           ` Robert Millan
  0 siblings, 1 reply; 16+ messages in thread
From: Bean @ 2008-01-05 12:11 UTC (permalink / raw)
  To: The development of GRUB 2

On Jan 5, 2008 7:52 PM, Robert Millan <rmh@aybabtu.com> wrote:
>
> Would be nice if you could include inline attachments without base64 encoding;
> that'd make it easier for context-reply.  At least in mutt.
>

ok, here is it.

2008-01-05  Bean <bean123ch@gmail.com>

	* 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 c6a04c9..c4b8835 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 4773f7d..45dfeef 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 2638ee5..a25dd76 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -59,6 +59,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 \
@@ -121,6 +124,18 @@ 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 commands/hexdump.c io/gzio.c	\
+	commands/blocklist.c fs/fat.c fs/ext2.c kern/parser.c		\
+	kern/partition.c partmap/pc.c partmap/apple.c partmap/gpt.c 	\
+	fs/ufs.c fs/minix.c fs/hfs.c fs/jfs.c fs/ntfs.c kern/fs.c	\
+	kern/env.c fs/fshelp.c fs/xfs.c fs/affs.c fs/sfs.c fs/hfsplus.c	\
+	fs/ntfscomp.c fs/iso9660.c fs/cpio.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 bd2d745..8ca04d5 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]
@@ -8141,6 +8144,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"

@@ -8854,11 +8864,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 fb6e026..451230f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -319,6 +319,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 100755
index 0000000..c255dbb
--- /dev/null
+++ b/util/grub-fstest.c
@@ -0,0 +1,540 @@
+/* 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/normal.h>
+#include <grub/hexdump.h>
+
+#include <grub_fstest_init.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define _GNU_SOURCE	1
+#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 grub_err_t (*loopfunc) (struct grub_arg_list * state, int argc,
+			       char **args);
+static grub_err_t (*blstfunc) (struct grub_arg_list * state, int argc,
+			       char **args);
+
+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,
+		       const char *description,
+		       const struct grub_arg_option *options)
+{
+  (void) flags;
+  (void) summary;
+  (void) description;
+  (void) options;
+
+  if (!grub_strcmp (name, "loopback"))
+    loopfunc = func;
+  else if (!grub_strcmp (name, "blocklist"))
+    blstfunc = func;
+
+  return NULL;
+}
+
+void
+grub_unregister_command (const char *name)
+{
+  (void) name;
+}
+
+#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 int part;
+
+static void
+cmd_ls (grub_fs_t fs, grub_device_t dev, char *dirname)
+{
+  auto int print_files_long (const char *filename, int dir);
+  int print_files_long (const char *filename, int dir)
+  {
+    char pathname[grub_strlen (dirname) + grub_strlen (filename) + 1];
+
+    if (!dir)
+      {
+	grub_file_t file;
+
+	if (dirname[grub_strlen (dirname) - 1] == '/')
+	  grub_sprintf (pathname, "%s%s", dirname, filename);
+	else
+	  grub_sprintf (pathname, "%s/%s", dirname, filename);
+
+	file = grub_file_open_ex (pathname, 1);
+	if (!file)
+	  {
+	    grub_errno = 0;
+	    return 0;
+	  }
+
+	grub_printf ("%-12llu", file->size);
+	grub_file_close (file);
+      }
+    else
+      grub_printf ("%-12s", "DIR");
+
+    grub_printf ("%s%s\n", filename, dir ? "/" : "");
+
+    return 0;
+  }
+
+  fs->dir (dev, dirname, print_files_long);
+}
+
+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_ex (pathname, 1);
+  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
+cmd_blocklist (char *pathname)
+{
+  char *argv[1];
+
+  argv[0] = pathname;
+  if (blstfunc (NULL, 1, argv))
+    grub_util_error ("blocklist command fails.\n");
+  else
+    grub_printf ("\n");
+}
+
+static void
+fstest (char *image_path, int cmd, char **parm)
+{
+  grub_device_t dev = 0;
+  grub_fs_t fs;
+  char host_file[7 + grub_strlen (image_path) + 1];
+  struct grub_arg_list state[2];
+  char *argv[2];
+  char device_name[10];
+
+  grub_memset (&state, 0, sizeof (state));
+  state[1].set = (part != 0);
+
+  argv[0] = "loop";
+  grub_sprintf (host_file, "(host)/%s", image_path);
+  argv[1] = host_file;
+
+  if (loopfunc (state, 2, argv))
+    {
+      grub_util_error ("loopback command fails.\n");
+      goto fail;
+    }
+
+  if (part)
+    grub_sprintf (device_name, "loop,%d", part);
+  else
+    grub_strcpy (device_name, "loop");
+
+  dev = grub_device_open (device_name);
+  if (!dev)
+    {
+      grub_util_error ("cannot open device (%s).\n", device_name);
+      goto fail;
+    }
+
+  grub_env_set ("root", device_name);
+
+  fs = grub_fs_probe (dev);
+  if (!fs)
+    {
+      grub_util_error ("Unknown fs.\n");
+      goto fail;
+    }
+
+  grub_util_info ("filesystem %s.", fs->name);
+
+  switch (cmd)
+    {
+    case CMD_LS:
+      cmd_ls (fs, dev, parm[0]);
+      break;
+    case CMD_CP:
+      cmd_cp (parm[0], parm[1]);
+      break;
+    case CMD_CMP:
+      cmd_cmp (parm[0], parm[1]);
+      break;
+    case CMD_HEX:
+      cmd_hex (parm[0]);
+      break;
+    case CMD_BLOCKLIST:
+      cmd_blocklist (parm[0]);
+    }
+
+fail:
+  state[0].set = 1;
+  loopfunc (state, 1, argv);
+
+  if (dev)
+    grub_device_close (dev);
+}
+
+static struct option options[] = {
+  {"part", required_argument, 0, 'p'},
+  {"skip", required_argument, 0, 's'},
+  {"length", required_argument, 0, 'n'},
+  {"raw", required_argument, 0, 'r'},
+  {"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\
+  -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, raw = 0;
+
+  progname = "grub-fstest";
+
+  /* Check for options.  */
+  while (1)
+    {
+      int c = getopt_long (argc, argv, "p:s:n:rhVv", options, 0);
+
+      if (c == -1)
+	break;
+      else
+	switch (c)
+	  {
+	  case 'p':
+	    part = grub_strtoul (optarg, NULL, 0);
+	    break;
+
+	  case 's':
+	    skip = grub_strtoul (optarg, NULL, 0);
+	    break;
+
+	  case 'n':
+	    leng = grub_strtoul (optarg, NULL, 0);
+	    break;
+
+	  case 'r':
+	    raw = 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;
+	}
+      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 (raw)
+    grub_env_set ("filehook", "0");
+
+  /* Do it.  */
+  fstest (image_path + 1, cmd, argv + optind);
+
+  /* Free resources.  */
+  grub_fini_all ();
+
+  grub_hostfs_fini ();
+
+  return 0;
+}

-- 
Bean



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: grub-fstest: debug tool for filesystem driver
  2008-01-05 12:11         ` Bean
@ 2008-01-28 10:45           ` Robert Millan
  2008-01-28 14:48             ` Bean
  0 siblings, 1 reply; 16+ messages in thread
From: Robert Millan @ 2008-01-28 10:45 UTC (permalink / raw)
  To: The development of GRUB 2

On Sat, Jan 05, 2008 at 08:11:21PM +0800, Bean wrote:
> diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
> index 2638ee5..a25dd76 100644
> --- a/conf/i386-pc.rmk
> +++ b/conf/i386-pc.rmk
> @@ -59,6 +59,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 \
> @@ -121,6 +124,18 @@ 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 commands/hexdump.c io/gzio.c	\
> +	commands/blocklist.c fs/fat.c fs/ext2.c kern/parser.c		\
> +	kern/partition.c partmap/pc.c partmap/apple.c partmap/gpt.c 	\
> +	fs/ufs.c fs/minix.c fs/hfs.c fs/jfs.c fs/ntfs.c kern/fs.c	\
> +	kern/env.c fs/fshelp.c fs/xfs.c fs/affs.c fs/sfs.c fs/hfsplus.c	\
> +	fs/ntfscomp.c fs/iso9660.c fs/cpio.c disk/lvm.c disk/raid.c	\
> +	grub_fstest_init.c
> +
>  # Scripts.
>  sbin_SCRIPTS = grub-install
>  bin_SCRIPTS = grub-mkrescue

Can we move this to common.rmk ?  AFAICT, there's nothing i386-pc-specific about
this.

As for the list of filesystems, please reuse the filesystem chunk used on other
commands;  this will improve readability, ensure there are no missing components
(as it has happened before), and overall improve maintainability:

	\
	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                                       \
	\

-- 
Robert Millan

<GPLv2> I know my rights; I want my phone call!
<DRM> What use is a phone call… if you are unable to speak?
(as seen on /.)



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: grub-fstest: debug tool for filesystem driver
  2008-01-28 10:45           ` Robert Millan
@ 2008-01-28 14:48             ` Bean
  2008-01-28 17:27               ` Robert Millan
  0 siblings, 1 reply; 16+ messages in thread
From: Bean @ 2008-01-28 14:48 UTC (permalink / raw)
  To: The development of GRUB 2

On Jan 28, 2008 6:45 PM, Robert Millan <rmh@aybabtu.com> wrote:
> Can we move this to common.rmk ?  AFAICT, there's nothing i386-pc-specific about
> this.
>
> As for the list of filesystems, please reuse the filesystem chunk used on other
> commands;  this will improve readability, ensure there are no missing components
> (as it has happened before), and overall improve maintainability:
>
>         \
>         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                                       \
>         \

ok. i also change a few things, now the program should work better.


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..83cb622
--- /dev/null
+++ b/util/grub-fstest.c
@@ -0,0 +1,548 @@
+/* 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>
+
+#define _GNU_SOURCE	1
+#include <getopt.h>
+
+grub_jmp_buf grub_exit_env;
+
+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 int 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_ex (pathname, 1);
+  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)
+{
+  grub_device_t dev = 0;
+  grub_fs_t fs;
+  char host_file[7 + grub_strlen (image_path) + 1];
+  char *argv[3];
+  int argc = 0;
+  char device_name[10];
+
+  if (part)
+    argv[argc++] = "-p";
+
+  argv[argc++] = "loop";
+
+  grub_sprintf (host_file, "(host)/%s", image_path);
+  argv[argc++] = host_file;
+
+  if (execute_command (&cmd_loopback, argc, argv))
+    {
+      grub_util_error ("loopback command fails.\n");
+      goto fail;
+    }
+
+  if (part)
+    grub_sprintf (device_name, "loop,%d", part);
+  else
+    grub_strcpy (device_name, "loop");
+
+  dev = grub_device_open (device_name);
+  if (!dev)
+    {
+      grub_util_error ("cannot open device (%s).\n", device_name);
+      goto fail;
+    }
+
+  grub_env_set ("root", device_name);
+
+  fs = grub_fs_probe (dev);
+  if (!fs)
+    {
+      grub_util_error ("Unknown fs.\n");
+      goto fail;
+    }
+
+  grub_util_info ("filesystem %s.", fs->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:
+
+  argc = 0;
+  argv[argc++] = "-d";
+  argv[argc++] = "loop";
+
+  execute_command (&cmd_loopback, argc, argv);
+
+  if (dev)
+    grub_device_close (dev);
+}
+
+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 = grub_strtoul (optarg, NULL, 0);
+	    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;
+}


-- 
Bean



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: grub-fstest: debug tool for filesystem driver
  2008-01-28 14:48             ` Bean
@ 2008-01-28 17:27               ` Robert Millan
  2008-01-28 17:35                 ` Bean
  0 siblings, 1 reply; 16+ messages in thread
From: Robert Millan @ 2008-01-28 17:27 UTC (permalink / raw)
  To: The development of GRUB 2

On Mon, Jan 28, 2008 at 10:48:13PM +0800, Bean wrote:
> +#include <stdio.h>
> +#include <unistd.h>
> +#include <string.h>
> +#include <stdlib.h>
> +
> +#define _GNU_SOURCE	1
> +#include <getopt.h>

I suspect this wouldn't work in practice, because any system header can
drag <features.h> in.

-- 
Robert Millan

<GPLv2> I know my rights; I want my phone call!
<DRM> What use is a phone call… if you are unable to speak?
(as seen on /.)



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: grub-fstest: debug tool for filesystem driver
  2008-01-28 17:27               ` Robert Millan
@ 2008-01-28 17:35                 ` Bean
  2008-01-28 18:13                   ` Robert Millan
  0 siblings, 1 reply; 16+ messages in thread
From: Bean @ 2008-01-28 17:35 UTC (permalink / raw)
  To: The development of GRUB 2

On Jan 29, 2008 1:27 AM, Robert Millan <rmh@aybabtu.com> wrote:
> On Mon, Jan 28, 2008 at 10:48:13PM +0800, Bean wrote:
> > +#include <stdio.h>
> > +#include <unistd.h>
> > +#include <string.h>
> > +#include <stdlib.h>
> > +
> > +#define _GNU_SOURCE  1
> > +#include <getopt.h>
>
> I suspect this wouldn't work in practice, because any system header can
> drag <features.h> in.

i'm not sure about this, in fact, the line is copied from
grub-probe.c, perhaps i should remove it.

-- 
Bean



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: grub-fstest: debug tool for filesystem driver
  2008-01-28 17:35                 ` Bean
@ 2008-01-28 18:13                   ` Robert Millan
  2008-01-29 10:18                     ` Bean
  0 siblings, 1 reply; 16+ messages in thread
From: Robert Millan @ 2008-01-28 18:13 UTC (permalink / raw)
  To: The development of GRUB 2

On Tue, Jan 29, 2008 at 01:35:35AM +0800, Bean wrote:
> On Jan 29, 2008 1:27 AM, Robert Millan <rmh@aybabtu.com> wrote:
> > On Mon, Jan 28, 2008 at 10:48:13PM +0800, Bean wrote:
> > > +#include <stdio.h>
> > > +#include <unistd.h>
> > > +#include <string.h>
> > > +#include <stdlib.h>
> > > +
> > > +#define _GNU_SOURCE  1
> > > +#include <getopt.h>
> >
> > I suspect this wouldn't work in practice, because any system header can
> > drag <features.h> in.
> 
> i'm not sure about this, in fact, the line is copied from
> grub-probe.c, perhaps i should remove it.

Sure.  If it was needed, removing it would break build on Glibc.

-- 
Robert Millan

<GPLv2> I know my rights; I want my phone call!
<DRM> What use is a phone call… if you are unable to speak?
(as seen on /.)



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: grub-fstest: debug tool for filesystem driver
  2008-01-28 18:13                   ` Robert Millan
@ 2008-01-29 10:18                     ` Bean
  2008-01-29 13:45                       ` Robert Millan
  0 siblings, 1 reply; 16+ messages in thread
From: Bean @ 2008-01-29 10:18 UTC (permalink / raw)
  To: The development of GRUB 2

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 <bean123ch@gmail.com>

       * 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



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: grub-fstest: debug tool for filesystem driver
  2008-01-29 10:18                     ` Bean
@ 2008-01-29 13:45                       ` Robert Millan
  2008-01-29 13:51                         ` Bean
  0 siblings, 1 reply; 16+ messages in thread
From: Robert Millan @ 2008-01-29 13:45 UTC (permalink / raw)
  To: The development of GRUB 2

On Tue, Jan 29, 2008 at 06:18:35PM +0800, Bean wrote:
> --- 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
> +

Can this be in common.rmk ?

-- 
Robert Millan

<GPLv2> I know my rights; I want my phone call!
<DRM> What use is a phone call… if you are unable to speak?
(as seen on /.)



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: grub-fstest: debug tool for filesystem driver
  2008-01-29 13:45                       ` Robert Millan
@ 2008-01-29 13:51                         ` Bean
  2008-02-03 17:56                           ` Bean
  0 siblings, 1 reply; 16+ messages in thread
From: Bean @ 2008-01-29 13:51 UTC (permalink / raw)
  To: The development of GRUB 2

On Jan 29, 2008 9:45 PM, Robert Millan <rmh@aybabtu.com> wrote:
>
> On Tue, Jan 29, 2008 at 06:18:35PM +0800, Bean wrote:
> > --- 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
> > +
>
> Can this be in common.rmk ?

it seems so, all the required modules are platform independent.

-- 
Bean



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: grub-fstest: debug tool for filesystem driver
  2008-01-29 13:51                         ` Bean
@ 2008-02-03 17:56                           ` Bean
  2008-02-04  8:46                             ` Bean
  0 siblings, 1 reply; 16+ messages in thread
From: Bean @ 2008-02-03 17:56 UTC (permalink / raw)
  To: The development of GRUB 2

Hi,

Some change in this version:

Move grub-fstest.c_DEPENDENCIES and grub_fstest_SOURCES to common.rmk.
Add new option -d for grub-fstest, it's used to set the debug
environment variable.

This could be the final version, if nobody objects, i will check it in.

2008-02-03  Bean <bean123ch@gmail.com>

      * 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.
      (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 4722ac1..ec4c663 100644
--- a/conf/common.rmk
+++ b/conf/common.rmk
@@ -61,6 +61,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=$@:$<
@@ -331,3 +344,23 @@ gzio_mod_LDFLAGS = $(COMMON_LDFLAGS)
 read_mod_SOURCES = commands/read.c
 read_mod_CFLAGS = $(COMMON_CFLAGS)
 read_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+ifeq ($(enable_grub_fstest), yes)
+bin_UTILITIES += grub-fstest
+endif
+
+# 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
diff --git a/configure b/configure
index e5912e2..eced238 100755
--- a/configure
+++ b/configure
@@ -311,7 +311,7 @@ ac_includes_default="\
 # include <unistd.h>
 #endif"

-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME
PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix
program_transform_name bindir sbindir libexecdir datadir sysconfdir
sharedstatedir localstatedir libdir includedir oldincludedir infodir
mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T
LIBS build build_cpu build_vendor build_os host host_cpu host_vendor
host_os target target_cpu target_vendor target_os platform CMP YACC
UNIFONT_HEX INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA AWK SET_MAKE
RUBY CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP
LIBLZO TARGET_CC ac_ct_TARGET_CC OBJCOPY ac_ct_OBJCOPY STRIP
ac_ct_STRIP NM ac_ct_NM TARGET_CFLAGS TARGET_CPPFLAGS TARGET_LDFLAGS
LIBCURSES enable_grub_emu LIBOBJS LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME
PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix
program_transform_name bindir sbindir libexecdir datadir sysconfdir
sharedstatedir localstatedir libdir includedir oldincludedir infodir
mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T
LIBS build build_cpu build_vendor build_os host host_cpu host_vendor
host_os target target_cpu target_vendor target_os platform CMP YACC
UNIFONT_HEX INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA AWK SET_MAKE
RUBY CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP
LIBLZO TARGET_CC ac_ct_TARGET_CC OBJCOPY ac_ct_OBJCOPY STRIP
ac_ct_STRIP NM ac_ct_NM TARGET_CFLAGS TARGET_CPPFLAGS TARGET_LDFLAGS
LIBCURSES enable_grub_emu enable_grub_fstest LIBOBJS LTLIBOBJS'
 ac_subst_files=''

 # Initialize some variables set by options.
@@ -857,6 +857,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]
@@ -7510,6 +7512,13 @@ done
 fi


+# Check whether --enable-grub-fstest or --disable-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"

@@ -8182,6 +8191,7 @@ s,@TARGET_CPPFLAGS@,$TARGET_CPPFLAGS,;t t
 s,@TARGET_LDFLAGS@,$TARGET_LDFLAGS,;t t
 s,@LIBCURSES@,$LIBCURSES,;t t
 s,@enable_grub_emu@,$enable_grub_emu,;t t
+s,@enable_grub_fstest@,$enable_grub_fstest,;t t
 s,@LIBOBJS@,$LIBOBJS,;t t
 s,@LTLIBOBJS@,$LTLIBOBJS,;t t
 CEOF
diff --git a/configure.ac b/configure.ac
index 1f9ca46..73f6087 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..0530aa7
--- /dev/null
+++ b/util/grub-fstest.c
@@ -0,0 +1,522 @@
+/* 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'},
+  {"debug", required_argument, 0, 'd'},
+  {"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\
+  -d, --debug=S             Set debug environment variable\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, *debug_str = 0;
+  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:d: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 'd':
+            debug_str = optarg;
+            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");
+
+  if (debug_str)
+    grub_env_set ("debug", debug_str);
+  /* Do it.  */
+  fstest (image_path + 1, cmd, argc - optind, argv + optind);
+
+  /* Free resources.  */
+  grub_fini_all ();
+
+  grub_hostfs_fini ();
+
+  return 0;
+}


-- 
Bean



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: grub-fstest: debug tool for filesystem driver
  2008-02-03 17:56                           ` Bean
@ 2008-02-04  8:46                             ` Bean
  0 siblings, 0 replies; 16+ messages in thread
From: Bean @ 2008-02-04  8:46 UTC (permalink / raw)
  To: The development of GRUB 2

Committed.

-- 
Bean



^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2008-02-04  8:46 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-01-02 17:11 grub-fstest: debug tool for filesystem driver Bean
2008-01-04 11:53 ` Robert Millan
2008-01-04 12:08   ` Bean
2008-01-05  7:37     ` Bean
2008-01-05 11:52       ` Robert Millan
2008-01-05 12:11         ` Bean
2008-01-28 10:45           ` Robert Millan
2008-01-28 14:48             ` Bean
2008-01-28 17:27               ` Robert Millan
2008-01-28 17:35                 ` Bean
2008-01-28 18:13                   ` Robert Millan
2008-01-29 10:18                     ` Bean
2008-01-29 13:45                       ` Robert Millan
2008-01-29 13:51                         ` Bean
2008-02-03 17:56                           ` Bean
2008-02-04  8:46                             ` Bean

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.