Libinfo-173.tar.gz
[apple/libinfo.git] / lookup.subproj / lu_fstab.c
1 /*
2 * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /*
26 * fstab entry lookup
27 * Copyright (C) 1989 by NeXT, Inc.
28 */
29
30 #include <stdlib.h>
31 #include <mach/mach.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <rpc/types.h>
35 #include <rpc/xdr.h>
36 #include <fstab.h>
37 #include <pthread.h>
38
39 #include "lookup.h"
40 #include "_lu_types.h"
41 #include "lu_utils.h"
42 #include "lu_overrides.h"
43
44 static pthread_mutex_t _fstab_lock = PTHREAD_MUTEX_INITIALIZER;
45
46 #define FS_GET_SPEC 1
47 #define FS_GET_FILE 2
48 #define FS_GET_ENT 3
49
50 static void
51 free_fstab_data(struct fstab *f)
52 {
53 if (f == NULL) return;
54
55 if (f->fs_spec != NULL) free(f->fs_spec);
56 if (f->fs_file != NULL) free(f->fs_file);
57 if (f->fs_vfstype != NULL) free(f->fs_vfstype);
58 if (f->fs_mntops != NULL) free(f->fs_mntops);
59 if (f->fs_type != NULL) free(f->fs_type);
60 }
61
62 static void
63 free_fstab(struct fstab *f)
64 {
65 if (f == NULL) return;
66 free_fstab_data(f);
67 free(f);
68 }
69
70 static void
71 free_lu_thread_info_fstab(void *x)
72 {
73 struct lu_thread_info *tdata;
74
75 if (x == NULL) return;
76
77 tdata = (struct lu_thread_info *)x;
78
79 if (tdata->lu_entry != NULL)
80 {
81 free_fstab((struct fstab *)tdata->lu_entry);
82 tdata->lu_entry = NULL;
83 }
84
85 _lu_data_free_vm_xdr(tdata);
86
87 free(tdata);
88 }
89
90 static struct fstab *
91 extract_fstab(XDR *xdr)
92 {
93 int i, j, nkeys, nvals, status;
94 char *key, **vals;
95 struct fstab *f;
96
97 if (xdr == NULL) return NULL;
98
99 if (!xdr_int(xdr, &nkeys)) return NULL;
100
101 f = (struct fstab *)calloc(1, sizeof(struct fstab));
102
103 for (i = 0; i < nkeys; i++)
104 {
105 key = NULL;
106 vals = NULL;
107 nvals = 0;
108
109 status = _lu_xdr_attribute(xdr, &key, &vals, &nvals);
110 if (status < 0)
111 {
112 free_fstab(f);
113 return NULL;
114 }
115
116 if (nvals == 0)
117 {
118 free(key);
119 continue;
120 }
121
122 j = 0;
123
124 if ((f->fs_spec == NULL) && (!strcmp("name", key)))
125 {
126 f->fs_spec = vals[0];
127 j = 1;
128 }
129 else if ((f->fs_file == NULL) && (!strcmp("dir", key)))
130 {
131 f->fs_file = vals[0];
132 j = 1;
133 }
134 else if ((f->fs_vfstype == NULL) && (!strcmp("vfstype", key)))
135 {
136 f->fs_vfstype = vals[0];
137 j = 1;
138 }
139 else if ((f->fs_mntops == NULL) && (!strcmp("opts", key)))
140 {
141 f->fs_mntops = vals[0];
142 j = 1;
143 }
144 else if ((f->fs_type == NULL) && (!strcmp("type", key)))
145 {
146 f->fs_type = vals[0];
147 j = 1;
148 }
149 else if (!strcmp("freq", key))
150 {
151 f->fs_freq = atoi(vals[0]);
152 }
153 else if (!strcmp("passno", key))
154 {
155 f->fs_passno = atoi(vals[0]);
156 }
157
158 free(key);
159 if (vals != NULL)
160 {
161 for (; j < nvals; j++) free(vals[j]);
162 free(vals);
163 }
164 }
165
166 if (f->fs_spec == NULL) f->fs_spec = strdup("");
167 if (f->fs_file == NULL) f->fs_file = strdup("");
168 if (f->fs_vfstype == NULL) f->fs_vfstype = strdup("");
169 if (f->fs_mntops == NULL) f->fs_mntops = strdup("");
170 if (f->fs_type == NULL) f->fs_type = strdup("");
171
172 return f;
173 }
174
175 static struct fstab *
176 copy_fstab(struct fstab *in)
177 {
178 struct fstab *f;
179
180 if (in == NULL) return NULL;
181
182 f = (struct fstab *)calloc(1, sizeof(struct fstab));
183
184 f->fs_spec = LU_COPY_STRING(in->fs_spec);
185 f->fs_file = LU_COPY_STRING(in->fs_file);
186 f->fs_vfstype = LU_COPY_STRING(in->fs_vfstype);
187 f->fs_mntops = LU_COPY_STRING(in->fs_mntops);
188 f->fs_type = LU_COPY_STRING(in->fs_type);
189
190 f->fs_freq = in->fs_freq;
191 f->fs_passno = in->fs_passno;
192
193 return f;
194 }
195
196 static void
197 recycle_fstab(struct lu_thread_info *tdata, struct fstab *in)
198 {
199 struct fstab *f;
200
201 if (tdata == NULL) return;
202 f = (struct fstab *)tdata->lu_entry;
203
204 if (in == NULL)
205 {
206 free_fstab(f);
207 tdata->lu_entry = NULL;
208 }
209
210 if (tdata->lu_entry == NULL)
211 {
212 tdata->lu_entry = in;
213 return;
214 }
215
216 free_fstab_data(f);
217
218 f->fs_spec = in->fs_spec;
219 f->fs_file = in->fs_file;
220 f->fs_vfstype = in->fs_vfstype;
221 f->fs_mntops = in->fs_mntops;
222 f->fs_type = in->fs_type;
223 f->fs_freq = in->fs_freq;
224 f->fs_passno = in->fs_passno;
225
226 free(in);
227 }
228
229 static struct fstab *
230 lu_getfsspec(const char *name)
231 {
232 struct fstab *f;
233 unsigned datalen;
234 char namebuf[_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT];
235 XDR outxdr;
236 XDR inxdr;
237 static int proc = -1;
238 char *lookup_buf;
239 int count;
240
241 if (proc < 0)
242 {
243 if (_lookup_link(_lu_port, "getfsbyname", &proc) != KERN_SUCCESS)
244 {
245 return NULL;
246 }
247 }
248
249 xdrmem_create(&outxdr, namebuf, sizeof(namebuf), XDR_ENCODE);
250 if (!xdr__lu_string(&outxdr, (_lu_string *)&name))
251 {
252 xdr_destroy(&outxdr);
253 return NULL;
254 }
255
256 datalen = 0;
257 lookup_buf = NULL;
258
259 if (_lookup_all(_lu_port, proc, (unit *)namebuf, xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, &lookup_buf, &datalen)
260 != KERN_SUCCESS)
261 {
262 xdr_destroy(&outxdr);
263 return NULL;
264 }
265
266 xdr_destroy(&outxdr);
267
268 datalen *= BYTES_PER_XDR_UNIT;
269 if ((lookup_buf == NULL) || (datalen == 0)) return NULL;
270
271 xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE);
272
273 count = 0;
274 if (!xdr_int(&inxdr, &count))
275 {
276 xdr_destroy(&inxdr);
277 vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
278 return NULL;
279 }
280
281 if (count == 0)
282 {
283 xdr_destroy(&inxdr);
284 vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
285 return NULL;
286 }
287
288 f = extract_fstab(&inxdr);
289 xdr_destroy(&inxdr);
290 vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
291
292 return f;
293 }
294
295 static void
296 lu_endfsent(void)
297 {
298 struct lu_thread_info *tdata;
299
300 tdata = _lu_data_create_key(_lu_data_key_fstab, free_lu_thread_info_fstab);
301 _lu_data_free_vm_xdr(tdata);
302 }
303
304 static int
305 lu_setfsent(void)
306 {
307 lu_endfsent();
308 return 1;
309 }
310
311 static struct fstab *
312 lu_getfsent()
313 {
314 static int proc = -1;
315 struct lu_thread_info *tdata;
316 struct fstab *f;
317
318 tdata = _lu_data_create_key(_lu_data_key_fstab, free_lu_thread_info_fstab);
319 if (tdata == NULL)
320 {
321 tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
322 _lu_data_set_key(_lu_data_key_fstab, tdata);
323 }
324
325 if (tdata->lu_vm == NULL)
326 {
327 if (proc < 0)
328 {
329 if (_lookup_link(_lu_port, "getfsent", &proc) != KERN_SUCCESS)
330 {
331 lu_endfsent();
332 return NULL;
333 }
334 }
335
336 if (_lookup_all(_lu_port, proc, NULL, 0, &(tdata->lu_vm), &(tdata->lu_vm_length)) != KERN_SUCCESS)
337 {
338 lu_endfsent();
339 return NULL;
340 }
341
342 /* mig stubs measure size in words (4 bytes) */
343 tdata->lu_vm_length *= 4;
344
345 if (tdata->lu_xdr != NULL)
346 {
347 xdr_destroy(tdata->lu_xdr);
348 free(tdata->lu_xdr);
349 }
350 tdata->lu_xdr = (XDR *)calloc(1, sizeof(XDR));
351
352 xdrmem_create(tdata->lu_xdr, tdata->lu_vm, tdata->lu_vm_length, XDR_DECODE);
353 if (!xdr_int(tdata->lu_xdr, &tdata->lu_vm_cursor))
354 {
355 lu_endfsent();
356 return NULL;
357 }
358 }
359
360 if (tdata->lu_vm_cursor == 0)
361 {
362 lu_endfsent();
363 return NULL;
364 }
365
366 f = extract_fstab(tdata->lu_xdr);
367 if (f == NULL)
368 {
369 lu_endfsent();
370 return NULL;
371 }
372
373 tdata->lu_vm_cursor--;
374
375 return f;
376 }
377
378 static struct fstab *
379 lu_getfsfile(const char *name)
380 {
381 struct fstab *fs;
382
383 if (name == NULL) return (struct fstab *)NULL;
384
385 setfsent();
386 for (fs = lu_getfsent(); fs != NULL; fs = lu_getfsent())
387 if (!strcmp(fs->fs_file, name)) return fs;
388
389 endfsent();
390 return (struct fstab *)NULL;
391 }
392
393 static struct fstab *
394 getfs(const char *spec, const char *file, int source)
395 {
396 struct fstab *res = NULL;
397 struct lu_thread_info *tdata;
398
399 tdata = _lu_data_create_key(_lu_data_key_fstab, free_lu_thread_info_fstab);
400 if (tdata == NULL)
401 {
402 tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
403 _lu_data_set_key(_lu_data_key_fstab, tdata);
404 }
405
406 if (_lu_running())
407 {
408 switch (source)
409 {
410 case FS_GET_SPEC:
411 res = lu_getfsspec(spec);
412 break;
413 case FS_GET_FILE:
414 res = lu_getfsfile(file);
415 break;
416 case FS_GET_ENT:
417 res = lu_getfsent();
418 break;
419 default: res = NULL;
420 }
421 }
422 else
423 {
424 pthread_mutex_lock(&_fstab_lock);
425 switch (source)
426 {
427 case FS_GET_SPEC:
428 res = copy_fstab(_old_getfsspec(spec));
429 break;
430 case FS_GET_FILE:
431 res = copy_fstab(_old_getfsfile(file));
432 break;
433 case FS_GET_ENT:
434 res = copy_fstab(_old_getfsent());
435 break;
436 default: res = NULL;
437 }
438 pthread_mutex_unlock(&_fstab_lock);
439 }
440
441 recycle_fstab(tdata, res);
442 return (struct fstab *)tdata->lu_entry;
443 }
444
445
446 struct fstab *
447 getfsbyname(const char *name)
448 {
449 return getfs(name, NULL, FS_GET_SPEC);
450 }
451
452 struct fstab *
453 getfsspec(const char *name)
454 {
455 return getfs(name, NULL, FS_GET_SPEC);
456 }
457
458 struct fstab *
459 getfsfile(const char *name)
460 {
461 return getfs(NULL, name, FS_GET_FILE);
462 }
463
464 struct fstab *
465 getfsent(void)
466 {
467 return getfs(NULL, NULL, FS_GET_ENT);
468 }
469
470 int
471 setfsent(void)
472 {
473 if (_lu_running()) return (lu_setfsent());
474 return (_old_setfsent());
475 }
476
477 void
478 endfsent(void)
479 {
480 if (_lu_running()) lu_endfsent();
481 else _old_endfsent();
482 }
483