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