Here's a patch which implements grub-mkrelpath based on my
make_system_path_relative_to_its_root patch to fix the problem with
grub-setup and blocklists, if the path to core.img given to grub-setup
isn't already relative to the root.
I wasn't sure if I should place the function now in
util/grub-mkrelpath.c or some other file. That depends if we're going to
use it now in grub-setup or not.

-- 
Felix Zielcke
Proud Debian Maintainer
2009-08-28  Felix Zielcke  <fziel...@z-51.de>

	* conf/common.rmk (bin_UTILITIES): Add grub-mkrelpath.
	(grub_mkrelpath_SOURCES): New variable.
	* configure.ac (AC_CHECK_FUNCS): Add realpath.
	* util/grub-mkconfig_lib.in (make_system_path_relative_to_its_root):
	Use grub-mkrelpath.
	* util/grub-mkrelpath.c: New file.

diff --git a/conf/common.rmk b/conf/common.rmk
index 6d76746..9a2dc4c 100644
--- a/conf/common.rmk
+++ b/conf/common.rmk
@@ -55,6 +55,10 @@ grub_mkfont_CFLAGS = $(freetype_cflags)
 grub_mkfont_LDFLAGS = $(freetype_libs)
 endif
 
+# For grub-mkrelpath.
+bin_UTILITIES += grub-mkrelpath
+grub_mkrelpath_SOURCES = util/grub-mkrelpath.c util/misc.c
+
 # For the parser.
 grub_script.tab.c grub_script.tab.h: script/sh/parser.y
 	$(YACC) -d -p grub_script_yy -b grub_script $(srcdir)/script/sh/parser.y
diff --git a/configure.ac b/configure.ac
index 549b35c..ee5ebb1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -172,7 +172,7 @@ if test x$grub_cv_apple_cc = xyes ; 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/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in
index 2385b08..c8d2736 100644
--- a/util/grub-mkconfig_lib.in
+++ b/util/grub-mkconfig_lib.in
@@ -32,49 +32,7 @@ grub_warn ()
 
 make_system_path_relative_to_its_root ()
 {
-  path=$1
-  # abort if file doesn't exist
-  if test -e $path ; then : ;else
-    return 1
-  fi
-
-  # canonicalize
-  if path=`readlink -f $path` ; then : ; else
-    return 1
-  fi
-
-  # if not a directory, climb up to the directory containing it
-  if test -d $path ; then
-    dir=$path
-  else
-    dir=`echo $path | sed -e "s,/[^/]*$,,g"`
-  fi
-
-  num=`stat -c %d $dir`
-
-  # this loop sets $dir to the root directory of the filesystem we're inspecting
-  while : ; do
-    parent=`readlink -f $dir/..`
-    if [ "x`stat -c %d $parent`" = "x$num" ] ; then : ; else
-      # $parent is another filesystem; we found it.
-      break
-    fi
-    if [ "x$dir" = "x/" ] ; then
-      # / is our root.
-      break
-    fi
-    dir=$parent
-  done
-
-  # This function never prints trailing slashes (so that its output can be
-  # appended a slash unconditionally).  Each slash in $dir is considered a
-  # preceding slash, and therefore the root directory is an empty string.
-  if [ "$dir" = "/" ] ; then
-    dir=""
-  fi
-
-  # XXX: This fails if $dir contains ','.
-  path=`echo "$path" | sed -e "s,^$dir,,g"` || return 1
+  path = "`grub-mkrelpath $1`"
 
   case "`uname 2>/dev/null`" in
     CYGWIN*)
diff --git a/util/grub-mkrelpath.c b/util/grub-mkrelpath.c
index e69de29..7c9c678 100644
--- a/util/grub-mkrelpath.c
+++ b/util/grub-mkrelpath.c
@@ -0,0 +1,194 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <grub/util/misc.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <string.h>
+#include <getopt.h>
+
+static struct option options[] =
+  {
+    {"help", no_argument, 0, 'h'},
+    {"version", no_argument, 0, 'V'},
+  };
+
+char *
+make_system_path_relative_to_its_root (const char *path)
+{
+  struct stat st;
+  char *p, *buf, *buf2, *buf3;
+  uintptr_t offset = 0;
+  dev_t num;
+  size_t len;
+
+#ifdef HAVE_REALPATH
+  p = realpath (path, NULL);
+
+  if (buf == NULL) 
+    {
+      if (errno != EINVAL)
+	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);
+  strcpy (buf, p);
+  free (p);
+#else /* ! HAVE_REALPATH */
+  grub_util_warn ("grub-mkrelpath might not work on your OS correctly.");
+  if (*path != '/')
+    {
+      len = 1024;
+      buf = xmalloc (len);
+      do
+	{
+	  p = getcwd (buf, len);
+	  if (p == NULL)
+	    {
+	      if (errno != ERANGE)
+		grub_util_error ("can not get current working directory");
+	      else
+		len *= 2;
+	      buf = xrealloc (buf, len);
+	    }
+	} while (p == NULL);
+      buf = xmalloc (strlen (path) + len + 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);
+  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);
+  buf3 = strdup (buf2 + offset);
+  free (buf2);
+  return buf3;
+}
+
+static void
+usage (int status)
+{
+  if (status)
+    fprintf (stderr, "Try ``grub-mkrelpath --help'' for more information.\n");
+  else
+    printf ("\
+Usage: grub-mkrelpath [OPTIONS] PATH\n\
+\n\
+Make a system path relative to it's root.\n\
+\n\
+Options:\n\
+  -h, --help                display this message and exit\n\
+  -V, --version             print version information and exit\n\
+\n\
+Report bugs to <%s>.\n", PACKAGE_BUGREPORT);
+
+  exit (status);
+}
+
+int
+main (int argc, char *argv[])
+{
+  char *argument, *relpath;
+
+  progname = "grub-mkrelpath";
+
+  /* Check for options.  */
+  while (1)
+    {
+      int c = getopt_long (argc, argv, "hV", options, 0);
+
+      if (c == -1)
+	break;
+      else
+	switch (c)
+	  {
+	  case 'h':
+	    usage (0);
+	    break;
+
+	  case 'V':
+	    printf ("%s (%s) %s\n", progname, PACKAGE_NAME, PACKAGE_VERSION);
+	    return 0;
+
+	  default:
+	    usage (1);
+	    break;
+	  }
+    }
+
+  if (optind >= argc)
+    {
+      fprintf (stderr, "No path is specified.\n");
+      usage (1);
+    }
+
+  if (optind + 1 != argc)
+    {
+      fprintf (stderr, "Unknown extra argument `%s'.\n", argv[optind + 1]);
+      usage (1);
+    }
+
+  argument = argv[optind];
+
+  relpath = make_system_path_relative_to_its_root (argument);
+  printf ("%s\n",relpath);
+  free (relpath);
+
+  return 0;
+}
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to