On Wed, Jul 14, 2010 at 7:51 PM, Carl Fredrik Hammar
<hammy.l...@gmail.com> wrote:
> On Tue, Jul 13, 2010 at 08:00:24PM +0200, Jérémie Koenig wrote:
>> The second one, which I favor and am working on so far, would be to
>> enumerate the _grub_ devices, and use get_storage_info() on them too.
> (...)
>
> This is a bit hacky but could be a good intermediate solution if your
> not comfortable with adding a new RPC that isn't strongly related to
> your project.

For what it's worth, I attach the patch I'm currently using.

-- 
Jérémie Koenig <j...@jk.fr.eu.org>
http://jk.fr.eu.org/
=== modified file 'Makefile.in'
Index: Makefile.in
===================================================================
--- Makefile.in.orig	2010-07-12 10:43:40.000000000 +0000
+++ Makefile.in	2010-07-16 13:08:46.000000000 +0000
@@ -49,6 +49,9 @@
 # Util library.
 LIBUTIL = @LIBUTIL@
 
+# Hurd's libstore
+LIBSTORE = @LIBSTORE@
+
 XGETTEXT = @XGETTEXT@
 MSGMERGE = @MSGMERGE@
 MSGFMT = @MSGFMT@
@@ -84,7 +87,7 @@
 
 mkinstalldirs = $(srcdir)/mkinstalldirs
 
-LIBS = @LIBS@ $(LIBINTL) $(LIBUTIL)
+LIBS = @LIBS@ $(LIBINTL) $(LIBUTIL) $(LIBSTORE)
 
 CC = @CC@
 CFLAGS = @CFLAGS@
Index: configure.ac
===================================================================
--- configure.ac.orig	2010-07-16 13:08:11.000000000 +0000
+++ configure.ac	2010-07-16 13:09:45.000000000 +0000
@@ -31,7 +31,7 @@
 dnl type.
 
 
-AC_INIT([GRUB],[0],[bug-g...@gnu.org]) dnl version is filled by debian/rules
+AC_INIT([GRUB],[1.98+20100710-1+jk1],[bug-g...@gnu.org])
 AM_INIT_AUTOMAKE()
 AC_PREREQ(2.60)
 AC_CONFIG_SRCDIR([include/grub/dl.h])
@@ -270,6 +270,18 @@
 ])
 AC_SUBST([LIBUTIL])
 
+# On Hurd we need libstore for kern/emu/getroot.c
+case "$host_kernel" in 
+  hurd)
+    AC_CHECK_HEADER([hurd/store.h], [], [AC_MSG_ERROR([hurd/store.h is needed])])
+    AC_CHECK_LIB([store], [store_create], [], [AC_MSG_ERROR([libstore is needed])])
+    LIBSTORE="-lstore"
+    ;;
+  *)
+    ;;
+esac
+AC_SUBST([LIBSTORE])
+
 #
 # Check for target programs.
 #
Index: kern/emu/getroot.c
===================================================================
--- kern/emu/getroot.c.orig	2010-07-05 00:50:20.000000000 +0000
+++ kern/emu/getroot.c	2010-07-16 14:10:28.000000000 +0000
@@ -170,6 +170,161 @@
   return 0;
 }
 
