1 /* Copyright (C) 1992, 93, 94, 95, 96, 97 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 not,
16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, 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. */
158 err
= __file_set_size (*result
, 0);
161 __mach_port_deallocate (__mach_task_self (), *result
);
166 file_name
= retryname
;
169 case FS_RETRY_MAGICAL
:
170 switch (retryname
[0])
173 dirport
= INIT_PORT_CRDIR
;
174 if (*result
!= MACH_PORT_NULL
)
175 __mach_port_deallocate (__mach_task_self (), *result
);
176 file_name
= &retryname
[1];
180 if (retryname
[1] == 'd' && retryname
[2] == '/')
186 fd
= (int) strtol (&retryname
[3], &end
, 10);
187 if (end
== NULL
|| errno
|| /* Malformed number. */
188 /* Check for excess text after the number. A slash
189 is valid; it ends the component. Anything else
190 does not name a numeric file descriptor. */
191 (*end
!= '/' && *end
!= '\0'))
196 if (! get_dtable_port
)
200 *result
= (*get_dtable_port
) (fd
);
201 if (*result
== MACH_PORT_NULL
)
203 /* If the name was a proper number, but the file
204 descriptor does not exist, we return EBADF instead
217 /* Do a normal retry on the remaining components. */
219 file_name
= end
+ 1; /* Skip the slash. */
228 if (retryname
[1] == 'a' && retryname
[2] == 'c' &&
229 retryname
[3] == 'h' && retryname
[4] == 't' &&
230 retryname
[5] == 'y' && retryname
[6] == 'p' &&
234 struct host_basic_info hostinfo
;
235 mach_msg_type_number_t hostinfocnt
= HOST_BASIC_INFO_COUNT
;
237 /* XXX want client's host */
238 if (err
= __host_info (__mach_host_self (), HOST_BASIC_INFO
,
239 (natural_t
*) &hostinfo
,
242 if (hostinfocnt
!= HOST_BASIC_INFO_COUNT
)
244 p
= _itoa (hostinfo
.cpu_subtype
, &retryname
[8], 10, 0);
246 p
= _itoa (hostinfo
.cpu_type
, &retryname
[8], 10, 0);
248 abort (); /* XXX write this right if this ever happens */
250 strcpy (retryname
, p
);
258 if (retryname
[1] == 't' && retryname
[2] == 'y')
259 switch (retryname
[3])
261 error_t
opentty (file_t
*result
)
264 error_t
ctty_open (file_t port
)
266 if (port
== MACH_PORT_NULL
)
267 return ENXIO
; /* No controlling terminal. */
268 return __termctty_open_terminal (port
,
272 err
= (*use_init_port
) (INIT_PORT_CTTYID
, &ctty_open
);
274 err
= reauthenticate (*result
);
279 return opentty (result
);
281 if (err
= opentty (&startdir
))
283 strcpy (retryname
, &retryname
[4]);
302 if (startdir
!= MACH_PORT_NULL
)
304 err
= lookup_op (startdir
);
305 __mach_port_deallocate (__mach_task_self (), startdir
);
306 startdir
= MACH_PORT_NULL
;
309 err
= (*use_init_port
) (dirport
, &lookup_op
);
314 weak_alias (__hurd_file_name_lookup_retry
, hurd_file_name_lookup_retry
)
317 __hurd_file_name_split (error_t (*use_init_port
)
318 (int which
, error_t (*operate
) (file_t
)),
319 file_t (*get_dtable_port
) (int fd
),
321 (file_t dir
, char *name
, int flags
, mode_t mode
,
322 retry_type
*do_retry
, string_t retry_name
,
323 mach_port_t
*result
),
324 const char *file_name
,
325 file_t
*dir
, char **name
)
327 error_t
addref (file_t crdir
)
330 return __mach_port_mod_refs (__mach_task_self (),
331 crdir
, MACH_PORT_RIGHT_SEND
, +1);
334 const char *lastslash
= strrchr (file_name
, '/');
336 if (lastslash
!= NULL
)
338 if (lastslash
== file_name
)
340 /* "/foobar" => crdir + "foobar". */
341 *name
= (char *) file_name
+ 1;
342 return (*use_init_port
) (INIT_PORT_CRDIR
, &addref
);
346 /* "/dir1/dir2/.../file". */
347 char dirname
[lastslash
- file_name
+ 1];
348 memcpy (dirname
, file_name
, lastslash
- file_name
);
349 dirname
[lastslash
- file_name
] = '\0';
350 *name
= (char *) lastslash
+ 1;
352 __hurd_file_name_lookup (use_init_port
, get_dtable_port
, lookup
,
358 /* "foobar" => cwdir + "foobar". */
359 *name
= (char *) file_name
;
360 return (*use_init_port
) (INIT_PORT_CWDIR
, &addref
);
363 weak_alias (__hurd_file_name_split
, hurd_file_name_split
)
367 __file_name_lookup (const char *file_name
, int flags
, mode_t mode
)
372 err
= __hurd_file_name_lookup (&_hurd_ports_use
, &__getdport
, 0,
373 file_name
, flags
, mode
& ~_hurd_umask
,
376 return err
? (__hurd_fail (err
), MACH_PORT_NULL
) : result
;
378 weak_alias (__file_name_lookup
, file_name_lookup
)
382 __file_name_split (const char *file_name
, char **name
)
387 err
= __hurd_file_name_split (&_hurd_ports_use
, &__getdport
, 0,
388 file_name
, &result
, name
);
390 return err
? (__hurd_fail (err
), MACH_PORT_NULL
) : result
;
392 weak_alias (__file_name_split
, file_name_split
)
396 __file_name_lookup_under (file_t startdir
,
397 const char *file_name
, int flags
, mode_t mode
)
402 error_t
use_init_port (int which
, error_t (*operate
) (mach_port_t
))
404 return (which
== INIT_PORT_CWDIR
? (*operate
) (startdir
) :
405 _hurd_ports_use (which
, operate
));
408 err
= __hurd_file_name_lookup (&use_init_port
, &__getdport
, 0,
409 file_name
, flags
, mode
& ~_hurd_umask
,
412 return err
? (__hurd_fail (err
), MACH_PORT_NULL
) : result
;
414 weak_alias (__file_name_lookup_under
, file_name_lookup_under
)