From 92bb078645e55f116ebb253be5292cd10b6ffbb9 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 8 Jan 2011 19:51:08 +0100 Subject: [PATCH 01/13] grub-fuse --- Makefile.util.def | 15 ++ config.h.in | 4 + configure.ac | 37 ++++ docs/man/grub-fuse.h2m | 2 + util/grub-fuse.c | 455 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 513 insertions(+) create mode 100644 docs/man/grub-fuse.h2m create mode 100644 util/grub-fuse.c diff --git a/Makefile.util.def b/Makefile.util.def index 74984e2e9..369d312f6 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -212,6 +212,21 @@ program = { ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)'; }; +program = { + name = grub-fuse; + mansection = 1; + common_nodist = grub_fstest_init.c; + common = util/grub-fuse.c; + common = grub-core/kern/emu/hostfs.c; + common = grub-core/disk/host.c; + + ldadd = libgrubmods.a; + ldadd = libgrubkern.a; + ldadd = grub-core/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)' '-lfuse'; + condition = COND_GRUB_FUSE; +}; + program = { name = grub-mkfont; mansection = 1; diff --git a/config.h.in b/config.h.in index 6d7d95dec..3974ad7d5 100644 --- a/config.h.in +++ b/config.h.in @@ -1,3 +1,7 @@ +#undef _LARGEFILE_SOURCE +#undef _FILE_OFFSET_BITS +#define _LARGEFILE_SOURCE +#define _FILE_OFFSET_BITS 64 #if defined (GRUB_UTIL) || !defined (GRUB_MACHINE) #include #define NESTED_FUNC_ATTR diff --git a/configure.ac b/configure.ac index 8bb585a78..e9e31e7fb 100644 --- a/configure.ac +++ b/configure.ac @@ -856,6 +856,37 @@ AC_SUBST([enable_grub_mkfont]) AC_SUBST([freetype_cflags]) AC_SUBST([freetype_libs]) +AC_ARG_ENABLE([grub-mkfont], + [AS_HELP_STRING([--enable-grub-mkfont], + [build and install the `grub-mkfont' utility (default=guessed)])]) +if test x"$enable_grub_mkfont" = xno ; then + grub_mkfont_excuse="explicitly disabled" +fi + +if test x"$grub_fuse_excuse" = x ; then + AC_CHECK_LIB([fuse], [fuse_main_real], [], + [grub_fuse_excuse="need FUSE library"]) +fi + +if test x"$grub_fuse_excuse" = x ; then + # Check for fuse headers. + SAVED_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -D_FILE_OFFSET_BITS=64" + AC_CHECK_HEADERS([fuse/fuse.h], [], + [grub_fuse_excuse=["need FUSE headers"]]) + CPPFLAGS="$SAVED_CPPFLAGS" +fi + +if test x"$enable_grub_fuse" = xyes && test x"$grub_fuse_excuse" != x ; then + AC_MSG_ERROR([grub-fuse was explicitly requested but can't be compiled]) +fi +if test x"$grub_fuse_excuse" = x ; then +enable_grub_fuse=yes +else +enable_grub_fuse=no +fi +AC_SUBST([enable_grub_fuse]) + AC_ARG_ENABLE([device-mapper], [AS_HELP_STRING([--enable-device-mapper], [enable Linux device-mapper support (default=guessed)])]) @@ -952,6 +983,7 @@ AM_CONDITIONAL([COND_GRUB_EMU_USB], [test x$enable_grub_emu_usb = xyes]) AM_CONDITIONAL([COND_GRUB_EMU_SDL], [test x$enable_grub_emu_sdl = xyes]) AM_CONDITIONAL([COND_GRUB_EMU_PCI], [test x$enable_grub_emu_pci = xyes]) AM_CONDITIONAL([COND_GRUB_MKFONT], [test x$enable_grub_mkfont = xyes]) +AM_CONDITIONAL([COND_GRUB_FUSE], [test x$enable_grub_fuse = xyes]) AM_CONDITIONAL([COND_HAVE_FONT_SOURCE], [test x$FONT_SOURCE != x]) AM_CONDITIONAL([COND_GRUB_PE2ELF], [test x$TARGET_OBJ2ELF != x]) AM_CONDITIONAL([COND_APPLE_CC], [test x$TARGET_APPLE_CC = x1]) @@ -1027,5 +1059,10 @@ echo grub-mkfont: Yes else echo grub-mkfont: No "($grub_mkfont_excuse)" fi +if [ x"$grub_fuse_excuse" = x ]; then +echo grub-fuse: Yes +else +echo grub-fuse: No "($grub_fuse_excuse)" +fi echo "*******************************************************" ] diff --git a/docs/man/grub-fuse.h2m b/docs/man/grub-fuse.h2m new file mode 100644 index 000000000..0e234ddc1 --- /dev/null +++ b/docs/man/grub-fuse.h2m @@ -0,0 +1,2 @@ +[NAME] +grub-fuse \- export GRUB filesystem with FUSE. diff --git a/util/grub-fuse.c b/util/grub-fuse.c new file mode 100644 index 000000000..7f0ad0d0f --- /dev/null +++ b/util/grub-fuse.c @@ -0,0 +1,455 @@ +/* grub-fstest.c - debug tool for filesystem driver */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008,2009,2010 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 . + */ +#define FUSE_USE_VERSION 26 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "progname.h" +#include "argp.h" + +static char *root = NULL; +static char **images = NULL; +static char *debug_str = NULL; +static char **fuse_args = NULL; +static int fuse_argc = 0; +static int num_disks = 0; + +static grub_err_t +execute_command (char *name, int n, char **args) +{ + grub_command_t cmd; + + cmd = grub_command_find (name); + if (! cmd) + grub_util_error (_("can\'t find command %s"), name); + + return (cmd->func) (cmd, n, args); +} + +static int +fuse_getattr (const char *path, struct stat *st) +{ + char *filename, *pathname, *path2; + const char *pathname_t; + grub_fs_t fs; + grub_device_t dev; + struct grub_dirhook_info file_info; + int file_exists = 0; + + /* A hook for iterating directories. */ + auto int find_file (const char *cur_filename, + const struct grub_dirhook_info *info); + int find_file (const char *cur_filename, + const struct grub_dirhook_info *info) + { + if ((info->case_insensitive ? grub_strcasecmp (cur_filename, filename) + : grub_strcmp (cur_filename, filename)) == 0) + { + file_info = *info; + file_exists = 1; + return 1; + } + return 0; + } + + if (path[0] == '/' && path[1] == 0) + { + st->st_dev = 0; + st->st_ino = 0; + st->st_mode = 0555 | S_IFDIR; + st->st_uid = 0; + st->st_gid = 0; + st->st_rdev = 0; + st->st_size = 0; + st->st_blksize = 512; + st->st_blocks = (st->st_blksize + 511) >> 9; + st->st_atime = st->st_mtime = st->st_ctime = 0; + return 0; + } + + file_exists = 0; + dev = grub_device_open (0); + if (! dev) + return -1; + + fs = grub_fs_probe (dev); + if (! fs) + { + grub_device_close (dev); + return -1; + } + + pathname_t = grub_strchr (path, ')'); + if (! pathname_t) + pathname_t = path; + else + pathname_t++; + pathname = xstrdup (pathname_t); + + /* Remove trailing '/'. */ + while (*pathname && pathname[grub_strlen (pathname) - 1] == '/') + pathname[grub_strlen (pathname) - 1] = 0; + + /* Split into path and filename. */ + filename = grub_strrchr (pathname, '/'); + if (! filename) + { + path2 = grub_strdup ("/"); + filename = pathname; + } + else + { + filename++; + path2 = grub_strdup (pathname); + path2[filename - pathname] = 0; + } + + /* It's the whole device. */ + (fs->dir) (dev, path2, find_file); + + grub_device_close (dev); + grub_free (path2); + if (!file_exists) + return -1; + st->st_dev = 0; + st->st_ino = 0; + st->st_mode = file_info.dir ? (0555 | S_IFDIR) : (0444 | S_IFREG); + st->st_uid = 0; + st->st_gid = 0; + st->st_rdev = 0; + if (!file_info.dir) + { + grub_file_t file; + file = grub_file_open (path); + if (! file) + { + grub_print_error (); + return -1; + } + st->st_size = file->size; + grub_file_close (file); + } + else + st->st_size = 0; + st->st_blksize = 512; + st->st_blocks = (st->st_size + 511) >> 9; + st->st_atime = st->st_mtime = st->st_ctime = file_info.mtimeset + ? file_info.mtime : 0; + return 0; +} + +static int +fuse_opendir (const char *path, struct fuse_file_info *fi) +{ + return 0; +} + +/* FIXME */ +static grub_file_t files[65536]; +static int first_fd = 1; + +static int +fuse_open (const char *path, struct fuse_file_info *fi __attribute__ ((unused))) +{ + grub_file_t file; + file = grub_file_open (path); + if (! file) + { + grub_print_error (); + return -1; + } + files[first_fd++] = file; + fi->fh = first_fd; + files[first_fd++] = file; + return 0; +} + +static int +fuse_read (const char *path, char *buf, size_t sz, off_t off, + struct fuse_file_info *fi) +{ + grub_file_t file = files[fi->fh]; + + if (off > file->size) + return -1; + + file->offset = off; + + return grub_file_read (file, buf, sz); +} + +static int +fuse_release (const char *path, struct fuse_file_info *fi) +{ + grub_file_close (files[fi->fh]); + files[fi->fh] = NULL; + return 0; +} + +static int +fuse_readdir (const char *path, void *buf, + fuse_fill_dir_t fill, off_t off, struct fuse_file_info *fi) +{ + char *pathname; + grub_fs_t fs; + grub_device_t dev; + + auto int call_fill (const char *filename, + const struct grub_dirhook_info *info); + int call_fill (const char *filename, const struct grub_dirhook_info *info) + { + fill (buf, filename, NULL, 0); + return 0; + } + + dev = grub_device_open (0); + if (! dev) + { + return 1; + } + + fs = grub_fs_probe (dev); + if (! fs) + { + grub_device_close (dev); + return 1; + } + + pathname = xstrdup (path); + + /* Remove trailing '/'. */ + while (pathname [0] && pathname[1] + && pathname[grub_strlen (pathname) - 1] == '/') + pathname[grub_strlen (pathname) - 1] = 0; + + (fs->dir) (dev, pathname, call_fill); + grub_device_close (dev); + free (pathname); + return 0; +} + +struct fuse_operations grub_opers = { + .getattr = fuse_getattr, + .open = fuse_open, + .release = fuse_release, + .opendir = fuse_opendir, + .readdir = fuse_readdir, + .read = fuse_read +}; + +static void +fuse_init (void) +{ + int i; + + for (i = 0; i < num_disks; i++) + { + char *argv[2]; + char *host_file; + char *loop_name; + loop_name = grub_xasprintf ("loop%d", i); + if (!loop_name) + grub_util_error (grub_errmsg); + + host_file = grub_xasprintf ("(host)%s", images[i]); + if (!host_file) + grub_util_error (grub_errmsg); + + argv[0] = loop_name; + argv[1] = host_file; + + if (execute_command ("loopback", 2, argv)) + grub_util_error (_("loopback command fails")); + + grub_free (loop_name); + grub_free (host_file); + } + + grub_lvm_fini (); + grub_mdraid09_fini (); + grub_mdraid1x_fini (); + grub_raid_fini (); + grub_raid_init (); + grub_mdraid09_init (); + grub_mdraid1x_init (); + grub_lvm_init (); + + fuse_main (fuse_argc, fuse_args, &grub_opers, NULL); + + for (i = 0; i < num_disks; i++) + { + char *argv[2]; + char *loop_name; + + loop_name = grub_xasprintf ("loop%d", i); + if (!loop_name) + grub_util_error (grub_errmsg); + + argv[0] = "-d"; + argv[1] = loop_name; + + execute_command ("loopback", 2, argv); + + grub_free (loop_name); + } +} + +static struct argp_option options[] = { + {"root", 'r', N_("DEVICE_NAME"), 0, N_("Set root device."), 2}, + {"debug", 'd', "S", 0, N_("Set debug environment variable."), 2}, + {"verbose", 'v', NULL, OPTION_ARG_OPTIONAL, N_("Print verbose messages."), 2}, + {0, 0, 0, 0, 0, 0} +}; + +/* Print the version information. */ +static void +print_version (FILE *stream, struct argp_state *state) +{ + fprintf (stream, "%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION); +} +void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version; + +error_t +argp_parser (int key, char *arg, struct argp_state *state) +{ + char *p; + + switch (key) + { + case 'r': + root = arg; + return 0; + + case 'd': + debug_str = arg; + return 0; + + case 'v': + verbosity++; + return 0; + + case ARGP_KEY_ARG: + if (arg[0] != '-') + break; + + default: + if (!arg) + return 0; + + fuse_args = xrealloc (fuse_args, (fuse_argc + 1) * sizeof (fuse_args[0])); + fuse_args[fuse_argc] = xstrdup (arg); + fuse_argc++; + return 0; + } + + if (arg[0] != '/') + { + fprintf (stderr, "%s", _("Must use absolute path.\n")); + argp_usage (state); + } + images = xrealloc (images, (num_disks + 1) * sizeof (images[0])); + images[num_disks] = xstrdup (arg); + num_disks++; + + return 0; +} + +struct argp argp = { + options, argp_parser, N_("IMAGE1 [IMAGE2 ...] MOUNTPOINT"), + N_("Debug tool for filesystem driver."), + NULL, NULL, NULL +}; + +int +main (int argc, char *argv[]) +{ + char *default_root, *alloc_root; + + set_program_name (argv[0]); + + grub_util_init_nls (); + + fuse_args = xrealloc (fuse_args, (fuse_argc + 1) * sizeof (fuse_args[0])); + fuse_args[fuse_argc] = xstrdup (argv[0]); + fuse_argc++; + + argp_parse (&argp, argc, argv, 0, 0, 0); + + if (num_disks < 2) + grub_util_error ("need an image and mountpoint"); + fuse_args = xrealloc (fuse_args, (fuse_argc + 2) * sizeof (fuse_args[0])); + fuse_args[fuse_argc] = images[num_disks - 1]; + fuse_argc++; + num_disks--; + fuse_args[fuse_argc] = NULL; + + /* Initialize all modules. */ + grub_init_all (); + + if (debug_str) + grub_env_set ("debug", debug_str); + + default_root = (num_disks == 1) ? "loop0" : "md0"; + alloc_root = 0; + if (root) + { + if ((*root >= '0') && (*root <= '9')) + { + alloc_root = xmalloc (strlen (default_root) + strlen (root) + 2); + + sprintf (alloc_root, "%s,%s", default_root, root); + root = alloc_root; + } + } + else + root = default_root; + + grub_env_set ("root", root); + + if (alloc_root) + free (alloc_root); + + /* Do it. */ + fuse_init (); + + /* Free resources. */ + grub_fini_all (); + + return 0; +} From 89644ef113f00c03b18d075243debf5417e00549 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Tue, 11 Jan 2011 21:20:54 +0100 Subject: [PATCH 02/13] Rename grub-fuse to grub-mount (with Vladimir's blessing) --- Makefile.util.def | 4 ++-- configure.ac | 6 +++--- docs/man/grub-fuse.h2m | 2 -- docs/man/grub-mount.h2m | 2 ++ util/{grub-fuse.c => grub-mount.c} | 0 5 files changed, 7 insertions(+), 7 deletions(-) delete mode 100644 docs/man/grub-fuse.h2m create mode 100644 docs/man/grub-mount.h2m rename util/{grub-fuse.c => grub-mount.c} (100%) diff --git a/Makefile.util.def b/Makefile.util.def index 369d312f6..3009ff76a 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -213,10 +213,10 @@ program = { }; program = { - name = grub-fuse; + name = grub-mount; mansection = 1; common_nodist = grub_fstest_init.c; - common = util/grub-fuse.c; + common = util/grub-mount.c; common = grub-core/kern/emu/hostfs.c; common = grub-core/disk/host.c; diff --git a/configure.ac b/configure.ac index e9e31e7fb..b71aea910 100644 --- a/configure.ac +++ b/configure.ac @@ -878,7 +878,7 @@ if test x"$grub_fuse_excuse" = x ; then fi if test x"$enable_grub_fuse" = xyes && test x"$grub_fuse_excuse" != x ; then - AC_MSG_ERROR([grub-fuse was explicitly requested but can't be compiled]) + AC_MSG_ERROR([grub-mount was explicitly requested but can't be compiled]) fi if test x"$grub_fuse_excuse" = x ; then enable_grub_fuse=yes @@ -1060,9 +1060,9 @@ else echo grub-mkfont: No "($grub_mkfont_excuse)" fi if [ x"$grub_fuse_excuse" = x ]; then -echo grub-fuse: Yes +echo grub-mount: Yes else -echo grub-fuse: No "($grub_fuse_excuse)" +echo grub-mount: No "($grub_fuse_excuse)" fi echo "*******************************************************" ] diff --git a/docs/man/grub-fuse.h2m b/docs/man/grub-fuse.h2m deleted file mode 100644 index 0e234ddc1..000000000 --- a/docs/man/grub-fuse.h2m +++ /dev/null @@ -1,2 +0,0 @@ -[NAME] -grub-fuse \- export GRUB filesystem with FUSE. diff --git a/docs/man/grub-mount.h2m b/docs/man/grub-mount.h2m new file mode 100644 index 000000000..73e7246a3 --- /dev/null +++ b/docs/man/grub-mount.h2m @@ -0,0 +1,2 @@ +[NAME] +grub-mount \- export GRUB filesystem with FUSE. diff --git a/util/grub-fuse.c b/util/grub-mount.c similarity index 100% rename from util/grub-fuse.c rename to util/grub-mount.c From b0bfc5937d6232c01dbb44f7ad3135eb5aa07ff8 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Fri, 8 Apr 2011 10:31:32 +0100 Subject: [PATCH 03/13] fix header comment --- util/grub-mount.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/grub-mount.c b/util/grub-mount.c index 7f0ad0d0f..c1c7ecad8 100644 --- a/util/grub-mount.c +++ b/util/grub-mount.c @@ -1,4 +1,4 @@ -/* grub-fstest.c - debug tool for filesystem driver */ +/* grub-mount.c - FUSE driver for filesystems that GRUB understands */ /* * GRUB -- GRand Unified Bootloader * Copyright (C) 2008,2009,2010 Free Software Foundation, Inc. From 9aa6fcc17e7b7d6e1712a0cc400c39b44a6e6a72 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Fri, 8 Apr 2011 10:38:41 +0100 Subject: [PATCH 04/13] fix duplicate --enable-grub-mkfont option; this should be --enable-grub-fuse instead --- configure.ac | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index b71aea910..12ac0e917 100644 --- a/configure.ac +++ b/configure.ac @@ -856,11 +856,11 @@ AC_SUBST([enable_grub_mkfont]) AC_SUBST([freetype_cflags]) AC_SUBST([freetype_libs]) -AC_ARG_ENABLE([grub-mkfont], - [AS_HELP_STRING([--enable-grub-mkfont], - [build and install the `grub-mkfont' utility (default=guessed)])]) -if test x"$enable_grub_mkfont" = xno ; then - grub_mkfont_excuse="explicitly disabled" +AC_ARG_ENABLE([grub-fuse], + [AS_HELP_STRING([--enable-grub-fuse], + [build and install the `grub-fuse' utility (default=guessed)])]) +if test x"$enable_grub_fuse" = xno ; then + grub_fuse_excuse="explicitly disabled" fi if test x"$grub_fuse_excuse" = x ; then From 897e62079e0bab32f089a44b791116493d34ef45 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Fri, 8 Apr 2011 10:43:12 +0100 Subject: [PATCH 05/13] rename grub-fuse to grub-mount throughout configuration --- Makefile.util.def | 2 +- configure.ac | 34 +++++++++++++++++----------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Makefile.util.def b/Makefile.util.def index 3009ff76a..cd37d0d65 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -224,7 +224,7 @@ program = { ldadd = libgrubkern.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)' '-lfuse'; - condition = COND_GRUB_FUSE; + condition = COND_GRUB_MOUNT; }; program = { diff --git a/configure.ac b/configure.ac index 12ac0e917..d1eaa0c84 100644 --- a/configure.ac +++ b/configure.ac @@ -856,36 +856,36 @@ AC_SUBST([enable_grub_mkfont]) AC_SUBST([freetype_cflags]) AC_SUBST([freetype_libs]) -AC_ARG_ENABLE([grub-fuse], - [AS_HELP_STRING([--enable-grub-fuse], - [build and install the `grub-fuse' utility (default=guessed)])]) -if test x"$enable_grub_fuse" = xno ; then - grub_fuse_excuse="explicitly disabled" +AC_ARG_ENABLE([grub-mount], + [AS_HELP_STRING([--enable-grub-mount], + [build and install the `grub-mount' utility (default=guessed)])]) +if test x"$enable_grub_mount" = xno ; then + grub_mount_excuse="explicitly disabled" fi -if test x"$grub_fuse_excuse" = x ; then +if test x"$grub_mount_excuse" = x ; then AC_CHECK_LIB([fuse], [fuse_main_real], [], - [grub_fuse_excuse="need FUSE library"]) + [grub_mount_excuse="need FUSE library"]) fi -if test x"$grub_fuse_excuse" = x ; then +if test x"$grub_mount_excuse" = x ; then # Check for fuse headers. SAVED_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS -D_FILE_OFFSET_BITS=64" AC_CHECK_HEADERS([fuse/fuse.h], [], - [grub_fuse_excuse=["need FUSE headers"]]) + [grub_mount_excuse=["need FUSE headers"]]) CPPFLAGS="$SAVED_CPPFLAGS" fi -if test x"$enable_grub_fuse" = xyes && test x"$grub_fuse_excuse" != x ; then +if test x"$enable_grub_mount" = xyes && test x"$grub_mount_excuse" != x ; then AC_MSG_ERROR([grub-mount was explicitly requested but can't be compiled]) fi -if test x"$grub_fuse_excuse" = x ; then -enable_grub_fuse=yes +if test x"$grub_mount_excuse" = x ; then +enable_grub_mount=yes else -enable_grub_fuse=no +enable_grub_mount=no fi -AC_SUBST([enable_grub_fuse]) +AC_SUBST([enable_grub_mount]) AC_ARG_ENABLE([device-mapper], [AS_HELP_STRING([--enable-device-mapper], @@ -983,7 +983,7 @@ AM_CONDITIONAL([COND_GRUB_EMU_USB], [test x$enable_grub_emu_usb = xyes]) AM_CONDITIONAL([COND_GRUB_EMU_SDL], [test x$enable_grub_emu_sdl = xyes]) AM_CONDITIONAL([COND_GRUB_EMU_PCI], [test x$enable_grub_emu_pci = xyes]) AM_CONDITIONAL([COND_GRUB_MKFONT], [test x$enable_grub_mkfont = xyes]) -AM_CONDITIONAL([COND_GRUB_FUSE], [test x$enable_grub_fuse = xyes]) +AM_CONDITIONAL([COND_GRUB_MOUNT], [test x$enable_grub_mount = xyes]) AM_CONDITIONAL([COND_HAVE_FONT_SOURCE], [test x$FONT_SOURCE != x]) AM_CONDITIONAL([COND_GRUB_PE2ELF], [test x$TARGET_OBJ2ELF != x]) AM_CONDITIONAL([COND_APPLE_CC], [test x$TARGET_APPLE_CC = x1]) @@ -1059,10 +1059,10 @@ echo grub-mkfont: Yes else echo grub-mkfont: No "($grub_mkfont_excuse)" fi -if [ x"$grub_fuse_excuse" = x ]; then +if [ x"$grub_mount_excuse" = x ]; then echo grub-mount: Yes else -echo grub-mount: No "($grub_fuse_excuse)" +echo grub-mount: No "($grub_mount_excuse)" fi echo "*******************************************************" ] From f387685926dc0dedfa8eace8a76955c845e25a84 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Fri, 8 Apr 2011 11:45:10 +0100 Subject: [PATCH 06/13] remove trailing full stop, for consistency with other pages --- docs/man/grub-mount.h2m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/man/grub-mount.h2m b/docs/man/grub-mount.h2m index 73e7246a3..8d168982d 100644 --- a/docs/man/grub-mount.h2m +++ b/docs/man/grub-mount.h2m @@ -1,2 +1,2 @@ [NAME] -grub-mount \- export GRUB filesystem with FUSE. +grub-mount \- export GRUB filesystem with FUSE From 5b3633002b9fb95c830a4c339c64a25fa43013ea Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Sun, 10 Apr 2011 21:41:55 +0100 Subject: [PATCH 07/13] Make grub-mount exit non-zero if opening the device or filesystem fails. Translate GRUB error codes into OS error codes for FUSE. --- util/grub-mount.c | 132 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 91 insertions(+), 41 deletions(-) diff --git a/util/grub-mount.c b/util/grub-mount.c index c1c7ecad8..efada771a 100644 --- a/util/grub-mount.c +++ b/util/grub-mount.c @@ -44,6 +44,8 @@ #include "argp.h" static char *root = NULL; +grub_device_t dev = NULL; +grub_fs_t fs = NULL; static char **images = NULL; static char *debug_str = NULL; static char **fuse_args = NULL; @@ -62,13 +64,61 @@ execute_command (char *name, int n, char **args) return (cmd->func) (cmd, n, args); } +/* Translate GRUB error numbers into OS error numbers. Print any unexpected + errors. */ +static int +translate_error (void) +{ + int ret; + + switch (grub_errno) + { + case GRUB_ERR_NONE: + ret = 0; + break; + + case GRUB_ERR_OUT_OF_MEMORY: + grub_print_error (); + ret = -ENOMEM; + break; + + case GRUB_ERR_BAD_FILE_TYPE: + /* This could also be EISDIR. Take a guess. */ + ret = -ENOTDIR; + break; + + case GRUB_ERR_FILE_NOT_FOUND: + ret = -ENOENT; + break; + + case GRUB_ERR_FILE_READ_ERROR: + case GRUB_ERR_READ_ERROR: + case GRUB_ERR_IO: + grub_print_error (); + ret = -EIO; + break; + + case GRUB_ERR_SYMLINK_LOOP: + ret = -ELOOP; + break; + + default: + grub_print_error (); + ret = -EINVAL; + break; + } + + /* Any previous errors were handled. */ + grub_errno = GRUB_ERR_NONE; + + return ret; +} + static int fuse_getattr (const char *path, struct stat *st) { char *filename, *pathname, *path2; const char *pathname_t; - grub_fs_t fs; - grub_device_t dev; struct grub_dirhook_info file_info; int file_exists = 0; @@ -104,16 +154,6 @@ fuse_getattr (const char *path, struct stat *st) } file_exists = 0; - dev = grub_device_open (0); - if (! dev) - return -1; - - fs = grub_fs_probe (dev); - if (! fs) - { - grub_device_close (dev); - return -1; - } pathname_t = grub_strchr (path, ')'); if (! pathname_t) @@ -143,10 +183,12 @@ fuse_getattr (const char *path, struct stat *st) /* It's the whole device. */ (fs->dir) (dev, path2, find_file); - grub_device_close (dev); grub_free (path2); if (!file_exists) - return -1; + { + grub_errno = GRUB_ERR_NONE; + return -ENOENT; + } st->st_dev = 0; st->st_ino = 0; st->st_mode = file_info.dir ? (0555 | S_IFDIR) : (0444 | S_IFREG); @@ -158,10 +200,7 @@ fuse_getattr (const char *path, struct stat *st) grub_file_t file; file = grub_file_open (path); if (! file) - { - grub_print_error (); - return -1; - } + return translate_error (); st->st_size = file->size; grub_file_close (file); } @@ -171,6 +210,7 @@ fuse_getattr (const char *path, struct stat *st) st->st_blocks = (st->st_size + 511) >> 9; st->st_atime = st->st_mtime = st->st_ctime = file_info.mtimeset ? file_info.mtime : 0; + grub_errno = GRUB_ERR_NONE; return 0; } @@ -190,13 +230,11 @@ fuse_open (const char *path, struct fuse_file_info *fi __attribute__ ((unused))) grub_file_t file; file = grub_file_open (path); if (! file) - { - grub_print_error (); - return -1; - } + return translate_error (); files[first_fd++] = file; fi->fh = first_fd; files[first_fd++] = file; + grub_errno = GRUB_ERR_NONE; return 0; } @@ -205,13 +243,21 @@ fuse_read (const char *path, char *buf, size_t sz, off_t off, struct fuse_file_info *fi) { grub_file_t file = files[fi->fh]; + grub_ssize_t size; if (off > file->size) - return -1; + return -EINVAL; file->offset = off; - return grub_file_read (file, buf, sz); + size = grub_file_read (file, buf, sz); + if (size < 0) + return translate_error (); + else + { + grub_errno = GRUB_ERR_NONE; + return size; + } } static int @@ -219,6 +265,7 @@ fuse_release (const char *path, struct fuse_file_info *fi) { grub_file_close (files[fi->fh]); files[fi->fh] = NULL; + grub_errno = GRUB_ERR_NONE; return 0; } @@ -227,8 +274,6 @@ fuse_readdir (const char *path, void *buf, fuse_fill_dir_t fill, off_t off, struct fuse_file_info *fi) { char *pathname; - grub_fs_t fs; - grub_device_t dev; auto int call_fill (const char *filename, const struct grub_dirhook_info *info); @@ -238,19 +283,6 @@ fuse_readdir (const char *path, void *buf, return 0; } - dev = grub_device_open (0); - if (! dev) - { - return 1; - } - - fs = grub_fs_probe (dev); - if (! fs) - { - grub_device_close (dev); - return 1; - } - pathname = xstrdup (path); /* Remove trailing '/'. */ @@ -259,8 +291,8 @@ fuse_readdir (const char *path, void *buf, pathname[grub_strlen (pathname) - 1] = 0; (fs->dir) (dev, pathname, call_fill); - grub_device_close (dev); free (pathname); + grub_errno = GRUB_ERR_NONE; return 0; } @@ -273,7 +305,7 @@ struct fuse_operations grub_opers = { .read = fuse_read }; -static void +static grub_err_t fuse_init (void) { int i; @@ -310,6 +342,17 @@ fuse_init (void) grub_mdraid1x_init (); grub_lvm_init (); + dev = grub_device_open (0); + if (! dev) + return grub_errno; + + fs = grub_fs_probe (dev); + if (! fs) + { + grub_device_close (dev); + return grub_errno; + } + fuse_main (fuse_argc, fuse_args, &grub_opers, NULL); for (i = 0; i < num_disks; i++) @@ -328,6 +371,8 @@ fuse_init (void) grub_free (loop_name); } + + return GRUB_ERR_NONE; } static struct argp_option options[] = { @@ -447,6 +492,11 @@ main (int argc, char *argv[]) /* Do it. */ fuse_init (); + if (grub_errno) + { + grub_print_error (); + return 1; + } /* Free resources. */ grub_fini_all (); From 4ac93e6c4f8137a32a9591caf9cf7e2af234c12b Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Sun, 10 Apr 2011 22:12:23 +0100 Subject: [PATCH 08/13] add grub-mount to .bzrignore --- .bzrignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.bzrignore b/.bzrignore index 0cbb3f17f..d4d5987ec 100644 --- a/.bzrignore +++ b/.bzrignore @@ -44,6 +44,7 @@ grub-kbdcomp grub-macho2img grub-menulst2cfg grub-mk* +grub-mount grub-pbkdf2 grub-pe2elf grub-probe From 2a861f38a7f0b17ada0057b139f9ad6f63aad24f Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Thu, 14 Apr 2011 20:27:27 +0100 Subject: [PATCH 09/13] Tell FUSE to run single-threaded, since GRUB code is not thread-safe. Fixes Ubuntu bug #756297. --- util/grub-mount.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/util/grub-mount.c b/util/grub-mount.c index efada771a..434772eec 100644 --- a/util/grub-mount.c +++ b/util/grub-mount.c @@ -450,9 +450,12 @@ main (int argc, char *argv[]) grub_util_init_nls (); - fuse_args = xrealloc (fuse_args, (fuse_argc + 1) * sizeof (fuse_args[0])); + fuse_args = xrealloc (fuse_args, (fuse_argc + 2) * sizeof (fuse_args[0])); fuse_args[fuse_argc] = xstrdup (argv[0]); fuse_argc++; + /* Run single-threaded. */ + fuse_args[fuse_argc] = xstrdup ("-s"); + fuse_argc++; argp_parse (&argp, argc, argv, 0, 0, 0); From 338c7fab9be66bc5aa6cf093539a0aafa4010b83 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Sat, 11 Jun 2011 16:57:19 +0200 Subject: [PATCH 10/13] fix grub-mount buildability on GNU/kFreeBSD --- Makefile.util.def | 2 +- configure.ac | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.util.def b/Makefile.util.def index cd37d0d65..313339adc 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -223,7 +223,7 @@ program = { ldadd = libgrubmods.a; ldadd = libgrubkern.a; ldadd = grub-core/gnulib/libgnu.a; - ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)' '-lfuse'; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) -lfuse'; condition = COND_GRUB_MOUNT; }; diff --git a/configure.ac b/configure.ac index d1eaa0c84..26af7e7c3 100644 --- a/configure.ac +++ b/configure.ac @@ -871,7 +871,7 @@ fi if test x"$grub_mount_excuse" = x ; then # Check for fuse headers. SAVED_CPPFLAGS="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS -D_FILE_OFFSET_BITS=64" + CPPFLAGS="$CPPFLAGS -D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=26" AC_CHECK_HEADERS([fuse/fuse.h], [], [grub_mount_excuse=["need FUSE headers"]]) CPPFLAGS="$SAVED_CPPFLAGS" From f1f233ba430c27cbc6a327751bd3da53798cdf2f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 12 Nov 2011 00:56:20 +0100 Subject: [PATCH 11/13] Add crypto support to grub-mount --- Makefile.util.def | 1 + util/grub-mount.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/Makefile.util.def b/Makefile.util.def index 567747fc7..5f655b73d 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -246,6 +246,7 @@ program = { common = grub-core/disk/host.c; ldadd = libgrubmods.a; + ldadd = libgrubgcry.a; ldadd = libgrubkern.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) -lfuse'; diff --git a/util/grub-mount.c b/util/grub-mount.c index 434772eec..7c75acd15 100644 --- a/util/grub-mount.c +++ b/util/grub-mount.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -51,6 +52,7 @@ static char *debug_str = NULL; static char **fuse_args = NULL; static int fuse_argc = 0; static int num_disks = 0; +static int mount_crypt = 0; static grub_err_t execute_command (char *name, int n, char **args) @@ -333,6 +335,13 @@ fuse_init (void) grub_free (host_file); } + if (mount_crypt) + { + char *argv[2] = { "-a", NULL}; + if (execute_command ("cryptomount", 1, argv)) + grub_util_error (_("cryptomount command fails: %s"), grub_errmsg); + } + grub_lvm_fini (); grub_mdraid09_fini (); grub_mdraid1x_fini (); @@ -378,6 +387,8 @@ fuse_init (void) static struct argp_option options[] = { {"root", 'r', N_("DEVICE_NAME"), 0, N_("Set root device."), 2}, {"debug", 'd', "S", 0, N_("Set debug environment variable."), 2}, + {"crypto", 'C', NULL, OPTION_ARG_OPTIONAL, N_("Mount crypto devices."), 2}, + {"zfs-key", 'K', N_("FILE|prompt"), 0, N_("Load zfs crypto key."), 2}, {"verbose", 'v', NULL, OPTION_ARG_OPTIONAL, N_("Print verbose messages."), 2}, {0, 0, 0, 0, 0, 0} }; @@ -401,6 +412,42 @@ argp_parser (int key, char *arg, struct argp_state *state) root = arg; return 0; + case 'K': + if (strcmp (arg, "prompt") == 0) + { + char buf[1024]; + grub_printf ("Enter ZFS password: "); + if (grub_password_get (buf, 1023)) + { + grub_zfs_add_key ((grub_uint8_t *) buf, grub_strlen (buf), 1); + } + } + else + { + FILE *f; + ssize_t real_size; + grub_uint8_t buf[1024]; + f = fopen (arg, "rb"); + if (!f) + { + printf ("Error loading file %s: %s\n", arg, strerror (errno)); + return 0; + } + real_size = fread (buf, 1, 1024, f); + if (real_size < 0) + { + printf ("Error loading file %s: %s\n", arg, strerror (errno)); + fclose (f); + return 0; + } + grub_zfs_add_key (buf, real_size, 0); + } + return 0; + + case 'C': + mount_crypt = 1; + return 0; + case 'd': debug_str = arg; return 0; From d8e62bbeb95c357ac597db5ce28df20f7a9d9823 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 12 Nov 2011 01:19:06 +0100 Subject: [PATCH 12/13] gettextize --- util/grub-mount.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/util/grub-mount.c b/util/grub-mount.c index 7c75acd15..f084fbf98 100644 --- a/util/grub-mount.c +++ b/util/grub-mount.c @@ -416,7 +416,7 @@ argp_parser (int key, char *arg, struct argp_state *state) if (strcmp (arg, "prompt") == 0) { char buf[1024]; - grub_printf ("Enter ZFS password: "); + grub_printf ("%s", _("Enter ZFS password: ")); if (grub_password_get (buf, 1023)) { grub_zfs_add_key ((grub_uint8_t *) buf, grub_strlen (buf), 1); @@ -430,13 +430,13 @@ argp_parser (int key, char *arg, struct argp_state *state) f = fopen (arg, "rb"); if (!f) { - printf ("Error loading file %s: %s\n", arg, strerror (errno)); + printf (_("Error loading file %s: %s\n"), arg, strerror (errno)); return 0; } real_size = fread (buf, 1, 1024, f); if (real_size < 0) { - printf ("Error loading file %s: %s\n", arg, strerror (errno)); + printf (_("Error loading file %s: %s\n"), arg, strerror (errno)); fclose (f); return 0; } @@ -507,7 +507,7 @@ main (int argc, char *argv[]) argp_parse (&argp, argc, argv, 0, 0, 0); if (num_disks < 2) - grub_util_error ("need an image and mountpoint"); + grub_util_error (_("need an image and mountpoint")); fuse_args = xrealloc (fuse_args, (fuse_argc + 2) * sizeof (fuse_args[0])); fuse_args[fuse_argc] = images[num_disks - 1]; fuse_argc++; From ae60d685fad88cb461b6479ee28115c1d5251293 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 12 Nov 2011 01:20:23 +0100 Subject: [PATCH 13/13] fill attr on readdir --- util/grub-mount.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/util/grub-mount.c b/util/grub-mount.c index f084fbf98..a4be21738 100644 --- a/util/grub-mount.c +++ b/util/grub-mount.c @@ -281,7 +281,26 @@ fuse_readdir (const char *path, void *buf, const struct grub_dirhook_info *info); int call_fill (const char *filename, const struct grub_dirhook_info *info) { - fill (buf, filename, NULL, 0); + struct stat st; + grub_memset (&st, 0, sizeof (st)); + st.st_mode = info->dir ? (0555 | S_IFDIR) : (0444 | S_IFREG); + if (!info->dir) + { + grub_file_t file; + char *tmp; + tmp = xasprintf ("%s/%s", path, filename); + file = grub_file_open (tmp); + free (tmp); + if (! file) + return translate_error (); + st.st_size = file->size; + grub_file_close (file); + } + st.st_blksize = 512; + st.st_blocks = (st.st_size + 511) >> 9; + st.st_atime = st.st_mtime = st.st_ctime + = info->mtimeset ? info->mtime : 0; + fill (buf, filename, &st, 0); return 0; }