freebsd_file.c revision 1.20
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
63static const char * convert_from_freebsd_mount_type __P((int));
64
65static const char *
66convert_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
97int
98freebsd_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
137int
138freebsd_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
158int
159compat_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
175int
176freebsd_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
193int
194freebsd_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
209int
210freebsd_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
225int
226freebsd_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
243int
244freebsd_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
260int
261freebsd_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
278int
279freebsd_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
296int
297freebsd_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
313int
314freebsd_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
330int
331freebsd_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
347int
348compat_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
364int
365compat_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
381int
382freebsd_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
397int
398freebsd_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
415int
416freebsd_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
433int
434freebsd_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
458int
459freebsd_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
474int
475freebsd_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
492int
493compat_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
509int
510freebsd_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
526int
527freebsd_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
543int
544freebsd_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
559int
560freebsd_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
577int
578freebsd_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
595int
596freebsd_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
612int
613freebsd_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
629int
630freebsd_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
646int
647freebsd_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