=== modified file 'Makefile.util.def' --- Makefile.util.def 2012-04-01 19:35:18 +0000 +++ Makefile.util.def 2012-04-22 18:26:01 +0000 @@ -170,7 +170,7 @@ ldadd = libgrubgcry.a; ldadd = libgrubkern.a; ldadd = grub-core/gnulib/libgnu.a; - ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM) $(LIBSTORE)'; }; program = { @@ -300,7 +300,7 @@ ldadd = libgrubgcry.a; ldadd = libgrubkern.a; ldadd = grub-core/gnulib/libgnu.a; - ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM) $(LIBSTORE)'; }; program = { @@ -316,7 +316,7 @@ ldadd = libgrubkern.a; ldadd = libgrubgcry.a; ldadd = grub-core/gnulib/libgnu.a; - ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM) $(LIBSTORE)'; cppflags = '-DGRUB_SETUP_BIOS=1'; }; @@ -334,7 +334,7 @@ ldadd = libgrubkern.a; ldadd = libgrubgcry.a; ldadd = grub-core/gnulib/libgnu.a; - ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM) $(LIBSTORE)'; cppflags = '-DGRUB_SETUP_SPARC64=1'; }; === modified file 'configure.ac' --- configure.ac 2012-04-19 09:34:43 +0000 +++ configure.ac 2012-04-22 17:50:59 +0000 @@ -341,6 +341,18 @@ ]) AC_SUBST([LIBUTIL]) +# On Hurd we need libstore for util/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 host and build compilers. # === modified file 'grub-core/kern/emu/hostdisk.c' --- grub-core/kern/emu/hostdisk.c 2012-04-22 16:44:19 +0000 +++ grub-core/kern/emu/hostdisk.c 2012-04-22 18:46:07 +0000 @@ -115,12 +115,7 @@ # endif /* ! RAW_FLOPPY_MAJOR */ #endif /* defined(__NetBSD__) */ -struct -{ - char *drive; - char *device; - int device_map; -} map[256]; +struct hostdisk_map hostdisk_map[256]; struct grub_util_biosdisk_data { @@ -202,8 +197,8 @@ if (name) { - for (i = 0; i < ARRAY_SIZE (map); i++) - if (map[i].drive && unescape_cmp (map[i].drive, name) == 0) + for (i = 0; i < ARRAY_SIZE (hostdisk_map); i++) + if (hostdisk_map[i].drive && unescape_cmp (hostdisk_map[i].drive, name) == 0) return i; } @@ -215,8 +210,8 @@ { unsigned int i; - for (i = 0; i < sizeof (map) / sizeof (map[0]); i++) - if (! map[i].drive) + for (i = 0; i < sizeof (hostdisk_map) / sizeof (hostdisk_map[0]); i++) + if (! hostdisk_map[i].drive) return i; return -1; @@ -231,8 +226,8 @@ if (pull != GRUB_DISK_PULL_NONE) return 0; - for (i = 0; i < sizeof (map) / sizeof (map[0]); i++) - if (map[i].drive && hook (map[i].drive)) + for (i = 0; i < sizeof (hostdisk_map) / sizeof (hostdisk_map[0]); i++) + if (hostdisk_map[i].drive && hook (hostdisk_map[i].drive)) return 1; return 0; @@ -354,14 +349,14 @@ data->access_mode = 0; data->fd = -1; data->is_disk = 0; - data->device_map = map[drive].device_map; + data->device_map = hostdisk_map[drive].device_map; /* Get the size. */ #if defined(__MINGW32__) { grub_uint64_t size; - size = grub_util_get_disk_size (map[drive].device); + size = grub_util_get_disk_size (hostdisk_map[drive].device); if (size % 512) grub_util_error (_("unaligned device size")); @@ -376,12 +371,12 @@ { int fd; - fd = open (map[drive].device, O_RDONLY); + fd = open (hostdisk_map[drive].device, O_RDONLY); if (fd == -1) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("cannot open `%s': %s"), - map[drive].device, strerror (errno)); + hostdisk_map[drive].device, strerror (errno)); - disk->total_sectors = grub_util_get_fd_size (fd, map[drive].device, + disk->total_sectors = grub_util_get_fd_size (fd, hostdisk_map[drive].device, &disk->log_sector_size); disk->total_sectors >>= disk->log_sector_size; @@ -769,26 +764,26 @@ { unsigned int i; - for (i = 0; i < ARRAY_SIZE (map); i++) - if (! map[i].device) + for (i = 0; i < ARRAY_SIZE (hostdisk_map); i++) + if (! hostdisk_map[i].device) break; - else if (strcmp (map[i].device, os_disk) == 0) - return map[i].drive; + else if (strcmp (hostdisk_map[i].device, os_disk) == 0) + return hostdisk_map[i].drive; if (!add) return NULL; - if (i == ARRAY_SIZE (map)) + if (i == ARRAY_SIZE (hostdisk_map)) /* TRANSLATORS: it refers to the lack of free slots. */ grub_util_error ("%s", _("device count exceeds limit")); - map[i].device = xstrdup (os_disk); - map[i].drive = xmalloc (sizeof ("hostdisk/") + strlen (os_disk)); - strcpy (map[i].drive, "hostdisk/"); - strcpy (map[i].drive + sizeof ("hostdisk/") - 1, os_disk); - map[i].device_map = 0; + hostdisk_map[i].device = xstrdup (os_disk); + hostdisk_map[i].drive = xmalloc (sizeof ("hostdisk/") + strlen (os_disk)); + strcpy (hostdisk_map[i].drive, "hostdisk/"); + strcpy (hostdisk_map[i].drive + sizeof ("hostdisk/") - 1, os_disk); + hostdisk_map[i].device_map = 0; - return map[i].drive; + return hostdisk_map[i].drive; } static int @@ -823,9 +818,9 @@ part_start = grub_partition_get_start (disk->partition); - strcpy (dev, map[disk->id].device); + strcpy (dev, hostdisk_map[disk->id].device); if (disk->partition - && strncmp (map[disk->id].device, "/dev/", 5) == 0) + && strncmp (hostdisk_map[disk->id].device, "/dev/", 5) == 0) { if (sector >= part_start) is_partition = linux_find_partition (dev, part_start); @@ -884,7 +879,7 @@ if (*max == 0) *max = ~0ULL; is_partition = 0; - strcpy (dev, map[disk->id].device); + strcpy (dev, hostdisk_map[disk->id].device); goto reopen; } sector -= part_start; @@ -910,7 +905,7 @@ } #endif - if (data->dev && strcmp (data->dev, map[disk->id].device) == 0 && + if (data->dev && strcmp (data->dev, hostdisk_map[disk->id].device) == 0 && data->access_mode == (flags & O_ACCMODE)) { grub_dprintf ("hostdisk", "reusing open device `%s'\n", data->dev); @@ -933,10 +928,10 @@ data->fd = -1; } - fd = open (map[disk->id].device, flags); + fd = open (hostdisk_map[disk->id].device, flags); if (fd >= 0) { - data->dev = xstrdup (map[disk->id].device); + data->dev = xstrdup (hostdisk_map[disk->id].device); data->access_mode = (flags & O_ACCMODE); data->fd = fd; } @@ -954,13 +949,13 @@ #if defined(__APPLE__) /* If we can't have exclusive access, try shared access */ if (fd < 0) - fd = open(map[disk->id].device, flags | O_SHLOCK); + fd = open(hostdisk_map[disk->id].device, flags | O_SHLOCK); #endif if (fd < 0) { grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot open `%s': %s"), - map[disk->id].device, strerror (errno)); + hostdisk_map[disk->id].device, strerror (errno)); return -1; } #endif /* ! __linux__ */ @@ -969,7 +964,7 @@ configure_device_driver (fd); #endif /* defined(__NetBSD__) */ - if (grub_util_fd_seek (fd, map[disk->id].device, + if (grub_util_fd_seek (fd, hostdisk_map[disk->id].device, sector << disk->log_sector_size)) { close (fd); @@ -1056,7 +1051,7 @@ if (grub_util_fd_read (fd, buf, (1 << disk->log_sector_size)) != (1 << disk->log_sector_size)) return grub_error (GRUB_ERR_READ_ERROR, N_("cannot read `%s': %s"), - map[disk->id].device, strerror (errno)); + hostdisk_map[disk->id].device, strerror (errno)); buf += (1 << disk->log_sector_size); size--; @@ -1067,7 +1062,7 @@ if (grub_util_fd_read (fd, buf, max << disk->log_sector_size) != (ssize_t) (max << disk->log_sector_size)) return grub_error (GRUB_ERR_READ_ERROR, N_("cannot read `%s': %s"), - map[disk->id].device, strerror (errno)); + hostdisk_map[disk->id].device, strerror (errno)); size -= max; buf += (max << disk->log_sector_size); sector += max; @@ -1101,7 +1096,7 @@ != (1 << disk->log_sector_size)) return grub_error (GRUB_ERR_WRITE_ERROR, N_("cannot write to `%s': %s"), - map[disk->id].device, strerror (errno)); + hostdisk_map[disk->id].device, strerror (errno)); buf += (1 << disk->log_sector_size); size--; @@ -1112,7 +1107,7 @@ if (grub_util_fd_write (fd, buf, max << disk->log_sector_size) != (ssize_t) (max << disk->log_sector_size)) return grub_error (GRUB_ERR_WRITE_ERROR, N_("cannot write to `%s': %s"), - map[disk->id].device, strerror (errno)); + hostdisk_map[disk->id].device, strerror (errno)); size -= max; buf += (max << disk->log_sector_size); } @@ -1234,10 +1229,10 @@ show_error (tmp); } - map[drive].drive = xmalloc (p - e + sizeof ('\0')); - strncpy (map[drive].drive, e, p - e + sizeof ('\0')); - map[drive].drive[p - e] = '\0'; - map[drive].device_map = 1; + hostdisk_map[drive].drive = xmalloc (p - e + sizeof ('\0')); + strncpy (hostdisk_map[drive].drive, e, p - e + sizeof ('\0')); + hostdisk_map[drive].drive[p - e] = '\0'; + hostdisk_map[drive].device_map = 1; p++; /* Skip leading spaces. */ @@ -1260,8 +1255,8 @@ if (stat (p, &st) == -1) #endif { - free (map[drive].drive); - map[drive].drive = NULL; + free (hostdisk_map[drive].drive); + hostdisk_map[drive].drive = NULL; grub_util_info ("Cannot stat `%s', skipping", p); continue; } @@ -1272,13 +1267,13 @@ symbolic links. Leave /dev/mapper/ alone, though. */ if (strncmp (p, "/dev/mapper/", 12) != 0) { - map[drive].device = xmalloc (PATH_MAX); - if (! realpath (p, map[drive].device)) + hostdisk_map[drive].device = xmalloc (PATH_MAX); + if (! realpath (p, hostdisk_map[drive].device)) grub_util_error (_("failed to get canonical path of %s"), p); } else #endif - map[drive].device = xstrdup (p); + hostdisk_map[drive].device = xstrdup (p); } fclose (fp); @@ -1296,13 +1291,13 @@ { unsigned i; - for (i = 0; i < sizeof (map) / sizeof (map[0]); i++) + for (i = 0; i < sizeof (hostdisk_map) / sizeof (hostdisk_map[0]); i++) { - if (map[i].drive) - free (map[i].drive); - if (map[i].device) - free (map[i].device); - map[i].drive = map[i].device = NULL; + if (hostdisk_map[i].drive) + free (hostdisk_map[i].drive); + if (hostdisk_map[i].device) + free (hostdisk_map[i].device); + hostdisk_map[i].drive = hostdisk_map[i].device = NULL; } grub_disk_dev_unregister (&grub_util_biosdisk_dev); @@ -1311,7 +1306,7 @@ const char * grub_util_biosdisk_get_compatibility_hint (grub_disk_t disk) { - if (disk->dev != &grub_util_biosdisk_dev || map[disk->id].device_map) + if (disk->dev != &grub_util_biosdisk_dev || hostdisk_map[disk->id].device_map) return disk->name; return 0; } @@ -1322,5 +1317,5 @@ if (disk->dev != &grub_util_biosdisk_dev) return 0; - return map[disk->id].device; + return hostdisk_map[disk->id].device; } === modified file 'include/grub/emu/hostdisk.h' --- include/grub/emu/hostdisk.h 2012-02-29 14:23:31 +0000 +++ include/grub/emu/hostdisk.h 2012-04-22 18:21:40 +0000 @@ -24,6 +24,15 @@ #include #include +struct hostdisk_map +{ + char *drive; + char *device; + int device_map; +}; + +extern struct hostdisk_map hostdisk_map[256]; + void grub_util_biosdisk_init (const char *dev_map); void grub_util_biosdisk_fini (void); char *grub_util_biosdisk_get_grub_dev (const char *os_dev); === modified file 'util/getroot.c' --- util/getroot.c 2012-04-22 19:02:55 +0000 +++ util/getroot.c 2012-04-22 20:12:16 +0000 @@ -700,6 +700,153 @@ #elif defined (__GNU__) +#include +#include +#include +#include +#include + +/* 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; + } +} + +/* Retrieve 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) +{ + auto int check_part (grub_disk_t disk __attribute__((unused)), + const grub_partition_t partition); + auto int check_disk (const char *name); + + 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 && disk->dev->id != GRUB_DISK_DEVICE_HOSTDISK_ID) + { + grub_util_info ("`%s' is not a biosdisk or hostdisk, it is %d", name, disk->dev->id); + goto out_disk; + } + + disk_store = storeinfo_store (hostdisk_map[disk->id].device); + if (! disk_store) + { + grub_util_info ("Could not retrieve storage info for `%s'", hostdisk_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 retrieve storage information for `%s'", path); + + if (path_store->num_runs >= 1) + grub_disk_dev_iterate (check_disk); + + if (winner_disk >= 0) + { + const char *diskpath = hostdisk_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__) char * @@ -930,65 +1077,7 @@ grub_guess_root_devices (const char *dir) { char **os_dev = NULL; -#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 (2 * sizeof (os_dev[0])); - os_dev[0] = xmalloc (sizeof ("/dev/") - 1 + data_len); - memcpy (os_dev[0], "/dev/", sizeof ("/dev/") - 1); - memcpy (os_dev[0] + sizeof ("/dev/") - 1, data, data_len); - os_dev[1] = 0; - - 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); -#else /* !__GNU__ */ +#ifndef __GNU__ struct stat st; dev_t dev; @@ -1035,6 +1124,7 @@ grub_util_error (_("cannot stat `%s': %s"), dir, strerror (errno)); dev = st.st_dev; +#endif /* !__GNU__ */ os_dev = xmalloc (2 * sizeof (os_dev[0])); @@ -1042,6 +1132,10 @@ /* Cygwin specific function. */ os_dev[0] = grub_find_device (dir, dev); +#elif defined __GNU__ + /* GNU/Hurd specific function. */ + os_dev[0] = find_hurd_root_device (dir); + #else /* This might be truly slow, but is there any better way? */ @@ -1054,7 +1148,6 @@ } os_dev[1] = 0; -#endif /* !__GNU__ */ return os_dev; }