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