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