2009-06-11 Felix Zielcke * configure.ac (AC_CHECK_FUNCS): Add realpath. * include/grub/util/hostdisk.c (grub_make_system_path_relative_to_its_root): New function prototype. * util/hostdisk.c: Include . (grub_make_system_path_relative_to_its_root): New function. * util/i386/pc/grub-setup.c (setup): Use grub_make_system_path_relative_to_its_root to make core_path_dev relative to the partition. diff --git a/configure.ac b/configure.ac index b0f7bb7..9d594db 100644 --- a/configure.ac +++ b/configure.ac @@ -196,7 +196,7 @@ if test "$target_cpu"-"$platform" = i386-pc; then fi # Check for functions. -AC_CHECK_FUNCS(posix_memalign memalign asprintf) +AC_CHECK_FUNCS(posix_memalign memalign asprintf realpath) # # Check for target programs. diff --git a/include/grub/util/hostdisk.h b/include/grub/util/hostdisk.h index 21efb0d..85df1c6 100644 --- a/include/grub/util/hostdisk.h +++ b/include/grub/util/hostdisk.h @@ -23,5 +23,6 @@ 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); +char *grub_make_system_path_relative_to_its_root (char *path,void **free_ptr); #endif /* ! GRUB_BIOSDISK_MACHINE_UTIL_HEADER */ diff --git a/util/hostdisk.c b/util/hostdisk.c index 1844a7e..3224e07 100644 --- a/util/hostdisk.c +++ b/util/hostdisk.c @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -1076,3 +1077,95 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev) return make_device_name (drive, -1, -1); #endif } + +char * +grub_make_system_path_relative_to_its_root (char *path, void **free_ptr) +{ + struct stat st; + char *buf, *buf2; + uintptr_t offset = 0; + dev_t num; + long path_max; + size_t len, len2; + char *p; + + +#ifdef HAVE_REALPATH + p = realpath (path, NULL); + + if (p == NULL) && (ernno != ) + grub_util_error ("failed to get realpath of %s", path); + else + grub_util_error ("realpath not supporting (path, NULL)"); + len = strlen (p) + 1; + buf = xmalloc (len); + buf2 = xmalloc (len); +# ifdef __CYGWIN__ + if (strncmp (p, 10, "/cygdrive/") == 0) + strcpy (buf, p + sizeof ("/cygdrive/c") - 1); + else + grub_util_error "path not under /cygdrive/. Aborting."; +# else + strcpy (buf, p); +#endif + free (p); +#else /* ! HAVE_REALPATH */ +# warning "The function `grub_make_system_path_relative_to_its_root' might not work on your OS correctly." + if (*path != '/') + { + len2 = 4096; + do + { + p = getcwd (buf, len) + if (p == NULL) + { + if (errno != ERANGE) + grub_util_error ("can not get current working directory"); + else + len2 *= 2; + } + } while (p == NULL) + + buf = xmalloc (strlen (path) + len2 + 1); + strcat (buf, "/"); + strcat (buf, path); + } + else + { + buf = xmalloc (strlen (path) + 1); + strcpy (buf, path) + } +#endif /* ! HAVE_REALPATH */ + buf2 = xmalloc (strlen (buf) + 1); + strcpy (buf2, buf); + *free_ptr = buf2; + if (stat (buf, &st) < 0) + grub_util_error ("can not stat %s", p); + + num = st.st_dev; + while (1) + { + p = strrchr (buf, '/'); + if (p == NULL) + grub_util_error ("FIXME no / in buf"); + if (p != buf) + *p = 0; + else + *++p = 0; + + if (stat (buf, &st) < 0) + grub_util_error ("can not stat %s", buf); + + if (st.st_dev != num) + break; + + offset = p - buf; + if (offset == 1) + { + free (buf); + return buf2; + } + } + free (buf); + return buf2 + offset; +} diff --git a/util/i386/pc/grub-setup.c b/util/i386/pc/grub-setup.c index bdf234c..c9243bd 100644 --- a/util/i386/pc/grub-setup.c +++ b/util/i386/pc/grub-setup.c @@ -89,7 +89,7 @@ setup (const char *dir, const char *root, const char *dest, int must_embed, int force) { char *boot_path, *core_path, *core_path_dev; - char *boot_img, *core_img; + char *boot_img, *core_img, *p, *free_ptr; size_t boot_size, core_size; grub_uint16_t core_sectors; grub_device_t root_dev, dest_dev; @@ -404,7 +404,10 @@ unable_to_embed: /* Make sure that GRUB reads the identical image as the OS. */ tmp_img = xmalloc (core_size); - core_path_dev = grub_util_get_path (dir, core_file); + p = grub_util_get_path (dir, core_file); + core_path_dev = grub_make_system_path_relative_to_its_root (p,&free_ptr); + free (p); + free (free_ptr); /* It is a Good Thing to sync two times. */ sync ();