+#elif defined(__GNU__)
+
+#include <mach.h>
+#include <hurd/hurd_types.h>
+#include <hurd/store.h>
+#include <grub/disk.h>
+#include <grub/partition.h>
+
+/* from hostdisk.c */
+extern struct
+{
+	char *drive;
+	char *device;
+} map[256];
+
+
+/* Open a store for storage information only. */
+static struct store *
+storeinfo_store (const char *path)
+{
+  file_t file;
+  struct store *store;
+  int err;
+
+  file = file_name_lookup (path, 0, 0);
+  if (file == MACH_PORT_NULL)
+    return NULL;
+
+  err = store_create (file, STORE_INACTIVE | STORE_NO_FILEIO, NULL, &store);
+  return err ? NULL : store;
+}
+
+/* Determine whether two stores share the same underlying storage. */
+static int
+same_storage (struct store *s1, struct store *s2)
+{
+  if (s1->class->id != s2->class->id)
+    return 0;
+
+  switch (s1->class->id)
+    {
+      case STORAGE_DEVICE:
+      case STORAGE_HURD_FILE:
+      case STORAGE_TASK:
+      case STORAGE_MEMORY:
+	if (s1->port != MACH_PORT_NULL && s1->port == s2->port)
+	  return 1;
+	else if (s1->name && s2->name && strcmp (s1->name, s2->name) == 0)
+	  return 1;
+	else
+	  return 0;
+
+      default:
+	return 0;
+    }
+}
+
+/* Retreive the storage information for PATH, and search the device map until
+ * we find the matching disk, and maybe partition. */
+static char *
+find_hurd_root_device (const char *path)
+{
+  int winner_disk = -1, winner_part = -1;
+  struct store *path_store;
+  char *devpath = NULL;
+
+  auto int check_part (grub_disk_t, const grub_partition_t);
+  int check_part (grub_disk_t disk __attribute__((unused)),
+		  const grub_partition_t partition)
+    {
+      store_offset_t start = partition->start * GRUB_DISK_SECTOR_SIZE,
+		     length = partition->len * GRUB_DISK_SECTOR_SIZE,
+		     fstart = path_store->runs->start * path_store->block_size;
+
+      grub_util_info ("Trying partition #%d (%ld+%ld)", partition->number,
+		      (long) start, (long) length);
+
+      if (fstart >= start && fstart < start + length)
+	winner_part = partition->number;
+      else
+	grub_util_info ("The target is outside (%ld)", (long) fstart);
+
+      return winner_part >= 0;
+    }
+
+  auto int check_disk (const char *);
+  int check_disk (const char *name)
+    {
+      grub_disk_t disk;
+      struct store *disk_store;
+
+      grub_util_info ("Trying disk `%s'", name);
+
+      disk = grub_disk_open (name);
+      if (! disk)
+	goto out;
+
+      if (disk->dev->id != GRUB_DISK_DEVICE_BIOSDISK_ID)
+	{
+	  grub_util_info ("`%s' is not a biosdisk", name);
+	  goto out_disk;
+	}
+
+      disk_store = storeinfo_store (map[disk->id].device);
+      if (! disk_store)
+	{
+	  grub_util_info ("Could not retreive storage info for `%s'", map[disk->id].device);
+	  goto out_disk;
+	}
+
+      if (! same_storage (disk_store, path_store))
+	{
+	  grub_util_info ("`%s' does not use the same storage as `%s'", name, path);
+	  goto out_store;
+	}
+
+      winner_disk = disk->id;
+      grub_partition_iterate (disk, check_part);
+
+    out_store:
+      store_free (disk_store);
+    out_disk:
+      grub_disk_close (disk);
+    out:
+      return winner_disk >= 0;
+    }
+
+  path_store = storeinfo_store (path);
+  if (! path_store)
+    grub_util_error ("Could not retreive storage information for `%s'", path);
+
+  if (path_store->num_runs >= 1)
+    grub_disk_dev_iterate (check_disk);
+
+  if (winner_disk >= 0)
+    {
+      const char *diskpath = map[winner_disk].device;
+      devpath = xmalloc (strlen (diskpath) + 3 * sizeof (int) + 2);
+
+      strcpy (devpath, diskpath);
+      if (winner_part >= 0)
+	sprintf (devpath + strlen (devpath), "s%d", winner_part + 1);
+    }
+  else if (path_store->class->id == STORAGE_DEVICE && path_store->name)
+    {
+      /* use whatever device PATH_STORE is based on */
+      devpath = xmalloc (strlen (path_store->name) + sizeof "/dev/");
+      sprintf (devpath, "/dev/%s", path_store->name);
+    }
+
+  store_free (path_store);
+
+  return devpath;
+}
+
 #elif ! defined(__CYGWIN__)
 
 static char *
