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