xref: /netbsd/sys/compat/freebsd/freebsd_file.c (revision bf9ec67e)
1 /*	$NetBSD: freebsd_file.c,v 1.16 2002/03/16 20:43:50 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.16 2002/03/16 20:43:50 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/syscallargs.h>
56 
57 #include <compat/freebsd/freebsd_syscallargs.h>
58 #include <compat/common/compat_util.h>
59 
60 #define	ARRAY_LENGTH(array)	(sizeof(array)/sizeof(array[0]))
61 
62 static const char * convert_from_freebsd_mount_type __P((int));
63 
64 static const char *
65 convert_from_freebsd_mount_type(type)
66 	int type;
67 {
68 	static const char * const netbsd_mount_type[] = {
69 		NULL,     /*  0 = MOUNT_NONE */
70 		"ffs",	  /*  1 = "Fast" Filesystem */
71 		"nfs",	  /*  2 = Network Filesystem */
72 		"mfs",	  /*  3 = Memory Filesystem */
73 		"msdos",  /*  4 = MSDOS Filesystem */
74 		"lfs",	  /*  5 = Log-based Filesystem */
75 		"lofs",	  /*  6 = Loopback filesystem */
76 		"fdesc",  /*  7 = File Descriptor Filesystem */
77 		"portal", /*  8 = Portal Filesystem */
78 		"null",	  /*  9 = Minimal Filesystem Layer */
79 		"umap",	  /* 10 = User/Group Identifier Remapping Filesystem */
80 		"kernfs", /* 11 = Kernel Information Filesystem */
81 		"procfs", /* 12 = /proc Filesystem */
82 		"afs",	  /* 13 = Andrew Filesystem */
83 		"cd9660", /* 14 = ISO9660 (aka CDROM) Filesystem */
84 		"union",  /* 15 = Union (translucent) Filesystem */
85 		NULL,     /* 16 = "devfs" - existing device Filesystem */
86 #if 0 /* These filesystems don't exist in FreeBSD */
87 		"adosfs", /* ?? = AmigaDOS Filesystem */
88 #endif
89 	};
90 
91 	if (type < 0 || type >= ARRAY_LENGTH(netbsd_mount_type))
92 		return (NULL);
93 	return (netbsd_mount_type[type]);
94 }
95 
96 int
97 freebsd_sys_mount(p, v, retval)
98 	struct proc *p;
99 	void *v;
100 	register_t *retval;
101 {
102 	struct freebsd_sys_mount_args /* {
103 		syscallarg(int) type;
104 		syscallarg(char *) path;
105 		syscallarg(int) flags;
106 		syscallarg(caddr_t) data;
107 	} */ *uap = v;
108 	int error;
109 	const char *type;
110 	char *s;
111 	caddr_t sg = stackgap_init(p, 0);
112 	struct sys_mount_args bma;
113 
114 	if ((type = convert_from_freebsd_mount_type(SCARG(uap, type))) == NULL)
115 		return ENODEV;
116 	s = stackgap_alloc(p, &sg, MFSNAMELEN + 1);
117 	if ((error = copyout(type, s, strlen(type) + 1)) != 0)
118 		return error;
119 	SCARG(&bma, type) = s;
120 	CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
121 	SCARG(&bma, path) = SCARG(uap, path);
122 	SCARG(&bma, flags) = SCARG(uap, flags);
123 	SCARG(&bma, data) = SCARG(uap, data);
124 	return sys_mount(p, &bma, retval);
125 }
126 
127 /*
128  * The following syscalls are only here because of the alternate path check.
129  */
130 
131 /* XXX - UNIX domain: int freebsd_sys_bind(int s, caddr_t name, int namelen); */
132 /* XXX - UNIX domain: int freebsd_sys_connect(int s, caddr_t name, int namelen); */
133 
134 
135 int
136 freebsd_sys_open(p, v, retval)
137 	struct proc *p;
138 	void *v;
139 	register_t *retval;
140 {
141 	struct freebsd_sys_open_args /* {
142 		syscallarg(char *) path;
143 		syscallarg(int) flags;
144 		syscallarg(int) mode;
145 	} */ *uap = v;
146 	caddr_t sg = stackgap_init(p, 0);
147 
148 	if (SCARG(uap, flags) & O_CREAT)
149 		CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
150 	else
151 		CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
152 	return sys_open(p, uap, retval);
153 }
154 
155 int
156 compat_43_freebsd_sys_creat(p, v, retval)
157 	struct proc *p;
158 	void *v;
159 	register_t *retval;
160 {
161 	struct compat_43_freebsd_sys_creat_args /* {
162 		syscallarg(char *) path;
163 		syscallarg(int) mode;
164 	} */ *uap = v;
165 	caddr_t sg  = stackgap_init(p, 0);
166 
167 	CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
168 	return compat_43_sys_creat(p, uap, retval);
169 }
170 
171 int
172 freebsd_sys_link(p, v, retval)
173 	struct proc *p;
174 	void *v;
175 	register_t *retval;
176 {
177 	struct freebsd_sys_link_args /* {
178 		syscallarg(char *) path;
179 		syscallarg(char *) link;
180 	} */ *uap = v;
181 	caddr_t sg = stackgap_init(p, 0);
182 
183 	CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
184 	CHECK_ALT_CREAT(p, &sg, SCARG(uap, link));
185 	return sys_link(p, uap, retval);
186 }
187 
188 int
189 freebsd_sys_unlink(p, v, retval)
190 	struct proc *p;
191 	void *v;
192 	register_t *retval;
193 {
194 	struct freebsd_sys_unlink_args /* {
195 		syscallarg(char *) path;
196 	} */ *uap = v;
197 	caddr_t sg = stackgap_init(p, 0);
198 
199 	CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
200 	return sys_unlink(p, uap, retval);
201 }
202 
203 int
204 freebsd_sys_chdir(p, v, retval)
205 	struct proc *p;
206 	void *v;
207 	register_t *retval;
208 {
209 	struct freebsd_sys_chdir_args /* {
210 		syscallarg(char *) path;
211 	} */ *uap = v;
212 	caddr_t sg = stackgap_init(p, 0);
213 
214 	CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
215 	return sys_chdir(p, uap, retval);
216 }
217 
218 int
219 freebsd_sys_mknod(p, v, retval)
220 	struct proc *p;
221 	void *v;
222 	register_t *retval;
223 {
224 	struct freebsd_sys_mknod_args /* {
225 		syscallarg(char *) path;
226 		syscallarg(int) mode;
227 		syscallarg(int) dev;
228 	} */ *uap = v;
229 	caddr_t sg = stackgap_init(p, 0);
230 
231 	CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
232 	return sys_mknod(p, uap, retval);
233 }
234 
235 int
236 freebsd_sys_chmod(p, v, retval)
237 	struct proc *p;
238 	void *v;
239 	register_t *retval;
240 {
241 	struct freebsd_sys_chmod_args /* {
242 		syscallarg(char *) path;
243 		syscallarg(int) mode;
244 	} */ *uap = v;
245 	caddr_t sg = stackgap_init(p, 0);
246 
247 	CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
248 	return sys_chmod(p, uap, retval);
249 }
250 
251 int
252 freebsd_sys_chown(p, v, retval)
253 	struct proc *p;
254 	void *v;
255 	register_t *retval;
256 {
257 	struct freebsd_sys_chown_args /* {
258 		syscallarg(char *) path;
259 		syscallarg(int) uid;
260 		syscallarg(int) gid;
261 	} */ *uap = v;
262 	caddr_t sg = stackgap_init(p, 0);
263 
264 	CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
265 	return sys_chown(p, uap, retval);
266 }
267 
268 int
269 freebsd_sys_lchown(p, v, retval)
270 	struct proc *p;
271 	void *v;
272 	register_t *retval;
273 {
274 	struct freebsd_sys_lchown_args /* {
275 		syscallarg(char *) path;
276 		syscallarg(int) uid;
277 		syscallarg(int) gid;
278 	} */ *uap = v;
279 	caddr_t sg = stackgap_init(p, 0);
280 
281 	CHECK_ALT_SYMLINK(p, &sg, SCARG(uap, path));
282 	return sys_lchown(p, uap, retval);
283 }
284 
285 int
286 freebsd_sys_unmount(p, v, retval)
287 	struct proc *p;
288 	void *v;
289 	register_t *retval;
290 {
291 	struct freebsd_sys_unmount_args /* {
292 		syscallarg(char *) path;
293 		syscallarg(int) flags;
294 	} */ *uap = v;
295 	caddr_t sg = stackgap_init(p, 0);
296 
297 	CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
298 	return sys_unmount(p, uap, retval);
299 }
300 
301 int
302 freebsd_sys_access(p, v, retval)
303 	struct proc *p;
304 	void *v;
305 	register_t *retval;
306 {
307 	struct freebsd_sys_access_args /* {
308 		syscallarg(char *) path;
309 		syscallarg(int) flags;
310 	} */ *uap = v;
311 	caddr_t sg = stackgap_init(p, 0);
312 
313 	CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
314 	return sys_access(p, uap, retval);
315 }
316 
317 int
318 freebsd_sys_chflags(p, v, retval)
319 	struct proc *p;
320 	void *v;
321 	register_t *retval;
322 {
323 	struct freebsd_sys_chflags_args /* {
324 		syscallarg(char *) path;
325 		syscallarg(int) flags;
326 	} */ *uap = v;
327 	caddr_t sg = stackgap_init(p, 0);
328 
329 	CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
330 	return sys_chflags(p, uap, retval);
331 }
332 
333 int
334 compat_43_freebsd_sys_stat(p, v, retval)
335 	struct proc *p;
336 	void *v;
337 	register_t *retval;
338 {
339 	struct compat_43_freebsd_sys_stat_args /* {
340 		syscallarg(char *) path;
341 		syscallarg(struct stat43 *) ub;
342 	} */ *uap = v;
343 	caddr_t sg = stackgap_init(p, 0);
344 
345 	CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
346 	return compat_43_sys_stat(p, uap, retval);
347 }
348 
349 int
350 compat_43_freebsd_sys_lstat(p, v, retval)
351 	struct proc *p;
352 	void *v;
353 	register_t *retval;
354 {
355 	struct compat_43_freebsd_sys_lstat_args /* {
356 		syscallarg(char *) path;
357 		syscallarg(struct stat43 *) ub;
358 	} */ *uap = v;
359 	caddr_t sg = stackgap_init(p, 0);
360 
361 	CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
362 	return compat_43_sys_lstat(p, uap, retval);
363 }
364 
365 int
366 freebsd_sys_revoke(p, v, retval)
367 	struct proc *p;
368 	void *v;
369 	register_t *retval;
370 {
371 	struct freebsd_sys_revoke_args /* {
372 		syscallarg(char *) path;
373 	} */ *uap = v;
374 	caddr_t sg = stackgap_init(p, 0);
375 
376 	CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
377 	return sys_revoke(p, uap, retval);
378 }
379 
380 int
381 freebsd_sys_symlink(p, v, retval)
382 	struct proc *p;
383 	void *v;
384 	register_t *retval;
385 {
386 	struct freebsd_sys_symlink_args /* {
387 		syscallarg(char *) path;
388 		syscallarg(char *) link;
389 	} */ *uap = v;
390 	caddr_t sg = stackgap_init(p, 0);
391 
392 	CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
393 	CHECK_ALT_CREAT(p, &sg, SCARG(uap, link));
394 	return sys_symlink(p, uap, retval);
395 }
396 
397 int
398 freebsd_sys_readlink(p, v, retval)
399 	struct proc *p;
400 	void *v;
401 	register_t *retval;
402 {
403 	struct freebsd_sys_readlink_args /* {
404 		syscallarg(char *) path;
405 		syscallarg(char *) buf;
406 		syscallarg(int) count;
407 	} */ *uap = v;
408 	caddr_t sg = stackgap_init(p, 0);
409 
410 	CHECK_ALT_SYMLINK(p, &sg, SCARG(uap, path));
411 	return sys_readlink(p, uap, retval);
412 }
413 
414 int
415 freebsd_sys_execve(p, v, retval)
416 	struct proc *p;
417 	void *v;
418 	register_t *retval;
419 {
420 	struct freebsd_sys_execve_args /* {
421 		syscallarg(char *) path;
422 		syscallarg(char **) argp;
423 		syscallarg(char **) envp;
424 	} */ *uap = v;
425 	struct sys_execve_args ap;
426 	caddr_t sg;
427 
428 	sg = stackgap_init(p, 0);
429 	CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
430 
431 	SCARG(&ap, path) = SCARG(uap, path);
432 	SCARG(&ap, argp) = SCARG(uap, argp);
433 	SCARG(&ap, envp) = SCARG(uap, envp);
434 
435 	return sys_execve(p, &ap, retval);
436 }
437 
438 int
439 freebsd_sys_chroot(p, v, retval)
440 	struct proc *p;
441 	void *v;
442 	register_t *retval;
443 {
444 	struct freebsd_sys_chroot_args /* {
445 		syscallarg(char *) path;
446 	} */ *uap = v;
447 	caddr_t sg = stackgap_init(p, 0);
448 
449 	CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
450 	return sys_chroot(p, uap, retval);
451 }
452 
453 int
454 freebsd_sys_rename(p, v, retval)
455 	struct proc *p;
456 	void *v;
457 	register_t *retval;
458 {
459 	struct freebsd_sys_rename_args /* {
460 		syscallarg(char *) from;
461 		syscallarg(char *) to;
462 	} */ *uap = v;
463 	caddr_t sg = stackgap_init(p, 0);
464 
465 	CHECK_ALT_EXIST(p, &sg, SCARG(uap, from));
466 	CHECK_ALT_CREAT(p, &sg, SCARG(uap, to));
467 	return sys_rename(p, uap, retval);
468 }
469 
470 int
471 compat_43_freebsd_sys_truncate(p, v, retval)
472 	struct proc *p;
473 	void *v;
474 	register_t *retval;
475 {
476 	struct compat_43_freebsd_sys_truncate_args /* {
477 		syscallarg(char *) path;
478 		syscallarg(long) length;
479 	} */ *uap = v;
480 	caddr_t sg = stackgap_init(p, 0);
481 
482 	CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
483 	return compat_43_sys_truncate(p, uap, retval);
484 }
485 
486 int
487 freebsd_sys_mkfifo(p, v, retval)
488 	struct proc *p;
489 	void *v;
490 	register_t *retval;
491 {
492 	struct freebsd_sys_mkfifo_args /* {
493 		syscallarg(char *) path;
494 		syscallarg(int) mode;
495 	} */ *uap = v;
496 	caddr_t sg = stackgap_init(p, 0);
497 
498 	CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
499 	return sys_mkfifo(p, uap, retval);
500 }
501 
502 int
503 freebsd_sys_mkdir(p, v, retval)
504 	struct proc *p;
505 	void *v;
506 	register_t *retval;
507 {
508 	struct freebsd_sys_mkdir_args /* {
509 		syscallarg(char *) path;
510 		syscallarg(int) mode;
511 	} */ *uap = v;
512 	caddr_t sg = stackgap_init(p, 0);
513 
514 	CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
515 	return sys_mkdir(p, uap, retval);
516 }
517 
518 int
519 freebsd_sys_rmdir(p, v, retval)
520 	struct proc *p;
521 	void *v;
522 	register_t *retval;
523 {
524 	struct freebsd_sys_rmdir_args /* {
525 		syscallarg(char *) path;
526 	} */ *uap = v;
527 	caddr_t sg = stackgap_init(p, 0);
528 
529 	CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
530 	return sys_rmdir(p, uap, retval);
531 }
532 
533 int
534 freebsd_sys_statfs(p, v, retval)
535 	struct proc *p;
536 	void *v;
537 	register_t *retval;
538 {
539 	struct freebsd_sys_stat_args /* {
540 		syscallarg(char *) path;
541 		syscallarg(struct statfs *) buf;
542 	} */ *uap = v;
543 	caddr_t sg = stackgap_init(p, 0);
544 
545 	CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
546 	return sys_statfs(p, uap, retval);
547 }
548 
549 #ifdef NFS
550 int
551 freebsd_sys_getfh(p, v, retval)
552 	struct proc *p;
553 	void *v;
554 	register_t *retval;
555 {
556 	struct freebsd_sys_getfh_args /* {
557 		syscallarg(char *) fname;
558 		syscallarg(fhandle_t *) fhp;
559 	} */ *uap = v;
560 	caddr_t sg = stackgap_init(p, 0);
561 
562 	CHECK_ALT_EXIST(p, &sg, SCARG(uap, fname));
563 	return sys_getfh(p, uap, retval);
564 }
565 #endif /* NFS */
566 
567 int
568 freebsd_sys_stat(p, v, retval)
569 	struct proc *p;
570 	void *v;
571 	register_t *retval;
572 {
573 	struct freebsd_sys_stat_args /* {
574 		syscallarg(char *) path;
575 		syscallarg(struct stat12 *) ub;
576 	} */ *uap = v;
577 	caddr_t sg = stackgap_init(p, 0);
578 
579 	CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
580 	return compat_12_sys_stat(p, uap, retval);
581 }
582 
583 int
584 freebsd_sys_lstat(p, v, retval)
585 	struct proc *p;
586 	void *v;
587 	register_t *retval;
588 {
589 	struct freebsd_sys_lstat_args /* {
590 		syscallarg(char *) path;
591 		syscallarg(struct stat12 *) ub;
592 	} */ *uap = v;
593 	caddr_t sg = stackgap_init(p, 0);
594 
595 	CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
596 	return compat_12_sys_lstat(p, uap, retval);
597 }
598 
599 int
600 freebsd_sys_pathconf(p, v, retval)
601 	struct proc *p;
602 	void *v;
603 	register_t *retval;
604 {
605 	struct freebsd_sys_pathconf_args /* {
606 		syscallarg(char *) path;
607 		syscallarg(int) name;
608 	} */ *uap = v;
609 	caddr_t sg = stackgap_init(p, 0);
610 
611 	CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
612 	return sys_pathconf(p, uap, retval);
613 }
614 
615 int
616 freebsd_sys_truncate(p, v, retval)
617 	struct proc *p;
618 	void *v;
619 	register_t *retval;
620 {
621 	struct freebsd_sys_truncate_args /* {
622 		syscallarg(char *) path;
623 		syscallarg(int) pad;
624 		syscallarg(off_t) length;
625 	} */ *uap = v;
626 	caddr_t sg = stackgap_init(p, 0);
627 
628 	CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
629 	return sys_truncate(p, uap, retval);
630 }
631