@@ -387,64 +542,10 @@
 char *
 grub_guess_root_device (const char *dir)
 {
-  char *os_dev;
 #ifdef __GNU__
-  file_t file;
-  mach_port_t *ports;
-  int *ints;
-  loff_t *offsets;
-  char *data;
-  error_t err;
-  mach_msg_type_number_t num_ports = 0, num_ints = 0, num_offsets = 0, data_len = 0;
-  size_t name_len;
-
-  file = file_name_lookup (dir, 0, 0);
-  if (file == MACH_PORT_NULL)
-    return 0;
-
-  err = file_get_storage_info (file,
-			       &ports, &num_ports,
-			       &ints, &num_ints,
-			       &offsets, &num_offsets,
-			       &data, &data_len);
-
-  if (num_ints < 1)
-    grub_util_error ("Storage info for `%s' does not include type", dir);
-  if (ints[0] != STORAGE_DEVICE)
-    grub_util_error ("Filesystem of `%s' is not stored on local disk", dir);
-
-  if (num_ints < 5)
-    grub_util_error ("Storage info for `%s' does not include name", dir);
-  name_len = ints[4];
-  if (name_len < data_len)
-    grub_util_error ("Bogus name length for storage info for `%s'", dir);
-  if (data[name_len - 1] != '\0')
-    grub_util_error ("Storage name for `%s' not NUL-terminated", dir);
-
-  os_dev = xmalloc (strlen ("/dev/") + data_len);
-  memcpy (os_dev, "/dev/", strlen ("/dev/"));
-  memcpy (os_dev + strlen ("/dev/"), data, data_len);
-
-  if (ports && num_ports > 0)
-    {
-      mach_msg_type_number_t i;
-      for (i = 0; i < num_ports; i++)
-        {
-	  mach_port_t port = ports[i];
-	  if (port != MACH_PORT_NULL)
-	    mach_port_deallocate (mach_task_self(), port);
-        }
-      munmap ((caddr_t) ports, num_ports * sizeof (*ports));
-    }
-
-  if (ints && num_ints > 0)
-    munmap ((caddr_t) ints, num_ints * sizeof (*ints));
-  if (offsets && num_offsets > 0)
-    munmap ((caddr_t) offsets, num_offsets * sizeof (*offsets));
-  if (data && data_len > 0)
-    munmap (data, data_len);
-  mach_port_deallocate (mach_task_self (), file);
+  return find_hurd_root_device (dir);
 #else /* !__GNU__ */
+  char *os_dev;
   struct stat st;
 
 #ifdef __linux__
@@ -465,9 +566,9 @@
   /* This might be truly slow, but is there any better way?  */
   os_dev = find_root_device ("/dev", st.st_dev);
 #endif
-#endif /* !__GNU__ */
 
   return os_dev;
+#endif /* !__GNU__ */
 }
 
 static int
