]> sourceware.org Git - glibc.git/blame - hurd/hurdlookup.c
(__hurd_file_name_lookup_retry, __hurd_file_name_lookup, __hurd_file_name_split)...
[glibc.git] / hurd / hurdlookup.c
CommitLineData
dc825f85 1/* Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
28f540f4
RM
2This file is part of the GNU C Library.
3
4The GNU C Library is free software; you can redistribute it and/or
5modify it under the terms of the GNU Library General Public License as
6published by the Free Software Foundation; either version 2 of the
7License, or (at your option) any later version.
8
9The GNU C Library is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12Library General Public License for more details.
13
14You should have received a copy of the GNU Library General Public
15License along with the GNU C Library; see the file COPYING.LIB. If
16not, write to the Free Software Foundation, Inc., 675 Mass Ave,
17Cambridge, MA 02139, USA. */
18
19#include <hurd.h>
2948fc64 20#include <hurd/lookup.h>
28f540f4
RM
21#include <string.h>
22#include <limits.h>
23#include <fcntl.h>
cabcc273 24#include "stdio-common/_itoa.h"
28f540f4
RM
25#include <hurd/term.h>
26
27
28/* Translate the error from dir_lookup into the error the user sees. */
29static inline error_t
30lookup_error (error_t error)
31{
32 switch (error)
33 {
34 case EOPNOTSUPP:
35 case MIG_BAD_ID:
36 /* These indicate that the server does not understand dir_lookup
37 at all. If it were a directory, it would, by definition. */
38 return ENOTDIR;
39 default:
40 return error;
41 }
42}
43
44error_t
2948fc64
RM
45__hurd_file_name_lookup (error_t (*use_init_port)
46 (int which, error_t (*operate) (file_t)),
47 file_t (*get_dtable_port) (int fd),
92ea4fec
MB
48 error_t (*lookup)
49 (file_t dir, char *name, int flags, mode_t mode,
50 retry_type *do_retry, string_t retry_name,
51 mach_port_t *result),
28f540f4
RM
52 const char *file_name, int flags, mode_t mode,
53 file_t *result)
54{
55 error_t err;
56 enum retry_type doretry;
57 char retryname[1024]; /* XXX string_t LOSES! */
28f540f4 58
92ea4fec 59 error_t lookup_op (mach_port_t startdir)
2948fc64
RM
60 {
61 while (file_name[0] == '/')
62 file_name++;
28f540f4 63
92ea4fec
MB
64 return lookup_error ((*lookup) (startdir, file_name, flags, mode,
65 &doretry, retryname, result));
2948fc64 66 }
28f540f4 67
92ea4fec
MB
68 if (! lookup)
69 lookup = __dir_lookup;
70
2948fc64
RM
71 err = (*use_init_port) (file_name[0] == '/'
72 ? INIT_PORT_CRDIR : INIT_PORT_CWDIR,
92ea4fec 73 &lookup_op);
2948fc64 74 if (! err)
92ea4fec 75 err = __hurd_file_name_lookup_retry (use_init_port, get_dtable_port, lookup,
2948fc64
RM
76 doretry, retryname, flags, mode,
77 result);
28f540f4 78
2948fc64 79 return err;
28f540f4
RM
80}
81weak_alias (__hurd_file_name_lookup, hurd_file_name_lookup)
82
83error_t
2948fc64
RM
84__hurd_file_name_lookup_retry (error_t (*use_init_port)
85 (int which, error_t (*operate) (file_t)),
86 file_t (*get_dtable_port) (int fd),
92ea4fec
MB
87 error_t (*lookup)
88 (file_t dir, char *name, int flags, mode_t mode,
89 retry_type *do_retry, string_t retry_name,
90 mach_port_t *result),
28f540f4
RM
91 enum retry_type doretry,
92 char retryname[1024],
93 int flags, mode_t mode,
94 file_t *result)
95{
96 error_t err;
28f540f4 97 char *file_name;
28f540f4
RM
98 int nloops;
99
92ea4fec 100 error_t lookup_op (file_t startdir)
2948fc64
RM
101 {
102 while (file_name[0] == '/')
103 file_name++;
104
92ea4fec
MB
105 return lookup_error ((*lookup) (startdir, file_name, flags, mode,
106 &doretry, retryname, result));
2948fc64
RM
107 }
108 error_t reauthenticate (file_t unauth)
109 {
110 error_t err;
111 mach_port_t ref = __mach_reply_port ();
112 error_t reauth (auth_t auth)
113 {
8f0c527e 114 return __auth_user_authenticate (auth, ref,
2948fc64
RM
115 MACH_MSG_TYPE_MAKE_SEND,
116 result);
117 }
118 err = __io_reauthenticate (unauth, ref, MACH_MSG_TYPE_MAKE_SEND);
119 if (! err)
120 err = (*use_init_port) (INIT_PORT_AUTH, &reauth);
121 __mach_port_destroy (__mach_task_self (), ref);
122 __mach_port_deallocate (__mach_task_self (), unauth);
123 return err;
124 }
125
92ea4fec
MB
126 if (! lookup)
127 lookup = __dir_lookup;
128
28f540f4
RM
129 nloops = 0;
130 err = 0;
2948fc64 131 do
28f540f4 132 {
2948fc64
RM
133 file_t startdir = MACH_PORT_NULL;
134 int dirport = INIT_PORT_CWDIR;
28f540f4
RM
135
136 switch (doretry)
137 {
138 case FS_RETRY_REAUTH:
2948fc64 139 if (err = reauthenticate (*result))
28f540f4 140 return err;
28f540f4
RM
141 /* Fall through. */
142
143 case FS_RETRY_NORMAL:
144#ifdef SYMLOOP_MAX
145 if (nloops++ >= SYMLOOP_MAX)
146 return ELOOP;
147#endif
148
149 /* An empty RETRYNAME indicates we have the final port. */
4ca84cff
RM
150 if (retryname[0] == '\0' &&
151 /* If reauth'd, we must do one more retry on "" to give the new
152 translator a chance to make a new port for us. */
153 doretry == FS_RETRY_NORMAL)
28f540f4
RM
154 {
155 /* We got a successful translation. Now apply any open-time
156 action flags we were passed. */
157 if (flags & O_EXLOCK)
158 ; /* XXX */
159 if (!err && (flags & O_SHLOCK))
160 ; /* XXX */
161 if (!err && (flags & O_TRUNC))
aa910907 162 err = __file_set_size (*result, 0);
28f540f4
RM
163
164 if (err)
165 __mach_port_deallocate (__mach_task_self (), *result);
166 return err;
167 }
168
169 startdir = *result;
28f540f4
RM
170 file_name = retryname;
171 break;
172
173 case FS_RETRY_MAGICAL:
174 switch (retryname[0])
175 {
176 case '/':
2948fc64 177 dirport = INIT_PORT_CRDIR;
28f540f4
RM
178 if (*result != MACH_PORT_NULL)
179 __mach_port_deallocate (__mach_task_self (), *result);
180 file_name = &retryname[1];
181 break;
182
183 case 'f':
184 if (retryname[1] == 'd' && retryname[2] == '/')
185 {
186 int fd;
187 char *end;
188 int save = errno;
189 errno = 0;
4d049a8b 190 fd = (int) strtol (&retryname[3], &end, 10);
28f540f4
RM
191 if (end == NULL || errno || /* Malformed number. */
192 /* Check for excess text after the number. A slash
193 is valid; it ends the component. Anything else
194 does not name a numeric file descriptor. */
195 (*end != '/' && *end != '\0'))
196 {
197 errno = save;
198 return ENOENT;
199 }
2948fc64
RM
200 if (! get_dtable_port)
201 err = EGRATUITOUS;
202 else
28f540f4 203 {
2948fc64
RM
204 *result = (*get_dtable_port) (fd);
205 if (*result == MACH_PORT_NULL)
206 {
207 /* If the name was a proper number, but the file
208 descriptor does not exist, we return EBADF instead
209 of ENOENT. */
210 err = errno;
211 errno = save;
212 }
28f540f4
RM
213 }
214 errno = save;
2948fc64
RM
215 if (err)
216 return err;
28f540f4
RM
217 if (*end == '\0')
218 return 0;
219 else
220 {
221 /* Do a normal retry on the remaining components. */
222 startdir = *result;
28f540f4
RM
223 file_name = end + 1; /* Skip the slash. */
224 break;
225 }
226 }
227 else
228 goto bad_magic;
229 break;
230
231 case 'm':
232 if (retryname[1] == 'a' && retryname[2] == 'c' &&
233 retryname[3] == 'h' && retryname[4] == 't' &&
234 retryname[5] == 'y' && retryname[6] == 'p' &&
235 retryname[7] == 'e')
236 {
237 error_t err;
238 struct host_basic_info hostinfo;
239 mach_msg_type_number_t hostinfocnt = HOST_BASIC_INFO_COUNT;
240 char *p;
2948fc64 241 /* XXX want client's host */
28f540f4
RM
242 if (err = __host_info (__mach_host_self (), HOST_BASIC_INFO,
243 (natural_t *) &hostinfo,
244 &hostinfocnt))
245 return err;
246 if (hostinfocnt != HOST_BASIC_INFO_COUNT)
247 return EGRATUITOUS;
248 p = _itoa (hostinfo.cpu_subtype, &retryname[8], 10, 0);
249 *--p = '/';
250 p = _itoa (hostinfo.cpu_type, &retryname[8], 10, 0);
251 if (p < retryname)
252 abort (); /* XXX write this right if this ever happens */
253 if (p > retryname)
254 strcpy (retryname, p);
255 startdir = *result;
28f540f4
RM
256 }
257 else
258 goto bad_magic;
259 break;
260
261 case 't':
262 if (retryname[1] == 't' && retryname[2] == 'y')
263 switch (retryname[3])
264 {
265 error_t opentty (file_t *result)
266 {
267 error_t err;
2948fc64 268 error_t ctty_open (file_t port)
28f540f4 269 {
787e4db9
RM
270 if (port == MACH_PORT_NULL)
271 return ENXIO; /* No controlling terminal. */
2948fc64
RM
272 return __termctty_open_terminal (port,
273 flags,
274 result);
28f540f4 275 }
2948fc64
RM
276 err = (*use_init_port) (INIT_PORT_CTTYID, &ctty_open);
277 if (! err)
278 err = reauthenticate (*result);
28f540f4
RM
279 return err;
280 }
281
282 case '\0':
283 return opentty (result);
284 case '/':
285 if (err = opentty (&startdir))
286 return err;
28f540f4
RM
287 strcpy (retryname, &retryname[4]);
288 break;
289 default:
290 goto bad_magic;
291 }
292 else
293 goto bad_magic;
294 break;
295
296 default:
297 bad_magic:
298 return EGRATUITOUS;
299 }
787e4db9 300 break;
28f540f4
RM
301
302 default:
303 return EGRATUITOUS;
304 }
305
2948fc64
RM
306 if (startdir != MACH_PORT_NULL)
307 {
92ea4fec 308 err = lookup_op (startdir);
2948fc64
RM
309 __mach_port_deallocate (__mach_task_self (), startdir);
310 startdir = MACH_PORT_NULL;
311 }
312 else
92ea4fec 313 err = (*use_init_port) (dirport, &lookup_op);
2948fc64
RM
314 } while (! err);
315
316 return err;
28f540f4
RM
317}
318weak_alias (__hurd_file_name_lookup_retry, hurd_file_name_lookup_retry)
319
320error_t
2948fc64
RM
321__hurd_file_name_split (error_t (*use_init_port)
322 (int which, error_t (*operate) (file_t)),
323 file_t (*get_dtable_port) (int fd),
92ea4fec
MB
324 error_t (*lookup)
325 (file_t dir, char *name, int flags, mode_t mode,
326 retry_type *do_retry, string_t retry_name,
327 mach_port_t *result),
28f540f4
RM
328 const char *file_name,
329 file_t *dir, char **name)
330{
2948fc64
RM
331 error_t addref (file_t crdir)
332 {
333 *dir = crdir;
787e4db9 334 return __mach_port_mod_refs (__mach_task_self (),
2948fc64
RM
335 crdir, MACH_PORT_RIGHT_SEND, +1);
336 }
337
338 const char *lastslash = strrchr (file_name, '/');
28f540f4 339
28f540f4
RM
340 if (lastslash != NULL)
341 {
342 if (lastslash == file_name)
343 {
344 /* "/foobar" => crdir + "foobar". */
345 *name = (char *) file_name + 1;
2948fc64 346 return (*use_init_port) (INIT_PORT_CRDIR, &addref);
28f540f4
RM
347 }
348 else
349 {
350 /* "/dir1/dir2/.../file". */
351 char dirname[lastslash - file_name + 1];
352 memcpy (dirname, file_name, lastslash - file_name);
353 dirname[lastslash - file_name] = '\0';
354 *name = (char *) lastslash + 1;
92ea4fec
MB
355 return
356 __hurd_file_name_lookup (use_init_port, get_dtable_port, lookup,
357 dirname, 0, 0, dir);
28f540f4
RM
358 }
359 }
360 else
361 {
362 /* "foobar" => cwdir + "foobar". */
363 *name = (char *) file_name;
2948fc64 364 return (*use_init_port) (INIT_PORT_CWDIR, &addref);
28f540f4
RM
365 }
366}
367weak_alias (__hurd_file_name_split, hurd_file_name_split)
368
369\f
370file_t
371__file_name_lookup (const char *file_name, int flags, mode_t mode)
372{
373 error_t err;
2948fc64 374 file_t result;
28f540f4 375
92ea4fec 376 err = __hurd_file_name_lookup (&_hurd_ports_use, &__getdport, 0,
dc825f85 377 file_name, flags, mode & ~_hurd_umask,
28f540f4
RM
378 &result);
379
2948fc64 380 return err ? (__hurd_fail (err), MACH_PORT_NULL) : result;
28f540f4
RM
381}
382weak_alias (__file_name_lookup, file_name_lookup)
383
384
385file_t
386__file_name_split (const char *file_name, char **name)
387{
388 error_t err;
2948fc64
RM
389 file_t result;
390
92ea4fec 391 err = __hurd_file_name_split (&_hurd_ports_use, &__getdport, 0,
2948fc64 392 file_name, &result, name);
28f540f4 393
2948fc64
RM
394 return err ? (__hurd_fail (err), MACH_PORT_NULL) : result;
395}
396weak_alias (__file_name_split, file_name_split)
28f540f4 397
28f540f4 398
2948fc64
RM
399file_t
400__file_name_lookup_under (file_t startdir,
401 const char *file_name, int flags, mode_t mode)
402{
403 error_t err;
404 file_t result;
28f540f4 405
2948fc64 406 error_t use_init_port (int which, error_t (*operate) (mach_port_t))
28f540f4 407 {
2948fc64
RM
408 return (which == INIT_PORT_CWDIR ? (*operate) (startdir) :
409 _hurd_ports_use (which, operate));
28f540f4 410 }
2948fc64 411
92ea4fec 412 err = __hurd_file_name_lookup (&use_init_port, &__getdport, 0,
dc825f85 413 file_name, flags, mode & ~_hurd_umask,
2948fc64
RM
414 &result);
415
416 return err ? (__hurd_fail (err), MACH_PORT_NULL) : result;
28f540f4 417}
2948fc64 418weak_alias (__file_name_lookup_under, file_name_lookup_under)
This page took 0.087541 seconds and 5 git commands to generate.