]>
Commit | Line | Data |
---|---|---|
16a10468 | 1 | /* Copyright (C) 1992,1993,1994,1995,1996,1997,1999,2001,2004,2006 |
92d6708b | 2 | Free Software Foundation, Inc. |
c84142e8 | 3 | This file is part of the GNU C Library. |
28f540f4 | 4 | |
c84142e8 | 5 | The GNU C Library is free software; you can redistribute it and/or |
41bdb6e2 AJ |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
28f540f4 | 9 | |
c84142e8 UD |
10 | The GNU C Library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
41bdb6e2 | 13 | Lesser General Public License for more details. |
28f540f4 | 14 | |
41bdb6e2 AJ |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; if not, write to the Free | |
17 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | |
18 | 02111-1307 USA. */ | |
28f540f4 RM |
19 | |
20 | #include <hurd.h> | |
2948fc64 | 21 | #include <hurd/lookup.h> |
28f540f4 | 22 | #include <string.h> |
28f540f4 | 23 | #include <fcntl.h> |
28f540f4 RM |
24 | |
25 | ||
26 | /* Translate the error from dir_lookup into the error the user sees. */ | |
27 | static inline error_t | |
28 | lookup_error (error_t error) | |
29 | { | |
30 | switch (error) | |
31 | { | |
32 | case EOPNOTSUPP: | |
33 | case MIG_BAD_ID: | |
34 | /* These indicate that the server does not understand dir_lookup | |
35 | at all. If it were a directory, it would, by definition. */ | |
36 | return ENOTDIR; | |
37 | default: | |
38 | return error; | |
39 | } | |
40 | } | |
41 | ||
42 | error_t | |
2948fc64 RM |
43 | __hurd_file_name_lookup (error_t (*use_init_port) |
44 | (int which, error_t (*operate) (file_t)), | |
45 | file_t (*get_dtable_port) (int fd), | |
92ea4fec MB |
46 | error_t (*lookup) |
47 | (file_t dir, char *name, int flags, mode_t mode, | |
48 | retry_type *do_retry, string_t retry_name, | |
49 | mach_port_t *result), | |
28f540f4 RM |
50 | const char *file_name, int flags, mode_t mode, |
51 | file_t *result) | |
52 | { | |
53 | error_t err; | |
54 | enum retry_type doretry; | |
55 | char retryname[1024]; /* XXX string_t LOSES! */ | |
791cfdb7 | 56 | int startport; |
28f540f4 | 57 | |
92ea4fec | 58 | error_t lookup_op (mach_port_t startdir) |
2948fc64 | 59 | { |
92ea4fec MB |
60 | return lookup_error ((*lookup) (startdir, file_name, flags, mode, |
61 | &doretry, retryname, result)); | |
2948fc64 | 62 | } |
28f540f4 | 63 | |
92ea4fec MB |
64 | if (! lookup) |
65 | lookup = __dir_lookup; | |
66 | ||
3220cade RM |
67 | if (file_name[0] == '\0') |
68 | return ENOENT; | |
69 | ||
791cfdb7 RM |
70 | startport = (file_name[0] == '/') ? INIT_PORT_CRDIR : INIT_PORT_CWDIR; |
71 | while (file_name[0] == '/') | |
72 | file_name++; | |
73 | ||
5c7665dc | 74 | if (flags & O_NOFOLLOW) /* See lookup-retry.c about O_NOFOLLOW. */ |
791cfdb7 RM |
75 | flags |= O_NOTRANS; |
76 | ||
77 | if (flags & O_DIRECTORY) | |
78 | { | |
79 | /* The caller wants to require that the file we look up is a directory. | |
80 | We can do this without an extra RPC by appending a trailing slash | |
81 | to the file name we look up. */ | |
82 | size_t len = strlen (file_name); | |
83 | if (len == 0) | |
84 | file_name = "/"; | |
85 | else if (file_name[len - 1] != '/') | |
86 | { | |
87 | char *n = alloca (len + 2); | |
88 | memcpy (n, file_name, len); | |
89 | n[len] = '/'; | |
90 | n[len + 1] = '\0'; | |
91 | file_name = n; | |
92 | } | |
93 | } | |
94 | ||
95 | err = (*use_init_port) (startport, &lookup_op); | |
2948fc64 | 96 | if (! err) |
791cfdb7 RM |
97 | err = __hurd_file_name_lookup_retry (use_init_port, get_dtable_port, |
98 | lookup, doretry, retryname, | |
99 | flags, mode, result); | |
28f540f4 | 100 | |
2948fc64 | 101 | return err; |
28f540f4 RM |
102 | } |
103 | weak_alias (__hurd_file_name_lookup, hurd_file_name_lookup) | |
104 | ||
28f540f4 | 105 | error_t |
2948fc64 RM |
106 | __hurd_file_name_split (error_t (*use_init_port) |
107 | (int which, error_t (*operate) (file_t)), | |
108 | file_t (*get_dtable_port) (int fd), | |
92ea4fec MB |
109 | error_t (*lookup) |
110 | (file_t dir, char *name, int flags, mode_t mode, | |
111 | retry_type *do_retry, string_t retry_name, | |
112 | mach_port_t *result), | |
28f540f4 RM |
113 | const char *file_name, |
114 | file_t *dir, char **name) | |
115 | { | |
2948fc64 RM |
116 | error_t addref (file_t crdir) |
117 | { | |
118 | *dir = crdir; | |
787e4db9 | 119 | return __mach_port_mod_refs (__mach_task_self (), |
2948fc64 RM |
120 | crdir, MACH_PORT_RIGHT_SEND, +1); |
121 | } | |
122 | ||
123 | const char *lastslash = strrchr (file_name, '/'); | |
28f540f4 | 124 | |
28f540f4 RM |
125 | if (lastslash != NULL) |
126 | { | |
127 | if (lastslash == file_name) | |
128 | { | |
129 | /* "/foobar" => crdir + "foobar". */ | |
130 | *name = (char *) file_name + 1; | |
2948fc64 | 131 | return (*use_init_port) (INIT_PORT_CRDIR, &addref); |
28f540f4 RM |
132 | } |
133 | else | |
134 | { | |
135 | /* "/dir1/dir2/.../file". */ | |
136 | char dirname[lastslash - file_name + 1]; | |
137 | memcpy (dirname, file_name, lastslash - file_name); | |
138 | dirname[lastslash - file_name] = '\0'; | |
139 | *name = (char *) lastslash + 1; | |
92ea4fec MB |
140 | return |
141 | __hurd_file_name_lookup (use_init_port, get_dtable_port, lookup, | |
142 | dirname, 0, 0, dir); | |
28f540f4 RM |
143 | } |
144 | } | |
92d6708b RM |
145 | else if (file_name[0] == '\0') |
146 | return ENOENT; | |
28f540f4 RM |
147 | else |
148 | { | |
149 | /* "foobar" => cwdir + "foobar". */ | |
150 | *name = (char *) file_name; | |
2948fc64 | 151 | return (*use_init_port) (INIT_PORT_CWDIR, &addref); |
28f540f4 RM |
152 | } |
153 | } | |
154 | weak_alias (__hurd_file_name_split, hurd_file_name_split) | |
155 | ||
0bd01927 RM |
156 | /* This is the same as hurd_file_name_split, except that it ignores |
157 | trailing slashes (so *NAME is never ""). */ | |
158 | error_t | |
159 | __hurd_directory_name_split (error_t (*use_init_port) | |
160 | (int which, error_t (*operate) (file_t)), | |
161 | file_t (*get_dtable_port) (int fd), | |
162 | error_t (*lookup) | |
163 | (file_t dir, char *name, int flags, mode_t mode, | |
164 | retry_type *do_retry, string_t retry_name, | |
165 | mach_port_t *result), | |
166 | const char *file_name, | |
167 | file_t *dir, char **name) | |
168 | { | |
169 | error_t addref (file_t crdir) | |
170 | { | |
171 | *dir = crdir; | |
172 | return __mach_port_mod_refs (__mach_task_self (), | |
173 | crdir, MACH_PORT_RIGHT_SEND, +1); | |
174 | } | |
175 | ||
176 | const char *lastslash = strrchr (file_name, '/'); | |
177 | ||
178 | if (lastslash != NULL && lastslash[1] == '\0') | |
179 | { | |
180 | /* Trailing slash doesn't count. Look back further. */ | |
181 | ||
182 | /* Back up over all trailing slashes. */ | |
183 | while (lastslash > file_name && *lastslash == '/') | |
184 | --lastslash; | |
185 | ||
186 | /* Find the last one earlier in the string, before the trailing ones. */ | |
0bd01927 | 187 | lastslash = __memrchr (file_name, '/', lastslash - file_name); |
0bd01927 RM |
188 | } |
189 | ||
190 | if (lastslash != NULL) | |
191 | { | |
192 | if (lastslash == file_name) | |
193 | { | |
194 | /* "/foobar" => crdir + "foobar". */ | |
195 | *name = (char *) file_name + 1; | |
196 | return (*use_init_port) (INIT_PORT_CRDIR, &addref); | |
197 | } | |
198 | else | |
199 | { | |
200 | /* "/dir1/dir2/.../file". */ | |
201 | char dirname[lastslash - file_name + 1]; | |
202 | memcpy (dirname, file_name, lastslash - file_name); | |
203 | dirname[lastslash - file_name] = '\0'; | |
204 | *name = (char *) lastslash + 1; | |
205 | return | |
206 | __hurd_file_name_lookup (use_init_port, get_dtable_port, lookup, | |
207 | dirname, 0, 0, dir); | |
208 | } | |
209 | } | |
92d6708b RM |
210 | else if (file_name[0] == '\0') |
211 | return ENOENT; | |
0bd01927 RM |
212 | else |
213 | { | |
214 | /* "foobar" => cwdir + "foobar". */ | |
215 | *name = (char *) file_name; | |
216 | return (*use_init_port) (INIT_PORT_CWDIR, &addref); | |
217 | } | |
218 | } | |
219 | weak_alias (__hurd_directory_name_split, hurd_directory_name_split) | |
220 | ||
28f540f4 RM |
221 | \f |
222 | file_t | |
223 | __file_name_lookup (const char *file_name, int flags, mode_t mode) | |
224 | { | |
225 | error_t err; | |
2948fc64 | 226 | file_t result; |
28f540f4 | 227 | |
92ea4fec | 228 | err = __hurd_file_name_lookup (&_hurd_ports_use, &__getdport, 0, |
dc825f85 | 229 | file_name, flags, mode & ~_hurd_umask, |
28f540f4 RM |
230 | &result); |
231 | ||
2948fc64 | 232 | return err ? (__hurd_fail (err), MACH_PORT_NULL) : result; |
28f540f4 RM |
233 | } |
234 | weak_alias (__file_name_lookup, file_name_lookup) | |
235 | ||
236 | ||
237 | file_t | |
238 | __file_name_split (const char *file_name, char **name) | |
239 | { | |
240 | error_t err; | |
2948fc64 RM |
241 | file_t result; |
242 | ||
92ea4fec | 243 | err = __hurd_file_name_split (&_hurd_ports_use, &__getdport, 0, |
2948fc64 | 244 | file_name, &result, name); |
28f540f4 | 245 | |
2948fc64 RM |
246 | return err ? (__hurd_fail (err), MACH_PORT_NULL) : result; |
247 | } | |
248 | weak_alias (__file_name_split, file_name_split) | |
28f540f4 | 249 | |
0bd01927 RM |
250 | file_t |
251 | __directory_name_split (const char *directory_name, char **name) | |
252 | { | |
253 | error_t err; | |
254 | file_t result; | |
255 | ||
256 | err = __hurd_directory_name_split (&_hurd_ports_use, &__getdport, 0, | |
257 | directory_name, &result, name); | |
258 | ||
259 | return err ? (__hurd_fail (err), MACH_PORT_NULL) : result; | |
260 | } | |
261 | weak_alias (__directory_name_split, directory_name_split) | |
262 | ||
28f540f4 | 263 | |
2948fc64 RM |
264 | file_t |
265 | __file_name_lookup_under (file_t startdir, | |
266 | const char *file_name, int flags, mode_t mode) | |
267 | { | |
268 | error_t err; | |
269 | file_t result; | |
28f540f4 | 270 | |
2948fc64 | 271 | error_t use_init_port (int which, error_t (*operate) (mach_port_t)) |
28f540f4 | 272 | { |
2948fc64 RM |
273 | return (which == INIT_PORT_CWDIR ? (*operate) (startdir) : |
274 | _hurd_ports_use (which, operate)); | |
28f540f4 | 275 | } |
2948fc64 | 276 | |
92ea4fec | 277 | err = __hurd_file_name_lookup (&use_init_port, &__getdport, 0, |
dc825f85 | 278 | file_name, flags, mode & ~_hurd_umask, |
2948fc64 RM |
279 | &result); |
280 | ||
281 | return err ? (__hurd_fail (err), MACH_PORT_NULL) : result; | |
28f540f4 | 282 | } |
2948fc64 | 283 | weak_alias (__file_name_lookup_under, file_name_lookup_under) |