xref: /netbsd-src/sys/compat/freebsd/freebsd_file.c (revision 23c8222edbfb0f0932d88a8351d3a0cf817dfb9e)
1 /*	$NetBSD: freebsd_file.c,v 1.20 2004/04/21 01:05:36 christos 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 2004/04/21 01:05:36 christos 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(p, &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(p, &sg, SCARG(uap, path));
153 	else
154 		CHECK_ALT_EXIST(p, &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(p, &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(p, &sg, SCARG(uap, path));
189 	CHECK_ALT_CREAT(p, &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(p, &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(p, &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(p, &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(p, &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(p, &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(p, &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(p, &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(p, &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(p, &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(p, &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(p, &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(p, &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(p, &sg, SCARG(uap, path));
411 	CHECK_ALT_CREAT(p, &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(p, &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(p, &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(p, &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(p, &sg, SCARG(uap, from));
488 	CHECK_ALT_CREAT(p, &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(p, &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(p, &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(p, &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(p, &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(p, &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(p, &sg, SCARG(uap, fname));
591 	return 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(p, &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(p, &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(p, &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(p, &sg, SCARG(uap, path));
661 	return sys_truncate(l, uap, retval);
662 }
663