From 994cc3a308a4451ef3b6db289a7a7dc1e298c90a Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sat, 21 Nov 2009 18:00:23 +0100 Subject: [PATCH] 2009-11-21 Samuel Thibault * util/getroot.c [__GNU__]: Include , , and [__GNU__] (grub_guess_root_device): Call file_name_lookup and file_get_storage_info to implement grub_guess_root_device. --- ChangeLog | 7 ++++++ util/getroot.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 2e6ab2bdc..243a92c4d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2009-11-21 Samuel Thibault + + * util/getroot.c [__GNU__]: Include , , and + + [__GNU__] (grub_guess_root_device): Call file_name_lookup and + file_get_storage_info to implement grub_guess_root_device. + 2009-11-21 Felix Zielcke * util/grub-mkrescue.in: Print an error and usage if output option diff --git a/util/getroot.c b/util/getroot.c index 120ab13b1..2915ab4f2 100644 --- a/util/getroot.c +++ b/util/getroot.c @@ -30,6 +30,12 @@ # define DEV_CYGDRIVE_MAJOR 98 #endif +#ifdef __GNU__ +#include +#include +#include +#endif + #include #include #include @@ -378,8 +384,65 @@ find_cygwin_root_device (const char *path, dev_t dev) char * grub_guess_root_device (const char *dir) { - struct stat st; 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); +#else /* !__GNU__ */ + struct stat st; if (stat (dir, &st) < 0) grub_util_error ("Cannot stat `%s'", dir); @@ -393,6 +456,7 @@ grub_guess_root_device (const char *dir) /* 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; }