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
),
49 (file_t dir
, char *name
, int flags
, mode_t mode
,
50 retry_type
*do_retry
, string_t retry_name
,
52 const char *file_name
, int flags
, mode_t mode
,
56 enum retry_type doretry
;
57 char retryname
[1024]; /* XXX string_t LOSES! */
59 error_t
lookup_op (mach_port_t startdir
)
61 while (file_name
[0] == '/')
64 return lookup_error ((*lookup
) (startdir
, file_name
, flags
, mode
,
65 &doretry
, retryname
, result
));
69 lookup
= __dir_lookup
;
71 err
= (*use_init_port
) (file_name
[0] == '/'
72 ? INIT_PORT_CRDIR
: INIT_PORT_CWDIR
,
75 err
= __hurd_file_name_lookup_retry (use_init_port
, get_dtable_port
, lookup
,
76 doretry
, retryname
, flags
, mode
,
81 weak_alias (__hurd_file_name_lookup
, hurd_file_name_lookup
)
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
),
88 (file_t dir
, char *name
, int flags
, mode_t mode
,
89 retry_type
*do_retry
, string_t retry_name
,
91 enum retry_type doretry
,
93 int flags
, mode_t mode
,
100 error_t
lookup_op (file_t startdir
)
102 while (file_name
[0] == '/')
105 return lookup_error ((*lookup
) (startdir
, file_name
, flags
, mode
,
106 &doretry
, retryname
, result
));
108 error_t
reauthenticate (file_t unauth
)
111 mach_port_t ref
= __mach_reply_port ();
112 error_t
reauth (auth_t auth
)
114 return __auth_user_authenticate (auth
, ref
,
115 MACH_MSG_TYPE_MAKE_SEND
,
118 err
= __io_reauthenticate (unauth
, ref
, MACH_MSG_TYPE_MAKE_SEND
);
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
);
127 lookup
= __dir_lookup
;
133 file_t startdir
= MACH_PORT_NULL
;
134 int dirport
= INIT_PORT_CWDIR
;
138 case FS_RETRY_REAUTH
:
139 if (err
= reauthenticate (*result
))
143 case FS_RETRY_NORMAL
:
145 if (nloops
++ >= SYMLOOP_MAX
)
149 /* An empty RETRYNAME indicates we have the final port. */
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
)
155 /* We got a successful translation. Now apply any open-time
156 action flags we were passed. */
157 if (flags
& O_EXLOCK
)
159 if (!err
&& (flags
& O_SHLOCK
))
161 if (!err
&& (flags
& O_TRUNC
))
162 err
= __file_set_size (*result
, 0);
165 __mach_port_deallocate (__mach_task_self (), *result
);
170 file_name
= retryname
;
173 case FS_RETRY_MAGICAL
:
174 switch (retryname
[0])
177 dirport
= INIT_PORT_CRDIR
;
178 if (*result
!= MACH_PORT_NULL
)
179 __mach_port_deallocate (__mach_task_self (), *result
);
180 file_name
= &retryname
[1];
184 if (retryname
[1] == 'd' && retryname
[2] == '/')
190 fd
= (int) strtol (&retryname
[3], &end
, 10);
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'))
200 if (! get_dtable_port
)
204 *result
= (*get_dtable_port
) (fd
);
205 if (*result
== MACH_PORT_NULL
)
207 /* If the name was a proper number, but the file
208 descriptor does not exist, we return EBADF instead
221 /* Do a normal retry on the remaining components. */
223 file_name
= end
+ 1; /* Skip the slash. */
232 if (retryname
[1] == 'a' && retryname
[2] == 'c' &&
233 retryname
[3] == 'h' && retryname
[4] == 't' &&
234 retryname
[5] == 'y' && retryname
[6] == 'p' &&
238 struct host_basic_info hostinfo
;
239 mach_msg_type_number_t hostinfocnt
= HOST_BASIC_INFO_COUNT
;
241 /* XXX want client's host */
242 if (err
= __host_info (__mach_host_self (), HOST_BASIC_INFO
,
243 (natural_t
*) &hostinfo
,
246 if (hostinfocnt
!= HOST_BASIC_INFO_COUNT
)
248 p
= _itoa (hostinfo
.cpu_subtype
, &retryname
[8], 10, 0);
250 p
= _itoa (hostinfo
.cpu_type
, &retryname
[8], 10, 0);
252 abort (); /* XXX write this right if this ever happens */
254 strcpy (retryname
, p
);
262 if (retryname
[1] == 't' && retryname
[2] == 'y')
263 switch (retryname
[3])
265 error_t
opentty (file_t
*result
)
268 error_t
ctty_open (file_t port
)
270 if (port
== MACH_PORT_NULL
)
271 return ENXIO
; /* No controlling terminal. */
272 return __termctty_open_terminal (port
,
276 err
= (*use_init_port
) (INIT_PORT_CTTYID
, &ctty_open
);
278 err
= reauthenticate (*result
);
283 return opentty (result
);
285 if (err
= opentty (&startdir
))
287 strcpy (retryname
, &retryname
[4]);
306 if (startdir
!= MACH_PORT_NULL
)
308 err
= lookup_op (startdir
);
309 __mach_port_deallocate (__mach_task_self (), startdir
);
310 startdir
= MACH_PORT_NULL
;
313 err
= (*use_init_port
) (dirport
, &lookup_op
);
318 weak_alias (__hurd_file_name_lookup_retry
, hurd_file_name_lookup_retry
)
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
),
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
),
328 const char *file_name
,
329 file_t
*dir
, char **name
)
331 error_t
addref (file_t crdir
)
334 return __mach_port_mod_refs (__mach_task_self (),
335 crdir
, MACH_PORT_RIGHT_SEND
, +1);
338 const char *lastslash
= strrchr (file_name
, '/');
340 if (lastslash
!= NULL
)
342 if (lastslash
== file_name
)
344 /* "/foobar" => crdir + "foobar". */
345 *name
= (char *) file_name
+ 1;
346 return (*use_init_port
) (INIT_PORT_CRDIR
, &addref
);
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;
356 __hurd_file_name_lookup (use_init_port
, get_dtable_port
, lookup
,
362 /* "foobar" => cwdir + "foobar". */
363 *name
= (char *) file_name
;
364 return (*use_init_port
) (INIT_PORT_CWDIR
, &addref
);
367 weak_alias (__hurd_file_name_split
, hurd_file_name_split
)
371 __file_name_lookup (const char *file_name
, int flags
, mode_t mode
)
376 err
= __hurd_file_name_lookup (&_hurd_ports_use
, &__getdport
, 0,
377 file_name
, flags
, mode
& ~_hurd_umask
,
380 return err
? (__hurd_fail (err
), MACH_PORT_NULL
) : result
;
382 weak_alias (__file_name_lookup
, file_name_lookup
)
386 __file_name_split (const char *file_name
, char **name
)
391 err
= __hurd_file_name_split (&_hurd_ports_use
, &__getdport
, 0,
392 file_name
, &result
, name
);
394 return err
? (__hurd_fail (err
), MACH_PORT_NULL
) : result
;
396 weak_alias (__file_name_split
, file_name_split
)
400 __file_name_lookup_under (file_t startdir
,
401 const char *file_name
, int flags
, mode_t mode
)
406 error_t
use_init_port (int which
, error_t (*operate
) (mach_port_t
))
408 return (which
== INIT_PORT_CWDIR
? (*operate
) (startdir
) :
409 _hurd_ports_use (which
, operate
));
412 err
= __hurd_file_name_lookup (&use_init_port
, &__getdport
, 0,
413 file_name
, flags
, mode
& ~_hurd_umask
,
416 return err
? (__hurd_fail (err
), MACH_PORT_NULL
) : result
;
418 weak_alias (__file_name_lookup_under
, file_name_lookup_under
)