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