From f1699640b137ca5b835a0100f1912e41e4a7741d Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Sat, 13 Nov 1999 23:42:45 +0000 Subject: [PATCH] 1999-10-04 Roland McGrath * hurd/hurdlookup.c (__hurd_directory_name_split): New function. (__directory_name_split): New function. * hurd/hurd.h: Declare them. * sysdeps/mach/hurd/rmdir.c: Use __directory_name_split instead of __file_name_split, so we ignore trailing slashes properly. * sysdeps/mach/hurd/rename.c: Likewise. --- hurd/hurd.h | 6 +++ hurd/hurdlookup.c | 88 ++++++++++++++++++++++++++++++++++++++ sysdeps/mach/hurd/rename.c | 6 +-- sysdeps/mach/hurd/rmdir.c | 4 +- 4 files changed, 99 insertions(+), 5 deletions(-) diff --git a/hurd/hurd.h b/hurd/hurd.h index da298641a27..1eab2e22cd6 100644 --- a/hurd/hurd.h +++ b/hurd/hurd.h @@ -184,6 +184,12 @@ extern int seteuids (int __n, const uid_t *__uidset); extern file_t __file_name_split (const char *file, char **name); extern file_t file_name_split (const char *file, char **name); +/* Split DIRECTORY into a parent directory and a name within the directory. + This is the same as file_name_split, but ignores trailing slashes. */ + +extern file_t __directory_name_split (const char *file, char **name); +extern file_t directory_name_split (const char *file, char **name); + /* Open a port to FILE with the given FLAGS and MODE (see ). The file lookup uses the current root and working directory. Returns a port to the file if successful; otherwise sets `errno' diff --git a/hurd/hurdlookup.c b/hurd/hurdlookup.c index 0714e4aa86e..7e5f9afa995 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, diff --git a/sysdeps/mach/hurd/rename.c b/sysdeps/mach/hurd/rename.c index f217dedc6a2..1923a440819 100644 --- a/sysdeps/mach/hurd/rename.c +++ b/sysdeps/mach/hurd/rename.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 92, 93, 94, 96, 97 Free Software Foundation, Inc. +/* Copyright (C) 1991,92,93,94,96,97,99 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -29,10 +29,10 @@ rename (old, new) file_t olddir, newdir; const char *oldname, *newname; - olddir = __file_name_split (old, (char **) &oldname); + olddir = __directory_name_split (old, (char **) &oldname); if (olddir == MACH_PORT_NULL) return -1; - newdir = __file_name_split (new, (char **) &newname); + newdir = __directory_name_split (new, (char **) &newname); if (newdir == MACH_PORT_NULL) { __mach_port_deallocate (__mach_task_self (), olddir); diff --git a/sysdeps/mach/hurd/rmdir.c b/sysdeps/mach/hurd/rmdir.c index 920d6986441..be9a254a307 100644 --- a/sysdeps/mach/hurd/rmdir.c +++ b/sysdeps/mach/hurd/rmdir.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 92, 93, 94, 95, 97 Free Software Foundation, Inc. +/* Copyright (C) 1991,92,93,94,95,97,99 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -28,7 +28,7 @@ __rmdir (file_name) { error_t err; const char *name; - file_t parent = __file_name_split (file_name, (char **) &name); + file_t parent = __directory_name_split (file_name, (char **) &name); if (parent == MACH_PORT_NULL) return -1; err = __dir_rmdir (parent, name); -- 2.47.2