Am Dienstag, den 09.06.2009, 23:51 +0200 schrieb Vladimir 'phcoder'
Serbinenko:

> +
> +char *grub_make_system_path_relative_to_its_root (char *path)
> +{
> +
> +  struct stat st;
> +  char buf[500], buf2[500];
> Use malloc instead of static allocation

Changed.

> +      p = strrchr (buf, '/');
> +      if (p != buf)
> +     *p = 0;
> +      else *++p = 0;
> You assume path starts with /. You have to check this. Otherwise you
> may get sigsegv

Changed.
> +      strcpy(buf2,buf);
> Just save (p - buf) instead of copying buf to buf2

I did this now if realpath () isn't avaible.
Now realpath is used in case it's avaible. POSIX specifies it and
readlink is actually using it if it's avaible. I didn't read the source
correctly.
The problem is just Cygwin. It has it but it returns the cygwin path.
So C:\\Windows would get /cygdrive/c/windows, which is easy to handle.
But realpath ("/boot/grub") would return /boot/grub which isn't true
from Windows/GRUB point of view.
Maybe Christian and Bean can say something about it.
MingW doestn't have it and I don't know what Windows would have, so the
MingW users would still use my own way.

-- 
Felix Zielcke
2009-06-11  Felix Zielcke  <fziel...@z-51.de>

        * 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 <stdint.h>.
        (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 <grub/misc.h>
 
 #include <stdio.h>
+#include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
@@ -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 ();
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to