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. */
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')
138 /* We got a successful translation. Now apply any open-time
139 action flags we were passed. */
140 if (flags
& O_EXLOCK
)
142 if (!err
&& (flags
& O_SHLOCK
))
144 if (!err
&& (flags
& O_TRUNC
))
145 err
= __file_set_size (*result
, 0);
148 __mach_port_deallocate (__mach_task_self (), *result
);
153 file_name
= retryname
;
156 case FS_RETRY_MAGICAL
:
157 switch (retryname
[0])
160 dirport
= INIT_PORT_CRDIR
;
161 if (*result
!= MACH_PORT_NULL
)
162 __mach_port_deallocate (__mach_task_self (), *result
);
163 file_name
= &retryname
[1];
167 if (retryname
[1] == 'd' && retryname
[2] == '/')
173 fd
= (int) strtol (&retryname
[3], &end
, 10);
174 if (end
== NULL
|| errno
|| /* Malformed number. */
175 /* Check for excess text after the number. A slash
176 is valid; it ends the component. Anything else
177 does not name a numeric file descriptor. */
178 (*end
!= '/' && *end
!= '\0'))
183 if (! get_dtable_port
)
187 *result
= (*get_dtable_port
) (fd
);
188 if (*result
== MACH_PORT_NULL
)
190 /* If the name was a proper number, but the file
191 descriptor does not exist, we return EBADF instead
204 /* Do a normal retry on the remaining components. */
206 file_name
= end
+ 1; /* Skip the slash. */
215 if (retryname
[1] == 'a' && retryname
[2] == 'c' &&
216 retryname
[3] == 'h' && retryname
[4] == 't' &&
217 retryname
[5] == 'y' && retryname
[6] == 'p' &&
221 struct host_basic_info hostinfo
;
222 mach_msg_type_number_t hostinfocnt
= HOST_BASIC_INFO_COUNT
;
224 /* XXX want client's host */
225 if (err
= __host_info (__mach_host_self (), HOST_BASIC_INFO
,
226 (natural_t
*) &hostinfo
,
229 if (hostinfocnt
!= HOST_BASIC_INFO_COUNT
)
231 p
= _itoa (hostinfo
.cpu_subtype
, &retryname
[8], 10, 0);
233 p
= _itoa (hostinfo
.cpu_type
, &retryname
[8], 10, 0);
235 abort (); /* XXX write this right if this ever happens */
237 strcpy (retryname
, p
);
245 if (retryname
[1] == 't' && retryname
[2] == 'y')
246 switch (retryname
[3])
248 error_t
opentty (file_t
*result
)
251 error_t
ctty_open (file_t port
)
253 if (port
== MACH_PORT_NULL
)
254 return ENXIO
; /* No controlling terminal. */
255 return __termctty_open_terminal (port
,
259 err
= (*use_init_port
) (INIT_PORT_CTTYID
, &ctty_open
);
261 err
= reauthenticate (*result
);
266 return opentty (result
);
268 if (err
= opentty (&startdir
))
270 strcpy (retryname
, &retryname
[4]);
289 if (startdir
!= MACH_PORT_NULL
)
291 err
= lookup (startdir
);
292 __mach_port_deallocate (__mach_task_self (), startdir
);
293 startdir
= MACH_PORT_NULL
;
296 err
= (*use_init_port
) (dirport
, &lookup
);
301 weak_alias (__hurd_file_name_lookup_retry
, hurd_file_name_lookup_retry
)
304 __hurd_file_name_split (error_t (*use_init_port
)
305 (int which
, error_t (*operate
) (file_t
)),
306 file_t (*get_dtable_port
) (int fd
),
307 const char *file_name
,
308 file_t
*dir
, char **name
)
310 error_t
addref (file_t crdir
)
313 return __mach_port_mod_refs (__mach_task_self (),
314 crdir
, MACH_PORT_RIGHT_SEND
, +1);
317 const char *lastslash
= strrchr (file_name
, '/');
319 if (lastslash
!= NULL
)
321 if (lastslash
== file_name
)
323 /* "/foobar" => crdir + "foobar". */
324 *name
= (char *) file_name
+ 1;
325 return (*use_init_port
) (INIT_PORT_CRDIR
, &addref
);
329 /* "/dir1/dir2/.../file". */
330 char dirname
[lastslash
- file_name
+ 1];
331 memcpy (dirname
, file_name
, lastslash
- file_name
);
332 dirname
[lastslash
- file_name
] = '\0';
333 *name
= (char *) lastslash
+ 1;
334 return __hurd_file_name_lookup (use_init_port
, get_dtable_port
,
340 /* "foobar" => cwdir + "foobar". */
341 *name
= (char *) file_name
;
342 return (*use_init_port
) (INIT_PORT_CWDIR
, &addref
);
345 weak_alias (__hurd_file_name_split
, hurd_file_name_split
)
349 __file_name_lookup (const char *file_name
, int flags
, mode_t mode
)
354 err
= __hurd_file_name_lookup (&_hurd_ports_use
, &__getdport
,
355 file_name
, flags
, mode
,
358 return err
? (__hurd_fail (err
), MACH_PORT_NULL
) : result
;
360 weak_alias (__file_name_lookup
, file_name_lookup
)
364 __file_name_split (const char *file_name
, char **name
)
369 err
= __hurd_file_name_split (&_hurd_ports_use
, &__getdport
,
370 file_name
, &result
, name
);
372 return err
? (__hurd_fail (err
), MACH_PORT_NULL
) : result
;
374 weak_alias (__file_name_split
, file_name_split
)
378 __file_name_lookup_under (file_t startdir
,
379 const char *file_name
, int flags
, mode_t mode
)
384 error_t
use_init_port (int which
, error_t (*operate
) (mach_port_t
))
386 return (which
== INIT_PORT_CWDIR
? (*operate
) (startdir
) :
387 _hurd_ports_use (which
, operate
));
390 err
= __hurd_file_name_lookup (&use_init_port
, &__getdport
,
391 file_name
, flags
, mode
,
394 return err
? (__hurd_fail (err
), MACH_PORT_NULL
) : result
;
396 weak_alias (__file_name_lookup_under
, file_name_lookup_under
)