freebsd_file.c revision 1.16
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
62static const char * convert_from_freebsd_mount_type __P((int));
63
64static const char *
65convert_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
96int
97freebsd_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
135int
136freebsd_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
155int
156compat_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
171int
172freebsd_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
188int
189freebsd_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
203int
204freebsd_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
218int
219freebsd_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
235int
236freebsd_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
251int
252freebsd_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
268int
269freebsd_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
285int
286freebsd_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
301int
302freebsd_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
317int
318freebsd_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
333int
334compat_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
349int
350compat_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
365int
366freebsd_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
380int
381freebsd_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
397int
398freebsd_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
414int
415freebsd_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
438int
439freebsd_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
453int
454freebsd_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
470int
471compat_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
486int
487freebsd_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
502int
503freebsd_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
518int
519freebsd_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
533int
534freebsd_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
550int
551freebsd_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
567int
568freebsd_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
583int
584freebsd_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
599int
600freebsd_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
615int
616freebsd_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