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 e448c2f..9e923a6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -205,7 +205,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..a1ecf59 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)
#endif /* ! GRUB_BIOSDISK_MACHINE_UTIL_HEADER */
diff --git a/util/hostdisk.c b/util/hostdisk.c
index a7262dd..bce1b95 100644
--- a/util/hostdisk.c
+++ b/util/hostdisk.c
@@ -27,6 +27,7 @@
#include
#include
+#include
#include
#include
#include
@@ -1076,3 +1077,94 @@ 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)
+{
+ struct stat st;
+ char *buf, *buf2;
+ uintptr_t offset = 0;
+ dev_t num;
+ long path_max;
+#ifdef HAVE_REALPATH
+ char *p;
+#endif
+
+
+#ifdef HAVE_REALPATH
+# ifdef PATH_MAX
+ path_max = PATH_MAX
+# else
+ path_max = pathconf (path, _PC_PATH_MAX);
+ if (path_max <= 0)
+ /* 1024 is taken from glibc-2.10. */
+ path_max = 1024;
+# endif
+ p = xmalloc (path_max);
+ p = realpath (path, p);
+ if (p == NULL)
+ grub_util_error ("failed to get realpath of %s", path);
+
+#ifdef __CYGWIN__
+ if (strncmp (p,"/cygdrive/") == 0)
+ {
+ p += sizeof "/cygdrive/c" - 1;
+ }
+ else
+ grub_util_error "path not under /cygdrive/ aborting.";
+#endif
+ buf = xmalloc (path_max);
+ buf2 = xmalloc (path_max);
+ strcpy (buf, p);
+ free (p);
+#else /* ! HAVE_REALPATH */
+# warning "The function `grub_make_system_path_relative_to_its_root' might not work on your OS correctly."
+ path_max = 1024;
+ buf = xmalloc (path_max);
+ buf2 = xmalloc (path_max);
+ memset (buf, 0, sizeof (buf));
+ if (*path != '/')
+ {
+ size_t len = strlen (path);
+
+ if (getcwd (buf, 1024 - len) == NULL)
+ grub_util_error ("can not get current working directory");
+
+ strcat (buf, "/");
+ strcat (buf, path);
+ }
+ else
+ {
+ if (strlen (path) > 1024)
+ grub_util_error ("path too long");
+ strncpy (buf, path, 1024);
+ }
+#endif /* ! HAVE_REALPATH */
+
+ strcpy (buf2, buf);
+ 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 p");
+ 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)
+ return buf2;
+ }
+ return buf2 + offset;
+}
diff --git a/util/i386/pc/grub-setup.c b/util/i386/pc/grub-setup.c
index 997811b..7fb0273 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;
size_t boot_size, core_size;
grub_uint16_t core_sectors;
grub_device_t root_dev, dest_dev;
@@ -404,7 +404,9 @@ 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 (p);
/* It is a Good Thing to sync two times. */
sync ();