(os=gnu*): Always set elf=yes, not just for os=gnu*elf*.
[glibc.git] / hurd / hurdlookup.c
blobb467404840be06bad86f50f6a2c41c0d308890fe
1 /* Copyright (C) 1992, 1993, 1994, 1995 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 Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 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 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB. If
16 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
17 Cambridge, MA 02139, USA. */
19 #include <hurd.h>
20 #include <string.h>
21 #include <limits.h>
22 #include <fcntl.h>
23 #include "stdio/_itoa.h"
24 #include <hurd/term.h>
27 /* Translate the error from dir_lookup into the error the user sees. */
28 static inline error_t
29 lookup_error (error_t error)
31 switch (error)
33 case EOPNOTSUPP:
34 case MIG_BAD_ID:
35 /* These indicate that the server does not understand dir_lookup
36 at all. If it were a directory, it would, by definition. */
37 return ENOTDIR;
38 default:
39 return error;
43 error_t
44 __hurd_file_name_lookup (file_t crdir, file_t cwdir,
45 const char *file_name, int flags, mode_t mode,
46 file_t *result)
48 error_t err;
49 enum retry_type doretry;
50 char retryname[1024]; /* XXX string_t LOSES! */
51 file_t startdir;
53 startdir = file_name[0] == '/' ? crdir : cwdir;
55 while (file_name[0] == '/')
56 file_name++;
58 if (err = __dir_lookup (startdir, file_name, flags, mode,
59 &doretry, retryname, result))
60 return lookup_error (err);
62 return __hurd_file_name_lookup_retry (crdir, doretry, retryname, flags, mode,
63 result);
65 weak_alias (__hurd_file_name_lookup, hurd_file_name_lookup)
67 error_t
68 __hurd_file_name_lookup_retry (file_t crdir,
69 enum retry_type doretry,
70 char retryname[1024],
71 int flags, mode_t mode,
72 file_t *result)
74 error_t err;
75 file_t startdir;
76 file_t newpt;
77 char *file_name;
78 int dealloc_dir;
79 int nloops;
81 dealloc_dir = 0;
82 nloops = 0;
83 err = 0;
85 while (1)
87 if (dealloc_dir)
88 __mach_port_deallocate (__mach_task_self (), startdir);
89 if (err)
90 return lookup_error (err);
92 switch (doretry)
94 case FS_RETRY_REAUTH:
96 mach_port_t ref = __mach_reply_port ();
97 err = __io_reauthenticate (*result,
98 ref, MACH_MSG_TYPE_MAKE_SEND);
99 if (! err)
100 err = __USEPORT
101 (AUTH, __auth_user_authenticate (port, *result,
102 ref,
103 MACH_MSG_TYPE_MAKE_SEND,
104 &newpt));
105 __mach_port_destroy (__mach_task_self (), ref);
107 __mach_port_deallocate (__mach_task_self (), *result);
108 if (err)
109 return err;
110 *result = newpt;
111 /* Fall through. */
113 case FS_RETRY_NORMAL:
114 #ifdef SYMLOOP_MAX
115 if (nloops++ >= SYMLOOP_MAX)
116 return ELOOP;
117 #endif
119 /* An empty RETRYNAME indicates we have the final port. */
120 if (retryname[0] == '\0')
122 /* We got a successful translation. Now apply any open-time
123 action flags we were passed. */
124 if (flags & O_EXLOCK)
125 ; /* XXX */
126 if (!err && (flags & O_SHLOCK))
127 ; /* XXX */
128 if (!err && (flags & O_TRUNC))
129 err = __file_truncate (*result, 0);
131 if (err)
132 __mach_port_deallocate (__mach_task_self (), *result);
133 return err;
136 startdir = *result;
137 dealloc_dir = 1;
138 file_name = retryname;
139 break;
141 case FS_RETRY_MAGICAL:
142 switch (retryname[0])
144 case '/':
145 startdir = crdir;
146 dealloc_dir = 0;
147 if (*result != MACH_PORT_NULL)
148 __mach_port_deallocate (__mach_task_self (), *result);
149 file_name = &retryname[1];
150 break;
152 case 'f':
153 if (retryname[1] == 'd' && retryname[2] == '/')
155 int fd;
156 char *end;
157 int save = errno;
158 errno = 0;
159 fd = (int) strtol (retryname, &end, 10);
160 if (end == NULL || errno || /* Malformed number. */
161 /* Check for excess text after the number. A slash
162 is valid; it ends the component. Anything else
163 does not name a numeric file descriptor. */
164 (*end != '/' && *end != '\0'))
166 errno = save;
167 return ENOENT;
169 *result = __getdport (fd);
170 if (*result == MACH_PORT_NULL)
172 /* If the name was a proper number, but the file
173 descriptor does not exist, we return EBADF instead
174 of ENOENT. */
175 error_t err = errno;
176 errno = save;
177 return err;
179 errno = save;
180 if (*end == '\0')
181 return 0;
182 else
184 /* Do a normal retry on the remaining components. */
185 startdir = *result;
186 dealloc_dir = 1;
187 file_name = end + 1; /* Skip the slash. */
188 break;
191 else
192 goto bad_magic;
193 break;
195 case 'm':
196 if (retryname[1] == 'a' && retryname[2] == 'c' &&
197 retryname[3] == 'h' && retryname[4] == 't' &&
198 retryname[5] == 'y' && retryname[6] == 'p' &&
199 retryname[7] == 'e')
201 error_t err;
202 struct host_basic_info hostinfo;
203 mach_msg_type_number_t hostinfocnt = HOST_BASIC_INFO_COUNT;
204 char *p;
205 if (err = __host_info (__mach_host_self (), HOST_BASIC_INFO,
206 (natural_t *) &hostinfo,
207 &hostinfocnt))
208 return err;
209 if (hostinfocnt != HOST_BASIC_INFO_COUNT)
210 return EGRATUITOUS;
211 p = _itoa (hostinfo.cpu_subtype, &retryname[8], 10, 0);
212 *--p = '/';
213 p = _itoa (hostinfo.cpu_type, &retryname[8], 10, 0);
214 if (p < retryname)
215 abort (); /* XXX write this right if this ever happens */
216 if (p > retryname)
217 strcpy (retryname, p);
218 startdir = *result;
219 dealloc_dir = 1;
221 else
222 goto bad_magic;
223 break;
225 case 't':
226 if (retryname[1] == 't' && retryname[2] == 'y')
227 switch (retryname[3])
229 error_t opentty (file_t *result)
231 error_t err;
232 file_t unauth;
233 err = __USEPORT (CTTYID,
234 __termctty_open_terminal (port,
235 flags,
236 &unauth));
237 if (! err)
239 mach_port_t ref = __mach_reply_port ();
240 err = __io_reauthenticate
241 (unauth,
242 ref,
243 MACH_MSG_TYPE_MAKE_SEND);
244 if (! err)
245 err = __USEPORT
246 (AUTH, __auth_user_authenticate
247 (port,
248 unauth,
249 ref, MACH_MSG_TYPE_MAKE_SEND,
250 result));
251 __mach_port_deallocate (__mach_task_self (),
252 unauth);
253 __mach_port_destroy (__mach_task_self (), ref);
255 return err;
258 case '\0':
259 return opentty (result);
260 case '/':
261 if (err = opentty (&startdir))
262 return err;
263 dealloc_dir = 1;
264 strcpy (retryname, &retryname[4]);
265 break;
266 default:
267 goto bad_magic;
269 else
270 goto bad_magic;
271 break;
273 default:
274 bad_magic:
275 return EGRATUITOUS;
277 break;
279 default:
280 return EGRATUITOUS;
283 err = __dir_lookup (startdir, file_name, flags, mode,
284 &doretry, retryname, result);
287 weak_alias (__hurd_file_name_lookup_retry, hurd_file_name_lookup_retry)
289 error_t
290 __hurd_file_name_split (file_t crdir, file_t cwdir,
291 const char *file_name,
292 file_t *dir, char **name)
294 const char *lastslash;
295 error_t err;
297 lastslash = strrchr (file_name, '/');
298 if (lastslash != NULL)
300 if (lastslash == file_name)
302 /* "/foobar" => crdir + "foobar". */
303 *name = (char *) file_name + 1;
304 if (err = __mach_port_mod_refs (__mach_task_self (),
305 crdir, MACH_PORT_RIGHT_SEND, +1))
306 return err;
307 *dir = crdir;
308 return 0;
310 else
312 /* "/dir1/dir2/.../file". */
313 char dirname[lastslash - file_name + 1];
314 memcpy (dirname, file_name, lastslash - file_name);
315 dirname[lastslash - file_name] = '\0';
316 *name = (char *) lastslash + 1;
317 return __hurd_file_name_lookup (crdir, cwdir, dirname, 0, 0, dir);
320 else
322 /* "foobar" => cwdir + "foobar". */
323 *name = (char *) file_name;
324 if (err = __mach_port_mod_refs (__mach_task_self (),
325 cwdir, MACH_PORT_RIGHT_SEND, +1))
326 return err;
327 *dir = cwdir;
328 return 0;
331 weak_alias (__hurd_file_name_split, hurd_file_name_split)
334 file_t
335 __file_name_lookup (const char *file_name, int flags, mode_t mode)
337 error_t err;
338 file_t result, crdir, cwdir;
339 struct hurd_userlink crdir_ulink, cwdir_ulink;
341 crdir = _hurd_port_get (&_hurd_ports[INIT_PORT_CRDIR], &crdir_ulink);
342 cwdir = _hurd_port_get (&_hurd_ports[INIT_PORT_CWDIR], &cwdir_ulink);
344 err = __hurd_file_name_lookup (crdir, cwdir, file_name, flags, mode,
345 &result);
347 _hurd_port_free (&_hurd_ports[INIT_PORT_CRDIR], &crdir_ulink, crdir);
348 _hurd_port_free (&_hurd_ports[INIT_PORT_CWDIR], &cwdir_ulink, cwdir);
350 if (err)
351 return __hurd_fail (err), MACH_PORT_NULL;
352 else
353 return result;
355 weak_alias (__file_name_lookup, file_name_lookup)
358 file_t
359 __file_name_split (const char *file_name, char **name)
361 error_t err;
362 file_t dir, crdir, cwdir;
363 struct hurd_userlink crdir_ulink, cwdir_ulink;
365 crdir = _hurd_port_get (&_hurd_ports[INIT_PORT_CRDIR], &crdir_ulink);
366 cwdir = _hurd_port_get (&_hurd_ports[INIT_PORT_CWDIR], &cwdir_ulink);
368 err = __hurd_file_name_split (crdir, cwdir, file_name, &dir, name);
370 _hurd_port_free (&_hurd_ports[INIT_PORT_CRDIR], &crdir_ulink, crdir);
371 _hurd_port_free (&_hurd_ports[INIT_PORT_CWDIR], &cwdir_ulink, cwdir);
373 if (err)
375 errno = err;
376 return MACH_PORT_NULL;
378 else
379 return dir;
381 weak_alias (__file_name_split, file_name_split)