freebsd_file.c revision 1.20.12.2 1 /* $NetBSD: freebsd_file.c,v 1.20.12.2 2006/12/30 20:47:32 yamt Exp $ */
2
3 /*
4 * Copyright (c) 1995 Frank van der Linden
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed for the NetBSD Project
18 * by Frank van der Linden
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * from: linux_file.c,v 1.3 1995/04/04 04:21:30 mycroft Exp
34 */
35
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: freebsd_file.c,v 1.20.12.2 2006/12/30 20:47:32 yamt Exp $");
38
39 #if defined(_KERNEL_OPT)
40 #include "fs_nfs.h"
41 #endif
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/namei.h>
46 #include <sys/proc.h>
47 #include <sys/file.h>
48 #include <sys/stat.h>
49 #include <sys/filedesc.h>
50 #include <sys/ioctl.h>
51 #include <sys/kernel.h>
52 #include <sys/mount.h>
53 #include <sys/malloc.h>
54
55 #include <sys/sa.h>
56 #include <sys/syscallargs.h>
57
58 #include <compat/freebsd/freebsd_syscallargs.h>
59 #include <compat/common/compat_util.h>
60
61 #define ARRAY_LENGTH(array) (sizeof(array)/sizeof(array[0]))
62
63 static const char * convert_from_freebsd_mount_type __P((int));
64
65 static const char *
66 convert_from_freebsd_mount_type(type)
67 int type;
68 {
69 static const char * const netbsd_mount_type[] = {
70 NULL, /* 0 = MOUNT_NONE */
71 "ffs", /* 1 = "Fast" Filesystem */
72 "nfs", /* 2 = Network Filesystem */
73 "mfs", /* 3 = Memory Filesystem */
74 "msdos", /* 4 = MSDOS Filesystem */
75 "lfs", /* 5 = Log-based Filesystem */
76 "lofs", /* 6 = Loopback filesystem */
77 "fdesc", /* 7 = File Descriptor Filesystem */
78 "portal", /* 8 = Portal Filesystem */
79 "null", /* 9 = Minimal Filesystem Layer */
80 "umap", /* 10 = User/Group Identifier Remapping Filesystem */
81 "kernfs", /* 11 = Kernel Information Filesystem */
82 "procfs", /* 12 = /proc Filesystem */
83 "afs", /* 13 = Andrew Filesystem */
84 "cd9660", /* 14 = ISO9660 (aka CDROM) Filesystem */
85 "union", /* 15 = Union (translucent) Filesystem */
86 NULL, /* 16 = "devfs" - existing device Filesystem */
87 #if 0 /* These filesystems don't exist in FreeBSD */
88 "adosfs", /* ?? = AmigaDOS Filesystem */
89 #endif
90 };
91
92 if (type < 0 || type >= ARRAY_LENGTH(netbsd_mount_type))
93 return (NULL);
94 return (netbsd_mount_type[type]);
95 }
96
97 int
98 freebsd_sys_mount(l, v, retval)
99 struct lwp *l;
100 void *v;
101 register_t *retval;
102 {
103 struct freebsd_sys_mount_args /* {
104 syscallarg(int) type;
105 syscallarg(char *) path;
106 syscallarg(int) flags;
107 syscallarg(caddr_t) data;
108 } */ *uap = v;
109 struct proc *p = l->l_proc;
110 int error;
111 const char *type;
112 char *s;
113 caddr_t sg = stackgap_init(p, 0);
114 struct sys_mount_args bma;
115
116 if ((type = convert_from_freebsd_mount_type(SCARG(uap, type))) == NULL)
117 return ENODEV;
118 s = stackgap_alloc(p, &sg, MFSNAMELEN + 1);
119 if ((error = copyout(type, s, strlen(type) + 1)) != 0)
120 return error;
121 SCARG(&bma, type) = s;
122 CHECK_ALT_EXIST(l, &sg, SCARG(uap, path));
123 SCARG(&bma, path) = SCARG(uap, path);
124 SCARG(&bma, flags) = SCARG(uap, flags);
125 SCARG(&bma, data) = SCARG(uap, data);
126 return sys_mount(l, &bma, retval);
127 }
128
129 /*
130 * The following syscalls are only here because of the alternate path check.
131 */
132
133 /* XXX - UNIX domain: int freebsd_sys_bind(int s, caddr_t name, int namelen); */
134 /* XXX - UNIX domain: int freebsd_sys_connect(int s, caddr_t name, int namelen); */
135
136
137 int
138 freebsd_sys_open(l, v, retval)
139 struct lwp *l;
140 void *v;
141 register_t *retval;
142 {
143 struct freebsd_sys_open_args /* {
144 syscallarg(char *) path;
145 syscallarg(int) flags;
146 syscallarg(int) mode;
147 } */ *uap = v;
148 struct proc *p = l->l_proc;
149 caddr_t sg = stackgap_init(p, 0);
150
151 if (SCARG(uap, flags) & O_CREAT)
152 CHECK_ALT_CREAT(l, &sg, SCARG(uap, path));
153 else
154 CHECK_ALT_EXIST(l, &sg, SCARG(uap, path));
155 return sys_open(l, uap, retval);
156 }
157
158 int
159 compat_43_freebsd_sys_creat(l, v, retval)
160 struct lwp *l;
161 void *v;
162 register_t *retval;
163 {
164 struct compat_43_freebsd_sys_creat_args /* {
165 syscallarg(char *) path;
166 syscallarg(int) mode;
167 } */ *uap = v;
168 struct proc *p = l->l_proc;
169 caddr_t sg = stackgap_init(p, 0);
170
171 CHECK_ALT_CREAT(l, &sg, SCARG(uap, path));
172 return compat_43_sys_creat(l, uap, retval);
173 }
174
175 int
176 freebsd_sys_link(l, v, retval)
177 struct lwp *l;
178 void *v;
179 register_t *retval;
180 {
181 struct freebsd_sys_link_args /* {
182 syscallarg(char *) path;
183 syscallarg(char *) link;
184 } */ *uap = v;
185 struct proc *p = l->l_proc;
186 caddr_t sg = stackgap_init(p, 0);
187
188 CHECK_ALT_EXIST(l, &sg, SCARG(uap, path));
189 CHECK_ALT_CREAT(l, &sg, SCARG(uap, link));
190 return sys_link(l, uap, retval);
191 }
192
193 int
194 freebsd_sys_unlink(l, v, retval)
195 struct lwp *l;
196 void *v;
197 register_t *retval;
198 {
199 struct freebsd_sys_unlink_args /* {
200 syscallarg(char *) path;
201 } */ *uap = v;
202 struct proc *p = l->l_proc;
203 caddr_t sg = stackgap_init(p, 0);
204
205 CHECK_ALT_EXIST(l, &sg, SCARG(uap, path));
206 return sys_unlink(l, uap, retval);
207 }
208
209 int
210 freebsd_sys_chdir(l, v, retval)
211 struct lwp *l;
212 void *v;
213 register_t *retval;
214 {
215 struct freebsd_sys_chdir_args /* {
216 syscallarg(char *) path;
217 } */ *uap = v;
218 struct proc *p = l->l_proc;
219 caddr_t sg = stackgap_init(p, 0);
220
221 CHECK_ALT_EXIST(l, &sg, SCARG(uap, path));
222 return sys_chdir(l, uap, retval);
223 }
224
225 int
226 freebsd_sys_mknod(l, v, retval)
227 struct lwp *l;
228 void *v;
229 register_t *retval;
230 {
231 struct freebsd_sys_mknod_args /* {
232 syscallarg(char *) path;
233 syscallarg(int) mode;
234 syscallarg(int) dev;
235 } */ *uap = v;
236 struct proc *p = l->l_proc;
237 caddr_t sg = stackgap_init(p, 0);
238
239 CHECK_ALT_CREAT(l, &sg, SCARG(uap, path));
240 return sys_mknod(l, uap, retval);
241 }
242
243 int
244 freebsd_sys_chmod(l, v, retval)
245 struct lwp *l;
246 void *v;
247 register_t *retval;
248 {
249 struct freebsd_sys_chmod_args /* {
250 syscallarg(char *) path;
251 syscallarg(int) mode;
252 } */ *uap = v;
253 struct proc *p = l->l_proc;
254 caddr_t sg = stackgap_init(p, 0);
255
256 CHECK_ALT_EXIST(l, &sg, SCARG(uap, path));
257 return sys_chmod(l, uap, retval);
258 }
259
260 int
261 freebsd_sys_chown(l, v, retval)
262 struct lwp *l;
263 void *v;
264 register_t *retval;
265 {
266 struct freebsd_sys_chown_args /* {
267 syscallarg(char *) path;
268 syscallarg(int) uid;
269 syscallarg(int) gid;
270 } */ *uap = v;
271 struct proc *p = l->l_proc;
272 caddr_t sg = stackgap_init(p, 0);
273
274 CHECK_ALT_EXIST(l, &sg, SCARG(uap, path));
275 return sys_chown(l, uap, retval);
276 }
277
278 int
279 freebsd_sys_lchown(l, v, retval)
280 struct lwp *l;
281 void *v;
282 register_t *retval;
283 {
284 struct freebsd_sys_lchown_args /* {
285 syscallarg(char *) path;
286 syscallarg(int) uid;
287 syscallarg(int) gid;
288 } */ *uap = v;
289 struct proc *p = l->l_proc;
290 caddr_t sg = stackgap_init(p, 0);
291
292 CHECK_ALT_SYMLINK(l, &sg, SCARG(uap, path));
293 return sys_lchown(l, uap, retval);
294 }
295
296 int
297 freebsd_sys_unmount(l, v, retval)
298 struct lwp *l;
299 void *v;
300 register_t *retval;
301 {
302 struct freebsd_sys_unmount_args /* {
303 syscallarg(char *) path;
304 syscallarg(int) flags;
305 } */ *uap = v;
306 struct proc *p = l->l_proc;
307 caddr_t sg = stackgap_init(p, 0);
308
309 CHECK_ALT_EXIST(l, &sg, SCARG(uap, path));
310 return sys_unmount(l, uap, retval);
311 }
312
313 int
314 freebsd_sys_access(l, v, retval)
315 struct lwp *l;
316 void *v;
317 register_t *retval;
318 {
319 struct freebsd_sys_access_args /* {
320 syscallarg(char *) path;
321 syscallarg(int) flags;
322 } */ *uap = v;
323 struct proc *p = l->l_proc;
324 caddr_t sg = stackgap_init(p, 0);
325
326 CHECK_ALT_EXIST(l, &sg, SCARG(uap, path));
327 return sys_access(l, uap, retval);
328 }
329
330 int
331 freebsd_sys_chflags(l, v, retval)
332 struct lwp *l;
333 void *v;
334 register_t *retval;
335 {
336 struct freebsd_sys_chflags_args /* {
337 syscallarg(char *) path;
338 syscallarg(int) flags;
339 } */ *uap = v;
340 struct proc *p = l->l_proc;
341 caddr_t sg = stackgap_init(p, 0);
342
343 CHECK_ALT_EXIST(l, &sg, SCARG(uap, path));
344 return sys_chflags(l, uap, retval);
345 }
346
347 int
348 compat_43_freebsd_sys_stat(l, v, retval)
349 struct lwp *l;
350 void *v;
351 register_t *retval;
352 {
353 struct compat_43_freebsd_sys_stat_args /* {
354 syscallarg(char *) path;
355 syscallarg(struct stat43 *) ub;
356 } */ *uap = v;
357 struct proc *p = l->l_proc;
358 caddr_t sg = stackgap_init(p, 0);
359
360 CHECK_ALT_EXIST(l, &sg, SCARG(uap, path));
361 return compat_43_sys_stat(l, uap, retval);
362 }
363
364 int
365 compat_43_freebsd_sys_lstat(l, v, retval)
366 struct lwp *l;
367 void *v;
368 register_t *retval;
369 {
370 struct compat_43_freebsd_sys_lstat_args /* {
371 syscallarg(char *) path;
372 syscallarg(struct stat43 *) ub;
373 } */ *uap = v;
374 struct proc *p = l->l_proc;
375 caddr_t sg = stackgap_init(p, 0);
376
377 CHECK_ALT_EXIST(l, &sg, SCARG(uap, path));
378 return compat_43_sys_lstat(l, uap, retval);
379 }
380
381 int
382 freebsd_sys_revoke(l, v, retval)
383 struct lwp *l;
384 void *v;
385 register_t *retval;
386 {
387 struct freebsd_sys_revoke_args /* {
388 syscallarg(char *) path;
389 } */ *uap = v;
390 struct proc *p = l->l_proc;
391 caddr_t sg = stackgap_init(p, 0);
392
393 CHECK_ALT_EXIST(l, &sg, SCARG(uap, path));
394 return sys_revoke(l, uap, retval);
395 }
396
397 int
398 freebsd_sys_symlink(l, v, retval)
399 struct lwp *l;
400 void *v;
401 register_t *retval;
402 {
403 struct freebsd_sys_symlink_args /* {
404 syscallarg(char *) path;
405 syscallarg(char *) link;
406 } */ *uap = v;
407 struct proc *p = l->l_proc;
408 caddr_t sg = stackgap_init(p, 0);
409
410 CHECK_ALT_EXIST(l, &sg, SCARG(uap, path));
411 CHECK_ALT_CREAT(l, &sg, SCARG(uap, link));
412 return sys_symlink(l, uap, retval);
413 }
414
415 int
416 freebsd_sys_readlink(l, v, retval)
417 struct lwp *l;
418 void *v;
419 register_t *retval;
420 {
421 struct freebsd_sys_readlink_args /* {
422 syscallarg(char *) path;
423 syscallarg(char *) buf;
424 syscallarg(int) count;
425 } */ *uap = v;
426 struct proc *p = l->l_proc;
427 caddr_t sg = stackgap_init(p, 0);
428
429 CHECK_ALT_SYMLINK(l, &sg, SCARG(uap, path));
430 return sys_readlink(l, uap, retval);
431 }
432
433 int
434 freebsd_sys_execve(l, v, retval)
435 struct lwp *l;
436 void *v;
437 register_t *retval;
438 {
439 struct freebsd_sys_execve_args /* {
440 syscallarg(char *) path;
441 syscallarg(char **) argp;
442 syscallarg(char **) envp;
443 } */ *uap = v;
444 struct proc *p = l->l_proc;
445 struct sys_execve_args ap;
446 caddr_t sg;
447
448 sg = stackgap_init(p, 0);
449 CHECK_ALT_EXIST(l, &sg, SCARG(uap, path));
450
451 SCARG(&ap, path) = SCARG(uap, path);
452 SCARG(&ap, argp) = SCARG(uap, argp);
453 SCARG(&ap, envp) = SCARG(uap, envp);
454
455 return sys_execve(l, &ap, retval);
456 }
457
458 int
459 freebsd_sys_chroot(l, v, retval)
460 struct lwp *l;
461 void *v;
462 register_t *retval;
463 {
464 struct freebsd_sys_chroot_args /* {
465 syscallarg(char *) path;
466 } */ *uap = v;
467 struct proc *p = l->l_proc;
468 caddr_t sg = stackgap_init(p, 0);
469
470 CHECK_ALT_EXIST(l, &sg, SCARG(uap, path));
471 return sys_chroot(l, uap, retval);
472 }
473
474 int
475 freebsd_sys_rename(l, v, retval)
476 struct lwp *l;
477 void *v;
478 register_t *retval;
479 {
480 struct freebsd_sys_rename_args /* {
481 syscallarg(char *) from;
482 syscallarg(char *) to;
483 } */ *uap = v;
484 struct proc *p = l->l_proc;
485 caddr_t sg = stackgap_init(p, 0);
486
487 CHECK_ALT_EXIST(l, &sg, SCARG(uap, from));
488 CHECK_ALT_CREAT(l, &sg, SCARG(uap, to));
489 return sys_rename(l, uap, retval);
490 }
491
492 int
493 compat_43_freebsd_sys_truncate(l, v, retval)
494 struct lwp *l;
495 void *v;
496 register_t *retval;
497 {
498 struct compat_43_freebsd_sys_truncate_args /* {
499 syscallarg(char *) path;
500 syscallarg(long) length;
501 } */ *uap = v;
502 struct proc *p = l->l_proc;
503 caddr_t sg = stackgap_init(p, 0);
504
505 CHECK_ALT_EXIST(l, &sg, SCARG(uap, path));
506 return compat_43_sys_truncate(l, uap, retval);
507 }
508
509 int
510 freebsd_sys_mkfifo(l, v, retval)
511 struct lwp *l;
512 void *v;
513 register_t *retval;
514 {
515 struct freebsd_sys_mkfifo_args /* {
516 syscallarg(char *) path;
517 syscallarg(int) mode;
518 } */ *uap = v;
519 struct proc *p = l->l_proc;
520 caddr_t sg = stackgap_init(p, 0);
521
522 CHECK_ALT_CREAT(l, &sg, SCARG(uap, path));
523 return sys_mkfifo(l, uap, retval);
524 }
525
526 int
527 freebsd_sys_mkdir(l, v, retval)
528 struct lwp *l;
529 void *v;
530 register_t *retval;
531 {
532 struct freebsd_sys_mkdir_args /* {
533 syscallarg(char *) path;
534 syscallarg(int) mode;
535 } */ *uap = v;
536 struct proc *p = l->l_proc;
537 caddr_t sg = stackgap_init(p, 0);
538
539 CHECK_ALT_CREAT(l, &sg, SCARG(uap, path));
540 return sys_mkdir(l, uap, retval);
541 }
542
543 int
544 freebsd_sys_rmdir(l, v, retval)
545 struct lwp *l;
546 void *v;
547 register_t *retval;
548 {
549 struct freebsd_sys_rmdir_args /* {
550 syscallarg(char *) path;
551 } */ *uap = v;
552 struct proc *p = l->l_proc;
553 caddr_t sg = stackgap_init(p, 0);
554
555 CHECK_ALT_EXIST(l, &sg, SCARG(uap, path));
556 return sys_rmdir(l, uap, retval);
557 }
558
559 int
560 freebsd_sys_statfs(l, v, retval)
561 struct lwp *l;
562 void *v;
563 register_t *retval;
564 {
565 struct freebsd_sys_stat_args /* {
566 syscallarg(char *) path;
567 syscallarg(struct statfs12 *) buf;
568 } */ *uap = v;
569 struct proc *p = l->l_proc;
570 caddr_t sg = stackgap_init(p, 0);
571
572 CHECK_ALT_EXIST(l, &sg, SCARG(uap, path));
573 return compat_20_sys_statfs(l, uap, retval);
574 }
575
576 #ifdef NFS
577 int
578 freebsd_sys_getfh(l, v, retval)
579 struct lwp *l;
580 void *v;
581 register_t *retval;
582 {
583 struct freebsd_sys_getfh_args /* {
584 syscallarg(char *) fname;
585 syscallarg(fhandle_t *) fhp;
586 } */ *uap = v;
587 struct proc *p = l->l_proc;
588 caddr_t sg = stackgap_init(p, 0);
589
590 CHECK_ALT_EXIST(l, &sg, SCARG(uap, fname));
591 return compat_30_sys_getfh(l, uap, retval);
592 }
593 #endif /* NFS */
594
595 int
596 freebsd_sys_stat(l, v, retval)
597 struct lwp *l;
598 void *v;
599 register_t *retval;
600 {
601 struct freebsd_sys_stat_args /* {
602 syscallarg(char *) path;
603 syscallarg(struct stat12 *) ub;
604 } */ *uap = v;
605 struct proc *p = l->l_proc;
606 caddr_t sg = stackgap_init(p, 0);
607
608 CHECK_ALT_EXIST(l, &sg, SCARG(uap, path));
609 return compat_12_sys_stat(l, uap, retval);
610 }
611
612 int
613 freebsd_sys_lstat(l, v, retval)
614 struct lwp *l;
615 void *v;
616 register_t *retval;
617 {
618 struct freebsd_sys_lstat_args /* {
619 syscallarg(char *) path;
620 syscallarg(struct stat12 *) ub;
621 } */ *uap = v;
622 struct proc *p = l->l_proc;
623 caddr_t sg = stackgap_init(p, 0);
624
625 CHECK_ALT_EXIST(l, &sg, SCARG(uap, path));
626 return compat_12_sys_lstat(l, uap, retval);
627 }
628
629 int
630 freebsd_sys_pathconf(l, v, retval)
631 struct lwp *l;
632 void *v;
633 register_t *retval;
634 {
635 struct freebsd_sys_pathconf_args /* {
636 syscallarg(char *) path;
637 syscallarg(int) name;
638 } */ *uap = v;
639 struct proc *p = l->l_proc;
640 caddr_t sg = stackgap_init(p, 0);
641
642 CHECK_ALT_EXIST(l, &sg, SCARG(uap, path));
643 return sys_pathconf(l, uap, retval);
644 }
645
646 int
647 freebsd_sys_truncate(l, v, retval)
648 struct lwp *l;
649 void *v;
650 register_t *retval;
651 {
652 struct freebsd_sys_truncate_args /* {
653 syscallarg(char *) path;
654 syscallarg(int) pad;
655 syscallarg(off_t) length;
656 } */ *uap = v;
657 struct proc *p = l->l_proc;
658 caddr_t sg = stackgap_init(p, 0);
659
660 CHECK_ALT_EXIST(l, &sg, SCARG(uap, path));
661 return sys_truncate(l, uap, retval);
662 }
663