Formerly ../hurd/hurdpath.c.~8~
[kopensolaris-gnu/glibc.git] / hurd / hurdlookup.c
1 /* Copyright (C) 1992, 1993 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
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.
8
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.
13
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.  */
18
19 #include <hurd.h>
20 #include <string.h>
21 #include <limits.h>
22
23 error_t
24 __hurd_path_lookup (file_t crdir, file_t cwdir,
25                     const char *path, int flags, mode_t mode,
26                     file_t *result)
27 {
28   error_t err;
29   file_t startdir;
30
31   enum retry_type doretry;
32   char retryname[1024];         /* XXX string_t LOSES! */
33   file_t newpt;
34   int dealloc_dir;
35   int nloops;
36
37   if (*path == '/')
38     {
39       startdir = crdir;
40       while (*path == '/')
41         ++path;
42     }
43   else
44     startdir = cwdir;
45
46   dealloc_dir = 0;
47   nloops = 0;
48   
49   for (;;)
50     {
51       err = __dir_pathtrans (startdir, path, flags, mode,
52                              &doretry, retryname, result);
53
54       if (dealloc_dir)
55         __mach_port_deallocate (__mach_task_self (), startdir);
56       if (err)
57         return err;
58
59       switch (doretry)
60         {
61         case FS_RETRY_NONE:
62           return 0;
63           
64         case FS_RETRY_REAUTH:
65           __io_reauthenticate (*result);
66           __USEPORT (AUTH, __auth_user_authenticate (port, *result, &newpt));
67           __mach_port_deallocate (__mach_task_self (), *result);
68           *result = newpt;
69           /* Fall through.  */
70
71         case FS_RETRY_NORMAL:
72 #ifdef SYMLINK_MAX
73           if (nloops++ >= SYMLINK_MAX)
74             return ELOOP;
75 #endif
76
77           if (retryname[0] == '/')
78             {
79               startdir = crdir;
80               dealloc_dir = 0;
81               path = retryname;
82               do
83                 ++path;
84               while (*path == '/');
85             }
86           else
87             {
88               startdir = *result;
89               dealloc_dir = 1;
90               path = retryname;
91             }
92
93         /* case FS_RETRY_MAGICAL: XXX */
94         }
95     }
96 }
97
98 error_t
99 __hurd_path_split (file_t crdir, file_t cwdir,
100                    const char *path,
101                    file_t *dir, char **name)
102 {
103   const char *lastslash;
104   
105   /* Skip leading slashes in the pathname.  */
106   if (*path == '/')
107     {
108       while (*path == '/')
109         ++path;
110       --path;                   /* Leave on one slash.  */
111     }
112   
113   lastslash = strrchr (path, '/');
114   
115   if (lastslash != NULL)
116     {
117       if (lastslash == path)
118         {
119           /* "/foobar" => crdir + "foobar".  */
120           *name = (char *) path + 1;
121           __mach_port_mod_refs (__mach_task_self (), MACH_PORT_RIGHT_SEND,
122                                 crdir, +1);
123           *dir = crdir;
124           return 0;
125         }
126       else
127         {
128           /* "/dir1/dir2/.../file".  */
129           char dirname[lastslash - path + 1];
130           memcpy (dirname, path, lastslash - path);
131           dirname[lastslash - path] = '\0';
132           *name = (char *) lastslash + 1;
133           return __hurd_path_lookup (crdir, cwdir, dirname, 0, 0, dir);
134         }
135     }
136   else
137     {
138       /* "foobar" => cwdir + "foobar".  */
139       *name = (char *) path;
140       __mach_port_mod_refs (__mach_task_self (), MACH_PORT_RIGHT_SEND,
141                             cwdir, 1);
142       *dir = cwdir;
143       return 0;
144     }
145 }
146 \f
147 file_t
148 __path_lookup (const char *path, int flags, mode_t mode)
149 {
150   error_t err;
151   file_t result, crdir, cwdir;
152   int dealloc_crdir, dealloc_cwdir;
153
154   crdir = _hurd_port_get (&_hurd_ports[INIT_PORT_CRDIR], &dealloc_crdir);
155   cwdir = _hurd_port_get (&_hurd_ports[INIT_PORT_CWDIR], &dealloc_cwdir);
156
157   err = __hurd_path_lookup (crdir, cwdir, path, flags, mode, &result);
158
159   _hurd_port_free (&_hurd_ports[INIT_PORT_CRDIR], &dealloc_crdir, crdir);
160   _hurd_port_free (&_hurd_ports[INIT_PORT_CWDIR], &dealloc_cwdir, cwdir);
161
162   if (err)
163     {
164       errno = err;
165       return MACH_PORT_NULL;
166     }
167   else
168     return result;
169 }
170
171 file_t
172 __path_split (const char *path, char **name)
173 {
174   error_t err;
175   file_t dir, crdir, cwdir;
176   int dealloc_crdir, dealloc_cwdir;
177
178   crdir = _hurd_port_get (&_hurd_ports[INIT_PORT_CRDIR], &dealloc_crdir);
179   cwdir = _hurd_port_get (&_hurd_ports[INIT_PORT_CWDIR], &dealloc_cwdir);
180
181   err = __hurd_path_split (crdir, cwdir, path, &dir, name);
182
183   _hurd_port_free (&_hurd_ports[INIT_PORT_CRDIR], &dealloc_crdir, crdir);
184   _hurd_port_free (&_hurd_ports[INIT_PORT_CWDIR], &dealloc_cwdir, cwdir);
185
186   if (err)
187     {
188       errno = err;
189       return MACH_PORT_NULL;
190     }
191   else
192     return dir;
193 }