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