=== 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-grub@gnu.org]) dnl version is filled by debian/rules +AC_INIT([GRUB],[1.98+20100710-1+jk1],[bug-grub@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 +#include +#include +#include +#include + +/* 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 . - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __GNU__ -#include -#include -#include -#include -#endif - -#include -#include -#include -#include -#include - -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 -#include -#include -#include -#include - -/* 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; -}