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 ();