Hello,

The file_name_split(const char *path, char **name) function from glibc
resolves the parent directory for 'path' into a port (which is
returned) and makes '*name' point into 'path' at the beginning of the
base name. See 
http://www.gnu.org/software/hurd/hurd/glibc/hurd-specific_api.html.

There is a bug when 'path' is "/":
  * file_name_split() returns (<root port>, "")
  * the directory_name_split() variant returns (<CWD port>, "/")

The subsequent dir_* RPC calls generally fails with EINVAL. Compare
for instance the result of "mkdir /" vs. "mkdir /."

If there's no objection I would like to submit the attached patch for
inclusion in glibc. It returns the root port and a constant "." string
when the path is "/". Though this would change the interface slightly,
I have checked the code in glibc and the only use case for the
returned name is passing it to an RPC call and never using it again.
The only usage in hurd (namely, in nfsd) is similar.

In your opinion is this acceptable?

PS: I'll put a modified glibc package in my repository tomorrow (the
build takes like 12 hours). However I've tested the patch with the
remains of a failed build and it seems it works as exepected. BTW, a
modified gnumach with ramdisk is there as well (deb
http://jk.fr.eu.org/debian unstable/).
-- 
Jérémie Koenig <j...@jk.fr.eu.org>
http://jk.fr.eu.org/
Only in eglibc-2.11.1: build-tree
diff -ru eglibc-2.11.1.debian-orig/debian/changelog eglibc-2.11.1/debian/changelog
--- eglibc-2.11.1.debian-orig/debian/changelog	2010-06-11 17:15:34.000000000 +0200
+++ eglibc-2.11.1/debian/changelog	2010-06-12 03:41:27.000000000 +0200
@@ -1,3 +1,10 @@
+eglibc (2.11.1-2.0jk1) unstable; urgency=low
+
+  * Non-maintainer non-upload.
+  * Fix file_name_split("/") and directory_name_split("/").
+
+ -- Jeremie Koenig <j...@jk.fr.eu.org>  Sat, 12 Jun 2010 03:40:26 +0200
+
 eglibc (2.11.1-2) unstable; urgency=low
 
   [ Aurelien Jarno]
diff -ru eglibc-2.11.1.debian-orig/hurd/hurd.h eglibc-2.11.1/hurd/hurd.h
--- eglibc-2.11.1.debian-orig/hurd/hurd.h	2007-03-18 19:01:40.000000000 +0100
+++ eglibc-2.11.1/hurd/hurd.h	2010-06-12 21:49:58.000000000 +0200
@@ -183,7 +183,9 @@
    directory lookup uses the current root and working directory.  If
    successful, stores in *NAME a pointer into FILE where the name
    within directory begins and returns a port to the directory;
-   otherwise sets `errno' and returns MACH_PORT_NULL.  */
+   otherwise sets `errno' and returns MACH_PORT_NULL.  As a special
+   case, if PATH is "/", stores in *NAME a pointer into a constant
+   "." string and returns the current root directory.  */
 
 extern file_t __file_name_split (const char *file, char **name);
 extern file_t file_name_split (const char *file, char **name);
diff -ru eglibc-2.11.1.debian-orig/hurd/hurdlookup.c eglibc-2.11.1/hurd/hurdlookup.c
--- eglibc-2.11.1.debian-orig/hurd/hurdlookup.c	2006-08-17 03:18:26.000000000 +0200
+++ eglibc-2.11.1/hurd/hurdlookup.c	2010-06-12 20:20:08.000000000 +0200
@@ -22,6 +22,9 @@
 #include <string.h>
 #include <fcntl.h>
 
+/* Used as the basename of "/" by __hurd_{file,directory}_name_split() below */
+static const char *dot = ".";
+
 
 /* Translate the error from dir_lookup into the error the user sees.  */
 static inline error_t
@@ -126,8 +129,8 @@
     {
       if (lastslash == file_name)
 	{
-	  /* "/foobar" => crdir + "foobar".  */
-	  *name = (char *) file_name + 1;
+	  /* "/foobar" => crdir + "foobar", except for "/" => crdir + "." */
+	  *name = (char *) (file_name[1] ? file_name + 1 : dot);
 	  return (*use_init_port) (INIT_PORT_CRDIR, &addref);
 	}
       else
@@ -175,7 +178,7 @@
 
   const char *lastslash = strrchr (file_name, '/');
 
-  if (lastslash != NULL && lastslash[1] == '\0')
+  if (lastslash != NULL && lastslash[1] == '\0' && lastslash > file_name)
     {
       /* Trailing slash doesn't count.  Look back further.  */
 
@@ -191,8 +194,8 @@
     {
       if (lastslash == file_name)
 	{
-	  /* "/foobar" => crdir + "foobar".  */
-	  *name = (char *) file_name + 1;
+	  /* "/foobar" => crdir + "foobar", except for "/" => crdir + "." */
+	  *name = (char *) (file_name[1] ? file_name + 1 : dot);
 	  return (*use_init_port) (INIT_PORT_CRDIR, &addref);
 	}
       else
Only in eglibc-2.11.1: manual
Only in eglibc-2.11.1: stamp-dir
Only in eglibc-2.11.1/sysdeps: m68k
Only in eglibc-2.11.1.debian-orig/sysdeps/mach/hurd: .link.c.swp

Reply via email to