1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21: #include <hurd.h>
22: #include <hurd/lookup.h>
23: #include <hurd/term.h>
24: #include <hurd/paths.h>
25: #include <limits.h>
26: #include <fcntl.h>
27: #include <string.h>
28: #include "stdio-common/_itoa.h"
29:
30:
31: static inline error_t
32: lookup_error (error_t error)
33: {
34: switch (error)
35: {
36: case EOPNOTSUPP:
37: case MIG_BAD_ID:
38:
39:
40: return ENOTDIR;
41: default:
42: return error;
43: }
44: }
45:
46: error_t
47: __hurd_file_name_lookup_retry (error_t (*use_init_port)
48: (int which, error_t (*operate) (file_t)),
49: file_t (*get_dtable_port) (int fd),
50: error_t (*lookup)
51: (file_t dir, char *name,
52: int flags, mode_t mode,
53: retry_type *do_retry, string_t retry_name,
54: mach_port_t *result),
55: enum retry_type doretry,
56: char retryname[1024],
57: int flags, mode_t mode,
58: file_t *result)
59: {
60: error_t err;
61: char *file_name;
62: int nloops;
63:
64: error_t lookup_op (file_t startdir)
65: {
66: while (file_name[0] == '/')
67: file_name++;
68:
69: return lookup_error ((*lookup) (startdir, file_name, flags, mode,
70: &doretry, retryname, result));
71: }
72: error_t reauthenticate (file_t unauth)
73: {
74: error_t err;
75: mach_port_t ref = __mach_reply_port ();
76: error_t reauth (auth_t auth)
77: {
78: return __auth_user_authenticate (auth, ref,
79: MACH_MSG_TYPE_MAKE_SEND,
80: result);
81: }
82: err = __io_reauthenticate (unauth, ref, MACH_MSG_TYPE_MAKE_SEND);
83: if (! err)
84: err = (*use_init_port) (INIT_PORT_AUTH, &reauth);
85: __mach_port_destroy (__mach_task_self (), ref);
86: __mach_port_deallocate (__mach_task_self (), unauth);
87: return err;
88: }
89:
90: if (! lookup)
91: lookup = __dir_lookup;
92:
93: nloops = 0;
94: err = 0;
95: do
96: {
97: file_t startdir = MACH_PORT_NULL;
98: int dirport = INIT_PORT_CWDIR;
99:
100: switch (doretry)
101: {
102: case FS_RETRY_REAUTH:
103: if (err = reauthenticate (*result))
104: return err;
105:
106:
107: case FS_RETRY_NORMAL:
108: if (nloops++ >= SYMLOOP_MAX)
109: {
110: __mach_port_deallocate (__mach_task_self (), *result);
111: return ELOOP;
112: }
113:
114:
115: if (retryname[0] == '\0' &&
116:
117:
118: doretry == FS_RETRY_NORMAL)
119: {
120: if (flags & O_NOFOLLOW)
121: {
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140: struct stat64 st;
141: err = __io_stat (*result, &st);
142: if (!err
143: && (st.st_mode & (S_IPTRANS|S_IATRANS)))
144: {
145: if (st.st_uid != 0)
146: err = ENOENT;
147: else if (st.st_mode & S_IPTRANS)
148: {
149: char buf[1024];
150: char *trans = buf;
151: size_t translen = sizeof buf;
152: err = __file_get_translator (*result,
153: &trans, &translen);
154: if (!err
155: && translen > sizeof _HURD_SYMLINK
156: && !memcmp (trans,
157: _HURD_SYMLINK, sizeof _HURD_SYMLINK))
158: err = ENOENT;
159: }
160: }
161: }
162:
163:
164:
165:
166: if (!err && (flags & O_TRUNC))
167: err = __file_set_size (*result, 0);
168:
169: if (err)
170: __mach_port_deallocate (__mach_task_self (), *result);
171: return err;
172: }
173:
174: startdir = *result;
175: file_name = retryname;
176: break;
177:
178: case FS_RETRY_MAGICAL:
179: switch (retryname[0])
180: {
181: case '/':
182: dirport = INIT_PORT_CRDIR;
183: if (*result != MACH_PORT_NULL)
184: __mach_port_deallocate (__mach_task_self (), *result);
185: if (nloops++ >= SYMLOOP_MAX)
186: return ELOOP;
187: file_name = &retryname[1];
188: break;
189:
190: case 'f':
191: if (retryname[1] == 'd' && retryname[2] == '/')
192: {
193: int fd;
194: char *end;
195: int save = errno;
196: errno = 0;
197: fd = (int) strtoul (&retryname[3], &end, 10);
198: if (end == NULL || errno ||
199:
200:
201:
202: (*end != '/' && *end != '\0'))
203: {
204: errno = save;
205: return ENOENT;
206: }
207: if (! get_dtable_port)
208: err = EGRATUITOUS;
209: else
210: {
211: *result = (*get_dtable_port) (fd);
212: if (*result == MACH_PORT_NULL)
213: {
214:
215:
216:
217: err = errno;
218: errno = save;
219: }
220: }
221: errno = save;
222: if (err)
223: return err;
224: if (*end == '\0')
225: return 0;
226: else
227: {
228:
229: startdir = *result;
230: file_name = end + 1;
231: break;
232: }
233: }
234: else
235: goto bad_magic;
236: break;
237:
238: case 'm':
239: if (retryname[1] == 'a' && retryname[2] == 'c' &&
240: retryname[3] == 'h' && retryname[4] == 't' &&
241: retryname[5] == 'y' && retryname[6] == 'p' &&
242: retryname[7] == 'e')
243: {
244: error_t err;
245: struct host_basic_info hostinfo;
246: mach_msg_type_number_t hostinfocnt = HOST_BASIC_INFO_COUNT;
247: char *p;
248:
249: if (err = __host_info (__mach_host_self (), HOST_BASIC_INFO,
250: (integer_t *) &hostinfo,
251: &hostinfocnt))
252: return err;
253: if (hostinfocnt != HOST_BASIC_INFO_COUNT)
254: return EGRATUITOUS;
255: p = _itoa (hostinfo.cpu_subtype, &retryname[8], 10, 0);
256: *--p = '/';
257: p = _itoa (hostinfo.cpu_type, &retryname[8], 10, 0);
258: if (p < retryname)
259: abort ();
260: if (p > retryname)
261: strcpy (retryname, p);
262: startdir = *result;
263: }
264: else
265: goto bad_magic;
266: break;
267:
268: case 't':
269: if (retryname[1] == 't' && retryname[2] == 'y')
270: switch (retryname[3])
271: {
272: error_t opentty (file_t *result)
273: {
274: error_t err;
275: error_t ctty_open (file_t port)
276: {
277: if (port == MACH_PORT_NULL)
278: return ENXIO;
279: return __termctty_open_terminal (port,
280: flags,
281: result);
282: }
283: err = (*use_init_port) (INIT_PORT_CTTYID, &ctty_open);
284: if (! err)
285: err = reauthenticate (*result);
286: return err;
287: }
288:
289: case '\0':
290: return opentty (result);
291: case '/':
292: if (err = opentty (&startdir))
293: return err;
294: strcpy (retryname, &retryname[4]);
295: break;
296: default:
297: goto bad_magic;
298: }
299: else
300: goto bad_magic;
301: break;
302:
303: default:
304: bad_magic:
305: return EGRATUITOUS;
306: }
307: break;
308:
309: default:
310: return EGRATUITOUS;
311: }
312:
313: if (startdir != MACH_PORT_NULL)
314: {
315: err = lookup_op (startdir);
316: __mach_port_deallocate (__mach_task_self (), startdir);
317: startdir = MACH_PORT_NULL;
318: }
319: else
320: err = (*use_init_port) (dirport, &lookup_op);
321: } while (! err);
322:
323: return err;
324: }
325: weak_alias (__hurd_file_name_lookup_retry, hurd_file_name_lookup_retry)