Index: home/jk/gsoc/build/grub2-1.98+20100710/kern/emu/getroot.c
===================================================================
--- home/jk/gsoc/build/grub2-1.98+20100710/kern/emu/getroot.c	2010-07-16 14:05:48.000000000 +0000
+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
@@ -1,740 +0,0 @@
-/* getroot.c - Get root device */
-/*
- *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 1999,2000,2001,2002,2003,2006,2007,2008,2009  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 <sys/stat.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
-#include <dirent.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-
-#ifdef __GNU__
-#include <hurd.h>
-#include <hurd/lookup.h>
-#include <hurd/fs.h>
-#include <sys/mman.h>
-#endif
-
-#include <grub/mm.h>
-#include <grub/misc.h>
-#include <grub/emu/misc.h>
-#include <grub/emu/hostdisk.h>
-#include <grub/emu/getroot.h>
-
-static void
-strip_extra_slashes (char *dir)
-{
-  char *p = dir;
-
-  while ((p = strchr (p, '/')) != 0)
-    {
-      if (p[1] == '/')
-	{
-	  memmove (p, p + 1, strlen (p));
-	  continue;
-	}
-      else if (p[1] == '\0')
-	{
-	  if (p > dir)
-	    p[0] = '\0';
-	  break;
-	}
-
-      p++;
-    }
-}
-
-static char *
-xgetcwd (void)
-{
-  size_t size = 10;
-  char *path;
-
-  path = xmalloc (size);
-  while (! getcwd (path, size))
-    {
-      size <<= 1;
-      path = xrealloc (path, size);
-    }
-
-  return path;
-}
-
-#ifdef __linux__
-
-/* Statting something on a btrfs filesystem always returns a virtual device
-   major/minor pair rather than the real underlying device, because btrfs
-   can span multiple underlying devices (and even if it's currently only
-   using a single device it can be dynamically extended onto another).  We
-   can't deal with the multiple-device case yet, but in the meantime, we can
-   at least cope with the single-device case by scanning
-   /proc/self/mountinfo.  */
-static char *
-find_root_device_from_mountinfo (const char *dir)
-{
-  FILE *fp;
-  char *buf = NULL;
-  size_t len = 0;
-  char *ret = NULL;
-
-  fp = fopen ("/proc/self/mountinfo", "r");
-  if (! fp)
-    return NULL; /* fall through to other methods */
-
-  while (getline (&buf, &len, fp) > 0)
-    {
-      int mnt_id, parent_mnt_id;
-      unsigned int major, minor;
-      char enc_root[PATH_MAX], enc_path[PATH_MAX];
-      int count;
-      size_t enc_path_len;
-      const char *sep;
-      char fstype[PATH_MAX], device[PATH_MAX];
-      struct stat st;
-
-      if (sscanf (buf, "%d %d %u:%u %s %s%n",
-		  &mnt_id, &parent_mnt_id, &major, &minor, enc_root, enc_path,
-		  &count) < 6)
-	continue;
-
-      if (strcmp (enc_root, "/") != 0)
-	continue; /* only a subtree is mounted */
-
-      enc_path_len = strlen (enc_path);
-      if (strncmp (dir, enc_path, enc_path_len) != 0 ||
-	  (dir[enc_path_len] && dir[enc_path_len] != '/'))
-	continue;
-
-      /* This is a parent of the requested directory.  /proc/self/mountinfo
-	 is in mount order, so it must be the closest parent we've
-	 encountered so far.  If it's virtual, return its device node;
-	 otherwise, carry on to try to find something closer.  */
-
-      free (ret);
-      ret = NULL;
-
-      if (major != 0)
-	continue; /* not a virtual device */
-
-      sep = strstr (buf + count, " - ");
-      if (!sep)
-	continue;
-
-      sep += sizeof (" - ") - 1;
-      if (sscanf (sep, "%s %s", fstype, device) != 2)
-	continue;
-
-      if (stat (device, &st) < 0)
-	continue;
-
-      if (!S_ISBLK (st.st_mode))
-	continue; /* not a block device */
-
-      ret = strdup (device);
-    }
-
-  free (buf);
-  fclose (fp);
-  return ret;
-}
-
-#endif /* __linux__ */
-
-#ifdef __MINGW32__
-
-static char *
-find_root_device (const char *dir __attribute__ ((unused)),
-                  dev_t dev __attribute__ ((unused)))
-{
-  return 0;
-}
-
-#elif defined(__GNU__)
-
-#include <mach.h>
-#include <hurd/hurd_types.h>
-#include <hurd/store.h>
-#include <grub/disk.h>
-#include <grub/partition.h>
-
-/* from hostdisk.c */
-extern struct
-{
-	char *drive;
-	char *device;
-} map[256];
-
-
-/* Open a store for storage information only. */
-static struct store *
-storeinfo_store (const char *path)
-{
-  file_t file;
-  struct store *store;
-  int err;
-
-  file = file_name_lookup (path, 0, 0);
-  if (file == MACH_PORT_NULL)
-    return NULL;
-
-  err = store_create (file, STORE_INACTIVE | STORE_NO_FILEIO, NULL, &store);
-  return err ? NULL : store;
-}
-
-/* Determine whether two stores share the same underlying storage. */
-static int
-same_storage (struct store *s1, struct store *s2)
-{
-  if (s1->class->id != s2->class->id)
-    return 0;
-
-  switch (s1->class->id)
-    {
-      case STORAGE_DEVICE:
-      case STORAGE_HURD_FILE:
-      case STORAGE_TASK:
-      case STORAGE_MEMORY:
-	if (s1->port != MACH_PORT_NULL && s1->port == s2->port)
-	  return 1;
-	else if (s1->name && s2->name && strcmp (s1->name, s2->name) == 0)
-	  return 1;
-	else
-	  return 0;
-
-      default:
-	return 0;
-    }
-}
-
-/* Retreive the storage information for PATH, and search the device map until
- * we find the matching disk, and maybe partition. */
-static char *
-find_hurd_root_device (const char *path)
-{
-  int winner_disk = -1, winner_part = -1;
-  struct store *path_store;
-  char *devpath = NULL;
-
-  int check_part (grub_disk_t disk __attribute__((unused)),
-		  const grub_partition_t partition)
-    {
-      store_offset_t start = partition->start * GRUB_DISK_SECTOR_SIZE,
-		     length = partition->len * GRUB_DISK_SECTOR_SIZE,
-		     fstart = path_store->runs->start * path_store->block_size;
-
-      grub_util_info ("Trying partition #%d (%ld+%ld)", partition->number,
-		      (long) start, (long) length);
-
-      if (fstart >= start && fstart < start + length)
-	winner_part = partition->number;
-      else
-	grub_util_info ("The target is outside (%ld)", (long) fstart);
-
-      return winner_part >= 0;
-    }
-
-  int check_disk (const char *name)
-    {
-      grub_disk_t disk;
-      struct store *disk_store;
-
-      grub_util_info ("Trying disk `%s'", name);
-
-      disk = grub_disk_open (name);
-      if (! disk)
-	goto out;
-
-      if (disk->dev->id != GRUB_DISK_DEVICE_BIOSDISK_ID)
-	{
-	  grub_util_info ("`%s' is not a biosdisk", name);
-	  goto out_disk;
-	}
-
-      disk_store = storeinfo_store (map[disk->id].device);
-      if (! disk_store)
-	{
-	  grub_util_info ("Could not retreive storage info for `%s'", map[disk->id].device);
-	  goto out_disk;
-	}
-
-      if (! same_storage (disk_store, path_store))
-	{
-	  grub_util_info ("`%s' does not use the same storage as `%s'", name, path);
-	  goto out_store;
-	}
-
-      winner_disk = disk->id;
-      grub_partition_iterate (disk, check_part);
-
-    out_store:
-      store_free (disk_store);
-    out_disk:
-      grub_disk_close (disk);
-    out:
-      return winner_disk >= 0;
-    }
-
-  path_store = storeinfo_store (path);
-  if (! path_store)
-    grub_util_error ("Could not retreive storage information for `%s'", path);
-
-  if (path_store->num_runs >= 1)
-    grub_disk_dev_iterate (check_disk);
-
-  if (winner_disk >= 0)
-    {
-      const char *diskpath = map[winner_disk].device;
-      devpath = xmalloc (strlen (diskpath) + 3 * sizeof (int) + 2);
-
-      strcpy (devpath, diskpath);
-      if (winner_part >= 0)
-	sprintf (devpath + strlen (devpath), "s%d", winner_part + 1);
-    }
-  else if (path_store->class->id == STORAGE_DEVICE && path_store->name)
-    {
-      /* use whatever device PATH_STORE is based on */
-      devpath = xmalloc (strlen (path_store->name) + sizeof "/dev/");
-      sprintf (devpath, "/dev/%s", path_store->name);
-    }
-
-  store_free (path_store);
-
-  return devpath;
-}
-
-#elif ! defined(__CYGWIN__)
-
-static char *
-find_root_device (const char *dir, dev_t dev)
-{
-  DIR *dp;
-  char *saved_cwd;
-  struct dirent *ent;
-
-  dp = opendir (dir);
-  if (! dp)
-    return 0;
-
-  saved_cwd = xgetcwd ();
-
-  grub_util_info ("changing current directory to %s", dir);
-  if (chdir (dir) < 0)
-    {
-      free (saved_cwd);
-      closedir (dp);
-      return 0;
-    }
-
-  while ((ent = readdir (dp)) != 0)
-    {
-      struct stat st;
-
-      /* Avoid:
-	 - dotfiles (like "/dev/.tmp.md0") since they could be duplicates.
-	 - dotdirs (like "/dev/.static") since they could contain duplicates.  */
-      if (ent->d_name[0] == '.')
-	continue;
-
-      if (lstat (ent->d_name, &st) < 0)
-	/* Ignore any error.  */
-	continue;
-
-      if (S_ISLNK (st.st_mode)) {
-#ifdef __linux__
-	if (strcmp (dir, "mapper") == 0) {
-	  /* Follow symbolic links under /dev/mapper/; the canonical name
-	     may be something like /dev/dm-0, but the names under
-	     /dev/mapper/ are more human-readable and so we prefer them if
-	     we can get them.  */
-	  if (stat (ent->d_name, &st) < 0)
-	    continue;
-	} else
-#endif /* __linux__ */
-	/* Don't follow other symbolic links.  */
-	continue;
-      }
-
-      if (S_ISDIR (st.st_mode))
-	{
-	  /* Find it recursively.  */
-	  char *res;
-
-	  res = find_root_device (ent->d_name, dev);
-
-	  if (res)
-	    {
-	      if (chdir (saved_cwd) < 0)
-		grub_util_error ("cannot restore the original directory");
-
-	      free (saved_cwd);
-	      closedir (dp);
-	      return res;
-	    }
-	}
-
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__)
-      if (S_ISCHR (st.st_mode) && st.st_rdev == dev)
-#else
-      if (S_ISBLK (st.st_mode) && st.st_rdev == dev)
-#endif
-	{
-#ifdef __linux__
-	  /* Skip device names like /dev/dm-0, which are short-hand aliases
-	     to more descriptive device names, e.g. those under /dev/mapper */
-	  if (ent->d_name[0] == 'd' &&
-	      ent->d_name[1] == 'm' &&
-	      ent->d_name[2] == '-' &&
-	      ent->d_name[3] >= '0' &&
-	      ent->d_name[3] <= '9')
-	    continue;
-#endif
-
-	  /* Found!  */
-	  char *res;
-	  char *cwd;
-#if defined(__NetBSD__)
-	  /* Convert this block device to its character (raw) device.  */
-	  const char *template = "%s/r%s";
-#else
-	  /* Keep the device name as it is.  */
-	  const char *template = "%s/%s";
-#endif
-
-	  cwd = xgetcwd ();
-	  res = xmalloc (strlen (cwd) + strlen (ent->d_name) + 3);
-	  sprintf (res, template, cwd, ent->d_name);
-	  strip_extra_slashes (res);
-	  free (cwd);
-
-	  /* /dev/root is not a real block device keep looking, takes care
-	     of situation where root filesystem is on the same partition as
-	     grub files */
-
-	  if (strcmp(res, "/dev/root") == 0)
-		continue;
-
-	  if (chdir (saved_cwd) < 0)
-	    grub_util_error ("cannot restore the original directory");
-
-	  free (saved_cwd);
-	  closedir (dp);
-	  return res;
-	}
-    }
-
-  if (chdir (saved_cwd) < 0)
-    grub_util_error ("cannot restore the original directory");
-
-  free (saved_cwd);
-  closedir (dp);
-  return 0;
-}
-
-#else /* __CYGWIN__ */
-
-/* Read drive/partition serial number from mbr/boot sector,
-   return 0 on read error, ~0 on unknown serial.  */
-static unsigned
-get_bootsec_serial (const char *os_dev, int mbr)
-{
-  /* Read boot sector.  */
-  int fd = open (os_dev, O_RDONLY);
-  if (fd < 0)
-    return 0;
-  unsigned char buf[0x200];
-  int n = read (fd, buf, sizeof (buf));
-  close (fd);
-  if (n != sizeof(buf))
-    return 0;
-
-  /* Check signature.  */
-  if (!(buf[0x1fe] == 0x55 && buf[0x1ff] == 0xaa))
-    return ~0;
-
-  /* Serial number offset depends on boot sector type.  */
-  if (mbr)
-    n = 0x1b8;
-  else if (memcmp (buf + 0x03, "NTFS", 4) == 0)
-    n = 0x048;
-  else if (memcmp (buf + 0x52, "FAT32", 5) == 0)
-    n = 0x043;
-  else if (memcmp (buf + 0x36, "FAT", 3) == 0)
-    n = 0x027;
-  else
-    return ~0;
-
-  unsigned serial = *(unsigned *)(buf + n);
-  if (serial == 0)
-    return ~0;
-  return serial;
-}
-
-static char *
-find_cygwin_root_device (const char *path, dev_t dev)
-{
-  /* No root device for /cygdrive.  */
-  if (dev == (DEV_CYGDRIVE_MAJOR << 16))
-    return 0;
-
-  /* Convert to full POSIX and Win32 path.  */
-  char fullpath[PATH_MAX], winpath[PATH_MAX];
-  cygwin_conv_to_full_posix_path (path, fullpath);
-  cygwin_conv_to_full_win32_path (fullpath, winpath);
-
-  /* If identical, this is no real filesystem path.  */
-  if (strcmp (fullpath, winpath) == 0)
-    return 0;
-
-  /* Check for floppy drive letter.  */
-  if (winpath[0] && winpath[1] == ':' && strchr ("AaBb", winpath[0]))
-    return xstrdup (strchr ("Aa", winpath[0]) ? "/dev/fd0" : "/dev/fd1");
-
-  /* Cygwin returns the partition serial number in stat.st_dev.
-     This is never identical to the device number of the emulated
-     /dev/sdXN device, so above find_root_device () does not work.
-     Search the partition with the same serial in boot sector instead.  */
-  char devpath[sizeof ("/dev/sda15") + 13]; /* Size + Paranoia.  */
-  int d;
-  for (d = 'a'; d <= 'z'; d++)
-    {
-      sprintf (devpath, "/dev/sd%c", d);
-      if (get_bootsec_serial (devpath, 1) == 0)
-	continue;
-      int p;
-      for (p = 1; p <= 15; p++)
-	{
-	  sprintf (devpath, "/dev/sd%c%d", d, p);
-	  unsigned ser = get_bootsec_serial (devpath, 0);
-	  if (ser == 0)
-	    break;
-	  if (ser != (unsigned)~0 && dev == (dev_t)ser)
-	    return xstrdup (devpath);
-	}
-    }
-  return 0;
-}
-
-#endif /* __CYGWIN__ */
-
-char *
-grub_guess_root_device (const char *dir)
-{
-#ifdef __GNU__
-  return find_hurd_root_device (dir);
-#else /* !__GNU__ */
-  char *os_dev;
-  struct stat st;
-
-#ifdef __linux__
-  os_dev = find_root_device_from_mountinfo (dir);
-  if (os_dev)
-    return os_dev;
-#endif /* __linux__ */
-
-  if (stat (dir, &st) < 0)
-    grub_util_error ("cannot stat `%s'", dir);
-
-#ifdef __CYGWIN__
-  /* Cygwin specific function.  */
-  os_dev = find_cygwin_root_device (dir, st.st_dev);
-
-#else
-
-  /* This might be truly slow, but is there any better way?  */
-  os_dev = find_root_device ("/dev", st.st_dev);
-#endif
-
-  return os_dev;
-#endif /* !__GNU__ */
-}
-
-static int
-grub_util_is_dmraid (const char *os_dev)
-{
-  if (! strncmp (os_dev, "/dev/mapper/nvidia_", 19))
-    return 1;
-  else if (! strncmp (os_dev, "/dev/mapper/isw_", 16))
-    return 1;
-  else if (! strncmp (os_dev, "/dev/mapper/hpt37x_", 19))
-    return 1;
-  else if (! strncmp (os_dev, "/dev/mapper/hpt45x_", 19))
-    return 1;
-  else if (! strncmp (os_dev, "/dev/mapper/via_", 16))
-    return 1;
-  else if (! strncmp (os_dev, "/dev/mapper/lsi_", 16))
-    return 1;
-  else if (! strncmp (os_dev, "/dev/mapper/pdc_", 16))
-    return 1;
-  else if (! strncmp (os_dev, "/dev/mapper/jmicron_", 20))
-    return 1;
-  else if (! strncmp (os_dev, "/dev/mapper/asr_", 16))
-    return 1;
-  else if (! strncmp (os_dev, "/dev/mapper/sil_", 16))
-    return 1;
-
-  return 0;
-}
-
-int
-grub_util_get_dev_abstraction (const char *os_dev __attribute__((unused)))
-{
-#ifdef __linux__
-  /* Check for LVM.  */
-  if (!strncmp (os_dev, "/dev/mapper/", 12)
-      && ! grub_util_is_dmraid (os_dev)
-      && strncmp (os_dev, "/dev/mapper/mpath", 17) != 0)
-    return GRUB_DEV_ABSTRACTION_LVM;
-
-  /* Check for RAID.  */
-  if (!strncmp (os_dev, "/dev/md", 7))
-    return GRUB_DEV_ABSTRACTION_RAID;
-#endif
-
-  /* No abstraction found.  */
-  return GRUB_DEV_ABSTRACTION_NONE;
-}
-
-char *
-grub_util_get_grub_dev (const char *os_dev)
-{
-  char *grub_dev;
-
-  switch (grub_util_get_dev_abstraction (os_dev))
-    {
-    case GRUB_DEV_ABSTRACTION_LVM:
-
-      {
-	unsigned short i, len;
-	grub_size_t offset = sizeof ("/dev/mapper/") - 1;
-
-	len = strlen (os_dev) - offset + 1;
-	grub_dev = xmalloc (len);
-
-	for (i = 0; i < len; i++, offset++)
-	  {
-	    grub_dev[i] = os_dev[offset];
-	    if (os_dev[offset] == '-' && os_dev[offset + 1] == '-')
-	      offset++;
-	  }
-      }
-
-      break;
-
-    case GRUB_DEV_ABSTRACTION_RAID:
-
-      if (os_dev[7] == '_' && os_dev[8] == 'd')
-	{
-	  /* This a partitionable RAID device of the form /dev/md_dNNpMM. */
-
-	  char *p, *q;
-
-	  p = strdup (os_dev + sizeof ("/dev/md_d") - 1);
-
-	  q = strchr (p, 'p');
-	  if (q)
-	    *q = ',';
-
-	  grub_dev = xasprintf ("md%s", p);
-	  free (p);
-	}
-      else if (os_dev[7] == '/' && os_dev[8] == 'd')
-	{
-	  /* This a partitionable RAID device of the form /dev/md/dNNpMM. */
-
-	  char *p, *q;
-
-	  p = strdup (os_dev + sizeof ("/dev/md/d") - 1);
-
-	  q = strchr (p, 'p');
-	  if (q)
-	    *q = ',';
-
-	  grub_dev = xasprintf ("md%s", p);
-	  free (p);
-	}
-      else if (os_dev[7] >= '0' && os_dev[7] <= '9')
-	{
-	  char *p , *q;
-
-	  p = strdup (os_dev + sizeof ("/dev/md") - 1);
-
-	  q = strchr (p, 'p');
-	  if (q)
-	    *q = ',';
-
-	  grub_dev = xasprintf ("md%s", p);
-	  free (p);
-	}
-      else if (os_dev[7] == '/' && os_dev[8] >= '0' && os_dev[8] <= '9')
-	{
-	  char *p , *q;
-
-	  p = strdup (os_dev + sizeof ("/dev/md/") - 1);
-
-	  q = strchr (p, 'p');
-	  if (q)
-	    *q = ',';
-
-	  grub_dev = xasprintf ("md%s", p);
-	  free (p);
-	}
-      else
-	grub_util_error ("unknown kind of RAID device `%s'", os_dev);
-
-      break;
-
-    default:  /* GRUB_DEV_ABSTRACTION_NONE */
-      grub_dev = grub_util_biosdisk_get_grub_dev (os_dev);
-    }
-
-  return grub_dev;
-}
-
-const char *
-grub_util_check_block_device (const char *blk_dev)
-{
-  struct stat st;
-
-  if (stat (blk_dev, &st) < 0)
-    grub_util_error ("cannot stat `%s'", blk_dev);
-
-  if (S_ISBLK (st.st_mode))
-    return (blk_dev);
-  else
-    return 0;
-}
-
-const char *
-grub_util_check_char_device (const char *blk_dev)
-{
-  struct stat st;
-
-  if (stat (blk_dev, &st) < 0)
-    grub_util_error ("cannot stat `%s'", blk_dev);
-
-  if (S_ISCHR (st.st_mode))
-    return (blk_dev);
-  else
-    return 0;
-}

Reply via email to