* sysdeps/unix/sysv/linux/m68k/sysdep.h (INLINE_SYSCALL): Don't
[glibc.git] / hurd / hurdlookup.c
blobe8ccc51aab9dc24d9118a6bffaa1a4c35f3a6fdc
1 /* Copyright (C) 1992,93,94,95,96,97,99,2001 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, write to the Free
16 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17 02111-1307 USA. */
19 #include <hurd.h>
20 #include <hurd/lookup.h>
21 #include <string.h>
22 #include <fcntl.h>
25 /* Translate the error from dir_lookup into the error the user sees. */
26 static inline error_t
27 lookup_error (error_t error)
29 switch (error)
31 case EOPNOTSUPP:
32 case MIG_BAD_ID:
33 /* These indicate that the server does not understand dir_lookup
34 at all. If it were a directory, it would, by definition. */
35 return ENOTDIR;
36 default:
37 return error;
41 error_t
42 __hurd_file_name_lookup (error_t (*use_init_port)
43 (int which, error_t (*operate) (file_t)),
44 file_t (*get_dtable_port) (int fd),
45 error_t (*lookup)
46 (file_t dir, char *name, int flags, mode_t mode,
47 retry_type *do_retry, string_t retry_name,
48 mach_port_t *result),
49 const char *file_name, int flags, mode_t mode,
50 file_t *result)
52 error_t err;
53 enum retry_type doretry;
54 char retryname[1024]; /* XXX string_t LOSES! */
55 int startport;
57 error_t lookup_op (mach_port_t startdir)
59 return lookup_error ((*lookup) (startdir, file_name, flags, mode,
60 &doretry, retryname, result));
63 if (! lookup)
64 lookup = __dir_lookup;
66 startport = (file_name[0] == '/') ? INIT_PORT_CRDIR : INIT_PORT_CWDIR;
67 while (file_name[0] == '/')
68 file_name++;
70 if (flags & O_NOFOLLOW) /* See comments below about O_NOFOLLOW. */
71 flags |= O_NOTRANS;
73 if (flags & O_DIRECTORY)
75 /* The caller wants to require that the file we look up is a directory.
76 We can do this without an extra RPC by appending a trailing slash
77 to the file name we look up. */
78 size_t len = strlen (file_name);
79 if (len == 0)
80 file_name = "/";
81 else if (file_name[len - 1] != '/')
83 char *n = alloca (len + 2);
84 memcpy (n, file_name, len);
85 n[len] = '/';
86 n[len + 1] = '\0';
87 file_name = n;
91 err = (*use_init_port) (startport, &lookup_op);
92 if (! err)
93 err = __hurd_file_name_lookup_retry (use_init_port, get_dtable_port,
94 lookup, doretry, retryname,
95 flags, mode, result);
97 return err;
99 weak_alias (__hurd_file_name_lookup, hurd_file_name_lookup)
101 error_t
102 __hurd_file_name_split (error_t (*use_init_port)
103 (int which, error_t (*operate) (file_t)),
104 file_t (*get_dtable_port) (int fd),
105 error_t (*lookup)
106 (file_t dir, char *name, int flags, mode_t mode,
107 retry_type *do_retry, string_t retry_name,
108 mach_port_t *result),
109 const char *file_name,
110 file_t *dir, char **name)
112 error_t addref (file_t crdir)
114 *dir = crdir;
115 return __mach_port_mod_refs (__mach_task_self (),
116 crdir, MACH_PORT_RIGHT_SEND, +1);
119 const char *lastslash = strrchr (file_name, '/');
121 if (lastslash != NULL)
123 if (lastslash == file_name)
125 /* "/foobar" => crdir + "foobar". */
126 *name = (char *) file_name + 1;
127 return (*use_init_port) (INIT_PORT_CRDIR, &addref);
129 else
131 /* "/dir1/dir2/.../file". */
132 char dirname[lastslash - file_name + 1];
133 memcpy (dirname, file_name, lastslash - file_name);
134 dirname[lastslash - file_name] = '\0';
135 *name = (char *) lastslash + 1;
136 return
137 __hurd_file_name_lookup (use_init_port, get_dtable_port, lookup,
138 dirname, 0, 0, dir);
141 else
143 /* "foobar" => cwdir + "foobar". */
144 *name = (char *) file_name;
145 return (*use_init_port) (INIT_PORT_CWDIR, &addref);
148 weak_alias (__hurd_file_name_split, hurd_file_name_split)
150 /* This is the same as hurd_file_name_split, except that it ignores
151 trailing slashes (so *NAME is never ""). */
152 error_t
153 __hurd_directory_name_split (error_t (*use_init_port)
154 (int which, error_t (*operate) (file_t)),
155 file_t (*get_dtable_port) (int fd),
156 error_t (*lookup)
157 (file_t dir, char *name, int flags, mode_t mode,
158 retry_type *do_retry, string_t retry_name,
159 mach_port_t *result),
160 const char *file_name,
161 file_t *dir, char **name)
163 error_t addref (file_t crdir)
165 *dir = crdir;
166 return __mach_port_mod_refs (__mach_task_self (),
167 crdir, MACH_PORT_RIGHT_SEND, +1);
170 const char *lastslash = strrchr (file_name, '/');
172 if (lastslash != NULL && lastslash[1] == '\0')
174 /* Trailing slash doesn't count. Look back further. */
176 /* Back up over all trailing slashes. */
177 while (lastslash > file_name && *lastslash == '/')
178 --lastslash;
180 /* Find the last one earlier in the string, before the trailing ones. */
181 #if __GLIBC__ > 2 || __GLIBC_MINOR__ >= 2
182 lastslash = __memrchr (file_name, '/', lastslash - file_name);
183 #else
184 /* Keep backing up, looking for a slash. */
186 if (lastslash == file_name)
188 /* Hit the start with no slash. */
189 lastslash = NULL;
190 break;
192 while (*lastslash-- != '/');
193 #endif
196 if (lastslash != NULL)
198 if (lastslash == file_name)
200 /* "/foobar" => crdir + "foobar". */
201 *name = (char *) file_name + 1;
202 return (*use_init_port) (INIT_PORT_CRDIR, &addref);
204 else
206 /* "/dir1/dir2/.../file". */
207 char dirname[lastslash - file_name + 1];
208 memcpy (dirname, file_name, lastslash - file_name);
209 dirname[lastslash - file_name] = '\0';
210 *name = (char *) lastslash + 1;
211 return
212 __hurd_file_name_lookup (use_init_port, get_dtable_port, lookup,
213 dirname, 0, 0, dir);
216 else
218 /* "foobar" => cwdir + "foobar". */
219 *name = (char *) file_name;
220 return (*use_init_port) (INIT_PORT_CWDIR, &addref);
223 weak_alias (__hurd_directory_name_split, hurd_directory_name_split)
226 file_t
227 __file_name_lookup (const char *file_name, int flags, mode_t mode)
229 error_t err;
230 file_t result;
232 err = __hurd_file_name_lookup (&_hurd_ports_use, &__getdport, 0,
233 file_name, flags, mode & ~_hurd_umask,
234 &result);
236 return err ? (__hurd_fail (err), MACH_PORT_NULL) : result;
238 weak_alias (__file_name_lookup, file_name_lookup)
241 file_t
242 __file_name_split (const char *file_name, char **name)
244 error_t err;
245 file_t result;
247 err = __hurd_file_name_split (&_hurd_ports_use, &__getdport, 0,
248 file_name, &result, name);
250 return err ? (__hurd_fail (err), MACH_PORT_NULL) : result;
252 weak_alias (__file_name_split, file_name_split)
254 file_t
255 __directory_name_split (const char *directory_name, char **name)
257 error_t err;
258 file_t result;
260 err = __hurd_directory_name_split (&_hurd_ports_use, &__getdport, 0,
261 directory_name, &result, name);
263 return err ? (__hurd_fail (err), MACH_PORT_NULL) : result;
265 weak_alias (__directory_name_split, directory_name_split)
268 file_t
269 __file_name_lookup_under (file_t startdir,
270 const char *file_name, int flags, mode_t mode)
272 error_t err;
273 file_t result;
275 error_t use_init_port (int which, error_t (*operate) (mach_port_t))
277 return (which == INIT_PORT_CWDIR ? (*operate) (startdir) :
278 _hurd_ports_use (which, operate));
281 err = __hurd_file_name_lookup (&use_init_port, &__getdport, 0,
282 file_name, flags, mode & ~_hurd_umask,
283 &result);
285 return err ? (__hurd_fail (err), MACH_PORT_NULL) : result;
287 weak_alias (__file_name_lookup_under, file_name_lookup_under)