1 /* Copyright (C) 1992, 1993, 1994, 1995, 1996 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. */
20 #include <hurd/lookup.h>
24 #include "stdio-common/_itoa.h"
25 #include <hurd/term.h>
28 /* Translate the error from dir_lookup into the error the user sees. */
30 lookup_error (error_t error
)
36 /* These indicate that the server does not understand dir_lookup
37 at all. If it were a directory, it would, by definition. */
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
),
48 const char *file_name
, int flags
, mode_t mode
,
52 enum retry_type doretry
;
53 char retryname
[1024]; /* XXX string_t LOSES! */
55 error_t
lookup (mach_port_t startdir
)
57 while (file_name
[0] == '/')
60 return lookup_error (__dir_lookup (startdir
, file_name
, flags
, mode
,
61 &doretry
, retryname
, result
));
64 err
= (*use_init_port
) (file_name
[0] == '/'
65 ? INIT_PORT_CRDIR
: INIT_PORT_CWDIR
,
68 err
= __hurd_file_name_lookup_retry (use_init_port
, get_dtable_port
,
69 doretry
, retryname
, flags
, mode
,
74 weak_alias (__hurd_file_name_lookup
, hurd_file_name_lookup
)
77 __hurd_file_name_lookup_retry (error_t (*use_init_port
)
78 (int which
, error_t (*operate
) (file_t
)),
79 file_t (*get_dtable_port
) (int fd
),
80 enum retry_type doretry
,
82 int flags
, mode_t mode
,
89 error_t
lookup (file_t startdir
)
91 while (file_name
[0] == '/')
94 return lookup_error (__dir_lookup (startdir
, file_name
, flags
, mode
,
95 &doretry
, retryname
, result
));
97 error_t
reauthenticate (file_t unauth
)
100 mach_port_t ref
= __mach_reply_port ();
101 error_t
reauth (auth_t auth
)
103 return __auth_user_authenticate (auth
, unauth
, ref
,
104 MACH_MSG_TYPE_MAKE_SEND
,
107 err
= __io_reauthenticate (unauth
, ref
, MACH_MSG_TYPE_MAKE_SEND
);
109 err
= (*use_init_port
) (INIT_PORT_AUTH
, &reauth
);
110 __mach_port_destroy (__mach_task_self (), ref
);
111 __mach_port_deallocate (__mach_task_self (), unauth
);
119 file_t startdir
= MACH_PORT_NULL
;
120 int dirport
= INIT_PORT_CWDIR
;
124 case FS_RETRY_REAUTH
:
125 if (err
= reauthenticate (*result
))
129 case FS_RETRY_NORMAL
:
131 if (nloops
++ >= SYMLOOP_MAX
)
135 /* An empty RETRYNAME indicates we have the final port. */
136 if (retryname
[0] == '\0' &&
137 /* If reauth'd, we must do one more retry on "" to give the new
138 translator a chance to make a new port for us. */
139 doretry
== FS_RETRY_NORMAL
)
141 /* We got a successful translation. Now apply any open-time
142 action flags we were passed. */
143 if (flags
& O_EXLOCK
)
145 if (!err
&& (flags
& O_SHLOCK
))
147 if (!err
&& (flags
& O_TRUNC
))
148 err
= __file_set_size (*result
, 0);
151 __mach_port_deallocate (__mach_task_self (), *result
);
156 file_name
= retryname
;
159 case FS_RETRY_MAGICAL
:
160 switch (retryname
[0])
163 dirport
= INIT_PORT_CRDIR
;
164 if (*result
!= MACH_PORT_NULL
)
165 __mach_port_deallocate (__mach_task_self (), *result
);
166 file_name
= &retryname
[1];
170 if (retryname
[1] == 'd' && retryname
[2] == '/')
176 fd
= (int) strtol (&retryname
[3], &end
, 10);
177 if (end
== NULL
|| errno
|| /* Malformed number. */
178 /* Check for excess text after the number. A slash
179 is valid; it ends the component. Anything else
180 does not name a numeric file descriptor. */
181 (*end
!= '/' && *end
!= '\0'))
186 if (! get_dtable_port
)
190 *result
= (*get_dtable_port
) (fd
);
191 if (*result
== MACH_PORT_NULL
)
193 /* If the name was a proper number, but the file
194 descriptor does not exist, we return EBADF instead
207 /* Do a normal retry on the remaining components. */
209 file_name
= end
+ 1; /* Skip the slash. */
218 if (retryname
[1] == 'a' && retryname
[2] == 'c' &&
219 retryname
[3] == 'h' && retryname
[4] == 't' &&
220 retryname
[5] == 'y' && retryname
[6] == 'p' &&
224 struct host_basic_info hostinfo
;
225 mach_msg_type_number_t hostinfocnt
= HOST_BASIC_INFO_COUNT
;
227 /* XXX want client's host */
228 if (err
= __host_info (__mach_host_self (), HOST_BASIC_INFO
,
229 (natural_t
*) &hostinfo
,
232 if (hostinfocnt
!= HOST_BASIC_INFO_COUNT
)
234 p
= _itoa (hostinfo
.cpu_subtype
, &retryname
[8], 10, 0);
236 p
= _itoa (hostinfo
.cpu_type
, &retryname
[8], 10, 0);
238 abort (); /* XXX write this right if this ever happens */
240 strcpy (retryname
, p
);
248 if (retryname
[1] == 't' && retryname
[2] == 'y')
249 switch (retryname
[3])
251 error_t
opentty (file_t
*result
)
254 error_t
ctty_open (file_t port
)
256 if (port
== MACH_PORT_NULL
)
257 return ENXIO
; /* No controlling terminal. */
258 return __termctty_open_terminal (port
,
262 err
= (*use_init_port
) (INIT_PORT_CTTYID
, &ctty_open
);
264 err
= reauthenticate (*result
);
269 return opentty (result
);
271 if (err
= opentty (&startdir
))
273 strcpy (retryname
, &retryname
[4]);
292 if (startdir
!= MACH_PORT_NULL
)
294 err
= lookup (startdir
);
295 __mach_port_deallocate (__mach_task_self (), startdir
);
296 startdir
= MACH_PORT_NULL
;
299 err
= (*use_init_port
) (dirport
, &lookup
);
304 weak_alias (__hurd_file_name_lookup_retry
, hurd_file_name_lookup_retry
)
307 __hurd_file_name_split (error_t (*use_init_port
)
308 (int which
, error_t (*operate
) (file_t
)),
309 file_t (*get_dtable_port
) (int fd
),
310 const char *file_name
,
311 file_t
*dir
, char **name
)
313 error_t
addref (file_t crdir
)
316 return __mach_port_mod_refs (__mach_task_self (),
317 crdir
, MACH_PORT_RIGHT_SEND
, +1);
320 const char *lastslash
= strrchr (file_name
, '/');
322 if (lastslash
!= NULL
)
324 if (lastslash
== file_name
)
326 /* "/foobar" => crdir + "foobar". */
327 *name
= (char *) file_name
+ 1;
328 return (*use_init_port
) (INIT_PORT_CRDIR
, &addref
);
332 /* "/dir1/dir2/.../file". */
333 char dirname
[lastslash
- file_name
+ 1];
334 memcpy (dirname
, file_name
, lastslash
- file_name
);
335 dirname
[lastslash
- file_name
] = '\0';
336 *name
= (char *) lastslash
+ 1;
337 return __hurd_file_name_lookup (use_init_port
, get_dtable_port
,
343 /* "foobar" => cwdir + "foobar". */
344 *name
= (char *) file_name
;
345 return (*use_init_port
) (INIT_PORT_CWDIR
, &addref
);
348 weak_alias (__hurd_file_name_split
, hurd_file_name_split
)
352 __file_name_lookup (const char *file_name
, int flags
, mode_t mode
)
357 err
= __hurd_file_name_lookup (&_hurd_ports_use
, &__getdport
,
358 file_name
, flags
, mode
& ~_hurd_umask
,
361 return err
? (__hurd_fail (err
), MACH_PORT_NULL
) : result
;
363 weak_alias (__file_name_lookup
, file_name_lookup
)
367 __file_name_split (const char *file_name
, char **name
)
372 err
= __hurd_file_name_split (&_hurd_ports_use
, &__getdport
,
373 file_name
, &result
, name
);
375 return err
? (__hurd_fail (err
), MACH_PORT_NULL
) : result
;
377 weak_alias (__file_name_split
, file_name_split
)
381 __file_name_lookup_under (file_t startdir
,
382 const char *file_name
, int flags
, mode_t mode
)
387 error_t
use_init_port (int which
, error_t (*operate
) (mach_port_t
))
389 return (which
== INIT_PORT_CWDIR
? (*operate
) (startdir
) :
390 _hurd_ports_use (which
, operate
));
393 err
= __hurd_file_name_lookup (&use_init_port
, &__getdport
,
394 file_name
, flags
, mode
& ~_hurd_umask
,
397 return err
? (__hurd_fail (err
), MACH_PORT_NULL
) : result
;
399 weak_alias (__file_name_lookup_under
, file_name_lookup_under
)