Formerly ../hurd/hurdpath.c.~11~
[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, (char *) 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           /* We got a successful translation.  Now apply any
63              open-time action flags we were passed.  */
64           if (flags & O_EXLOCK)
65             ;                   /* XXX */
66           if (!err && (flags & O_SHLOCK))
67             ;                   /* XXX */
68           if (!err && (flags & O_TRUNC))
69             err = __file_truncate (*result, 0);
70
71           if (err)
72             __mach_port_deallocate (__mach_task_self (), *result);
73           return err;
74           
75         case FS_RETRY_REAUTH:
76           __io_reauthenticate (*result, _hurd_pid);
77           __USEPORT (AUTH, __auth_user_authenticate (port, *result, _hurd_pid,
78                                                      &newpt));
79           __mach_port_deallocate (__mach_task_self (), *result);
80           *result = newpt;
81           /* Fall through.  */
82
83         case FS_RETRY_NORMAL:
84 #ifdef SYMLINK_MAX
85           if (nloops++ >= SYMLINK_MAX)
86             return ELOOP;
87 #endif
88
89           if (retryname[0] == '/')
90             {
91               startdir = crdir;
92               dealloc_dir = 0;
93               path = retryname;
94               do
95                 ++path;
96               while (*path == '/');
97             }
98           else
99             {
100               startdir = *result;
101               dealloc_dir = 1;
102               path = retryname;
103             }
104           break;
105
106         /* case FS_RETRY_MAGICAL: XXX */
107         }
108     }
109 }
110
111 error_t
112 __hurd_path_split (file_t crdir, file_t cwdir,
113                    const char *path,
114                    file_t *dir, char **name)
115 {
116   const char *lastslash;
117   
118   /* Skip leading slashes in the pathname.  */
119   if (*path == '/')
120     {
121       while (*path == '/')
122         ++path;
123       --path;                   /* Leave on one slash.  */
124     }
125   
126   lastslash = strrchr (path, '/');
127   
128   if (lastslash != NULL)
129     {
130       if (lastslash == path)
131         {
132           /* "/foobar" => crdir + "foobar".  */
133           *name = (char *) path + 1;
134           __mach_port_mod_refs (__mach_task_self (), MACH_PORT_RIGHT_SEND,
135                                 crdir, +1);
136           *dir = crdir;
137           return 0;
138         }
139       else
140         {
141           /* "/dir1/dir2/.../file".  */
142           char dirname[lastslash - path + 1];
143           memcpy (dirname, path, lastslash - path);
144           dirname[lastslash - path] = '\0';
145           *name = (char *) lastslash + 1;
146           return __hurd_path_lookup (crdir, cwdir, dirname, 0, 0, dir);
147         }
148     }
149   else
150     {
151       /* "foobar" => cwdir + "foobar".  */
152       *name = (char *) path;
153       __mach_port_mod_refs (__mach_task_self (), MACH_PORT_RIGHT_SEND,
154                             cwdir, 1);
155       *dir = cwdir;
156       return 0;
157     }
158 }
159 \f
160 file_t
161 __path_lookup (const char *path, int flags, mode_t mode)
162 {
163   error_t err;
164   file_t result, crdir, cwdir;
165   int dealloc_crdir, dealloc_cwdir;
166
167   crdir = _hurd_port_get (&_hurd_ports[INIT_PORT_CRDIR], &dealloc_crdir);
168   cwdir = _hurd_port_get (&_hurd_ports[INIT_PORT_CWDIR], &dealloc_cwdir);
169
170   err = __hurd_path_lookup (crdir, cwdir, path, flags, mode, &result);
171
172   _hurd_port_free (&_hurd_ports[INIT_PORT_CRDIR], &dealloc_crdir, crdir);
173   _hurd_port_free (&_hurd_ports[INIT_PORT_CWDIR], &dealloc_cwdir, cwdir);
174
175   if (err)
176     {
177       errno = err;
178       return MACH_PORT_NULL;
179     }
180   else
181     return result;
182 }
183
184 file_t
185 __path_split (const char *path, char **name)
186 {
187   error_t err;
188   file_t dir, crdir, cwdir;
189   int dealloc_crdir, dealloc_cwdir;
190
191   crdir = _hurd_port_get (&_hurd_ports[INIT_PORT_CRDIR], &dealloc_crdir);
192   cwdir = _hurd_port_get (&_hurd_ports[INIT_PORT_CWDIR], &dealloc_cwdir);
193
194   err = __hurd_path_split (crdir, cwdir, path, &dir, name);
195
196   _hurd_port_free (&_hurd_ports[INIT_PORT_CRDIR], &dealloc_crdir, crdir);
197   _hurd_port_free (&_hurd_ports[INIT_PORT_CWDIR], &dealloc_cwdir, cwdir);
198
199   if (err)
200     {
201       errno = err;
202       return MACH_PORT_NULL;
203     }
204   else
205     return dir;
206 }