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