about summary refs log tree commit diff
path: root/hurd/hurdlookup.c
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>1999-11-13 23:52:38 +0000
committerRoland McGrath <roland@gnu.org>1999-11-13 23:52:38 +0000
commit0bd019279b29e72861ba57e6101afa5e6dafb3a5 (patch)
tree9c89dfd0f45958c30c82d3a5097cf5feaf96bd95 /hurd/hurdlookup.c
parent28f08f3fd1c20c4352746839c242d3a7776041a6 (diff)
downloadglibc-0bd019279b29e72861ba57e6101afa5e6dafb3a5.tar.gz
glibc-0bd019279b29e72861ba57e6101afa5e6dafb3a5.tar.xz
glibc-0bd019279b29e72861ba57e6101afa5e6dafb3a5.zip
* Versions.def (libc): Move GLIBC_2.2 dependency from GLIBC_2.1.1 to
	GLIBC_2.1.3.

1999-11-13  Roland McGrath  <roland@baalperazim.frob.com>
Diffstat (limited to 'hurd/hurdlookup.c')
-rw-r--r--hurd/hurdlookup.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/hurd/hurdlookup.c b/hurd/hurdlookup.c
index 0714e4aa86..7e5f9afa99 100644
--- a/hurd/hurdlookup.c
+++ b/hurd/hurdlookup.c
@@ -429,6 +429,81 @@ __hurd_file_name_split (error_t (*use_init_port)
 }
 weak_alias (__hurd_file_name_split, hurd_file_name_split)
 
+/* This is the same as hurd_file_name_split, except that it ignores
+   trailing slashes (so *NAME is never "").  */
+error_t
+__hurd_directory_name_split (error_t (*use_init_port)
+			     (int which, error_t (*operate) (file_t)),
+			     file_t (*get_dtable_port) (int fd),
+			     error_t (*lookup)
+			     (file_t dir, char *name, int flags, mode_t mode,
+			      retry_type *do_retry, string_t retry_name,
+			      mach_port_t *result),
+			     const char *file_name,
+			     file_t *dir, char **name)
+{
+  error_t addref (file_t crdir)
+    {
+      *dir = crdir;
+      return __mach_port_mod_refs (__mach_task_self (),
+				   crdir, MACH_PORT_RIGHT_SEND, +1);
+    }
+
+  const char *lastslash = strrchr (file_name, '/');
+
+  if (lastslash != NULL && lastslash[1] == '\0')
+    {
+      /* Trailing slash doesn't count.  Look back further.  */
+
+      /* Back up over all trailing slashes.  */
+      while (lastslash > file_name && *lastslash == '/')
+	--lastslash;
+
+      /* Find the last one earlier in the string, before the trailing ones.  */
+#if __GLIBC__ > 2 || __GLIBC_MINOR__ >= 2
+      lastslash = __memrchr (file_name, '/', lastslash - file_name);
+#else
+      /* Keep backing up, looking for a slash.  */
+      do
+	if (lastslash == file_name)
+	  {
+	    /* Hit the start with no slash.  */
+	    lastslash = NULL;
+	    break;
+	  }
+      while (*lastslash-- != '/');
+#endif
+    }
+
+  if (lastslash != NULL)
+    {
+      if (lastslash == file_name)
+	{
+	  /* "/foobar" => crdir + "foobar".  */
+	  *name = (char *) file_name + 1;
+	  return (*use_init_port) (INIT_PORT_CRDIR, &addref);
+	}
+      else
+	{
+	  /* "/dir1/dir2/.../file".  */
+	  char dirname[lastslash - file_name + 1];
+	  memcpy (dirname, file_name, lastslash - file_name);
+	  dirname[lastslash - file_name] = '\0';
+	  *name = (char *) lastslash + 1;
+	  return
+	    __hurd_file_name_lookup (use_init_port, get_dtable_port, lookup,
+				     dirname, 0, 0, dir);
+	}
+    }
+  else
+    {
+      /* "foobar" => cwdir + "foobar".  */
+      *name = (char *) file_name;
+      return (*use_init_port) (INIT_PORT_CWDIR, &addref);
+    }
+}
+weak_alias (__hurd_directory_name_split, hurd_directory_name_split)
+
 
 file_t
 __file_name_lookup (const char *file_name, int flags, mode_t mode)
@@ -458,6 +533,19 @@ __file_name_split (const char *file_name, char **name)
 }
 weak_alias (__file_name_split, file_name_split)
 
+file_t
+__directory_name_split (const char *directory_name, char **name)
+{
+  error_t err;
+  file_t result;
+
+  err = __hurd_directory_name_split (&_hurd_ports_use, &__getdport, 0,
+				     directory_name, &result, name);
+
+  return err ? (__hurd_fail (err), MACH_PORT_NULL) : result;
+}
+weak_alias (__directory_name_split, directory_name_split)
+
 
 file_t
 __file_name_lookup_under (file_t startdir,