freebsd_file.c revision 1.14
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
59static const char * convert_from_freebsd_mount_type __P((int));
60
61static const char *
62convert_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
93int
94freebsd_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
132int
133freebsd_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
152int
153compat_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
168int
169freebsd_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
185int
186freebsd_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
200int
201freebsd_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
215int
216freebsd_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
232int
233freebsd_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
248int
249freebsd_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
265int
266freebsd_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
282int
283freebsd_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
298int
299freebsd_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
314int
315freebsd_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
330int
331compat_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
346int
347compat_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
362int
363freebsd_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
377int
378freebsd_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
394int
395freebsd_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
411int
412freebsd_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
435int
436freebsd_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
450int
451freebsd_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
467int
468compat_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
483int
484freebsd_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
499int
500freebsd_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
515int
516freebsd_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
530int
531freebsd_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
547int
548freebsd_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
564int
565freebsd_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
580int
581freebsd_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
596int
597freebsd_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
612int
613freebsd_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