diff options
Diffstat (limited to 'REORG.TODO/hurd/hurdlookup.c')
-rw-r--r-- | REORG.TODO/hurd/hurdlookup.c | 281 |
1 files changed, 281 insertions, 0 deletions
diff --git a/REORG.TODO/hurd/hurdlookup.c b/REORG.TODO/hurd/hurdlookup.c new file mode 100644 index 0000000000..84cb3d3015 --- /dev/null +++ b/REORG.TODO/hurd/hurdlookup.c @@ -0,0 +1,281 @@ +/* Copyright (C) 1992-2017 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 + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <hurd.h> +#include <hurd/lookup.h> +#include <string.h> +#include <fcntl.h> + + +/* Translate the error from dir_lookup into the error the user sees. */ +static inline error_t +lookup_error (error_t error) +{ + switch (error) + { + case EOPNOTSUPP: + case MIG_BAD_ID: + /* These indicate that the server does not understand dir_lookup + at all. If it were a directory, it would, by definition. */ + return ENOTDIR; + default: + return error; + } +} + +error_t +__hurd_file_name_lookup (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, int flags, mode_t mode, + file_t *result) +{ + error_t err; + enum retry_type doretry; + char retryname[1024]; /* XXX string_t LOSES! */ + int startport; + + error_t lookup_op (mach_port_t startdir) + { + return lookup_error ((*lookup) (startdir, file_name, flags, mode, + &doretry, retryname, result)); + } + + if (! lookup) + lookup = __dir_lookup; + + if (file_name[0] == '\0') + return ENOENT; + + startport = (file_name[0] == '/') ? INIT_PORT_CRDIR : INIT_PORT_CWDIR; + while (file_name[0] == '/') + file_name++; + + if (flags & O_NOFOLLOW) /* See lookup-retry.c about O_NOFOLLOW. */ + flags |= O_NOTRANS; + + if (flags & O_DIRECTORY) + { + /* The caller wants to require that the file we look up is a directory. + We can do this without an extra RPC by appending a trailing slash + to the file name we look up. */ + size_t len = strlen (file_name); + if (len == 0) + file_name = "/"; + else if (file_name[len - 1] != '/') + { + char *n = alloca (len + 2); + memcpy (n, file_name, len); + n[len] = '/'; + n[len + 1] = '\0'; + file_name = n; + } + } + + err = (*use_init_port) (startport, &lookup_op); + if (! err) + err = __hurd_file_name_lookup_retry (use_init_port, get_dtable_port, + lookup, doretry, retryname, + flags, mode, result); + + return err; +} +weak_alias (__hurd_file_name_lookup, hurd_file_name_lookup) + +error_t +__hurd_file_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) + { + 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 if (file_name[0] == '\0') + return ENOENT; + else + { + /* "foobar" => cwdir + "foobar". */ + *name = (char *) file_name; + return (*use_init_port) (INIT_PORT_CWDIR, &addref); + } +} +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. */ + lastslash = __memrchr (file_name, '/', lastslash - file_name); + } + + 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 if (file_name[0] == '\0') + return ENOENT; + 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) +{ + error_t err; + file_t result; + + err = __hurd_file_name_lookup (&_hurd_ports_use, &__getdport, 0, + file_name, flags, mode & ~_hurd_umask, + &result); + + return err ? (__hurd_fail (err), MACH_PORT_NULL) : result; +} +weak_alias (__file_name_lookup, file_name_lookup) + + +file_t +__file_name_split (const char *file_name, char **name) +{ + error_t err; + file_t result; + + err = __hurd_file_name_split (&_hurd_ports_use, &__getdport, 0, + file_name, &result, name); + + return err ? (__hurd_fail (err), MACH_PORT_NULL) : result; +} +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, + const char *file_name, int flags, mode_t mode) +{ + error_t err; + file_t result; + + error_t use_init_port (int which, error_t (*operate) (mach_port_t)) + { + return (which == INIT_PORT_CWDIR ? (*operate) (startdir) : + _hurd_ports_use (which, operate)); + } + + err = __hurd_file_name_lookup (&use_init_port, &__getdport, 0, + file_name, flags, mode & ~_hurd_umask, + &result); + + return err ? (__hurd_fail (err), MACH_PORT_NULL) : result; +} +weak_alias (__file_name_lookup_under, file_name_lookup_under) |