Initial revision
[kopensolaris-gnu/glibc.git] / hurd / hurdlookup.c
1 /* Copyright (C) 1991 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 file_t
24 __hurd_path_lookup (const char *path, int flags, mode_t mode)
25 {
26   error_t err;
27   file_t startdir, result;
28
29   if (*path == '/')
30     {
31       startdir = _hurd_crdir;
32       while (*path == '/')
33         ++path;
34     }
35   else
36     startdir = _hurd_cwdir;
37
38   err = __dir_lookup (startdir, path, flags, mode, &result);
39   if (err)
40     {
41       errno = __hurd_errno (err);
42       return MACH_PORT_NULL;
43     }
44   return result;
45 }
46
47 error_t
48 __dir_lookup (file_t startdir, const char *path, int flags, mode_t mode,
49               file_t *result)
50 {
51   enum retry_type doretry;
52   char retryname[PATH_MAX];
53   size_t retrynamelen;
54   file_t newpt;
55   size_t pathlen;
56   int dealloc_dir;
57   int nloops;
58
59   dealloc_dir = 0;
60   nloops = 0;
61   pathlen = strlen (path) + 1;
62   
63   for (;;)
64     {
65       err = __dir_pathtrans (startdir, path, pathlen, flags, mode,
66                              &doretry, retryname, &retrynamelen, &result);
67
68       if (dealloc_dir)
69         __mach_port_deallocate (__mach_task_self (), startdir);
70       if (err)
71         return err;
72
73       switch (doretry)
74         {
75         case FS_RETRY_NONE:
76           return POSIX_SUCCESS;
77           
78         case FS_RETRY_REAUTH:
79           __io_reauthenticate (*result);
80           __auth_user_authenticate (_hurd_auth, result, &newpt);
81           __mach_port_deallocate (__mach_task_self (), *result);
82           *result = newpt;
83           /* Fall through.  */
84
85         case FS_RETRY_NORMAL:
86           if (nloops++ >= MAXSYMLINKS)
87             return POSIX_ELOOP;
88
89           if (*retryname == '/')
90             {
91               startdir = _hurd_crdir;
92               dealloc_dir = 0;
93               path = retryname;
94               pathlen = retrynamelen;
95               while (*path == '/')
96                 {
97                   ++path;
98                   --pathlen;
99                 }
100             }
101           else
102             {
103               startdir = *result;
104               dealloc_dir = 1;
105               path = retryname;
106               pathlen = retrynamelen;
107             }
108         }
109     }
110 }
111
112 file_t
113 __hurd_path_split (const char *path, const char **name)
114 {
115   const char *lastslash;
116   
117   /* Skip leading slashes in the pathname.  */
118   if (*path == '/')
119     {
120       while (*path == '/')
121         ++path;
122       --path;                   /* Leave on one slash.  */
123     }
124   
125   lastslash = strrchr (path, '/');
126   
127   if (lastslash != NULL)
128     {
129       if (lastslash == path)
130         {
131           *name = path;
132           __mach_port_mod_refs (__mach_task_self (), _hurd_crdir,
133                                 MACH_PORT_RIGHT_SEND, 1);
134           return _hurd_crdir;
135         }
136       else
137         {
138           char dirname[lastslash - path + 1];
139           memcpy (dirname, path, lastslash - path);
140           dirname[lastslath - path] = '\0';
141           *name = lastslash + 1;
142           return __hurd_path_lookup (dirname, 0, 0);
143         }
144     }
145   else
146     {
147       *name = path;
148       __mach_port_mod_refs (__mach_task_self (), _hurd_cwdir,
149                             MACH_PORT_RIGHT_SEND, 1);
150       return _hurd_cwdir;
151     }
152 }