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