1 /*	$OpenBSD: linux_file.c,v 1.22 2003/08/13 04:01:37 tedu Exp $	*/
2 /*	$NetBSD: linux_file.c,v 1.15 1996/05/20 01:59:09 fvdl Exp $	*/
3 
4 /*
5  * Copyright (c) 1995 Frank van der Linden
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *      This product includes software developed for the NetBSD Project
19  *      by Frank van der Linden
20  * 4. The name of the author may not be used to endorse or promote products
21  *    derived from this software without specific prior written permission
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/namei.h>
38 #include <sys/proc.h>
39 #include <sys/file.h>
40 #include <sys/stat.h>
41 #include <sys/filedesc.h>
42 #include <sys/ioctl.h>
43 #include <sys/kernel.h>
44 #include <sys/mount.h>
45 #include <sys/signalvar.h>
46 #include <sys/uio.h>
47 #include <sys/malloc.h>
48 #include <sys/vnode.h>
49 #include <sys/tty.h>
50 #include <sys/conf.h>
51 
52 #include <sys/syscallargs.h>
53 
54 #include <compat/linux/linux_types.h>
55 #include <compat/linux/linux_signal.h>
56 #include <compat/linux/linux_syscallargs.h>
57 #include <compat/linux/linux_fcntl.h>
58 #include <compat/linux/linux_util.h>
59 
60 #include <machine/linux_machdep.h>
61 
62 static int linux_to_bsd_ioflags(int);
63 static int bsd_to_linux_ioflags(int);
64 static void bsd_to_linux_flock(struct flock *, struct linux_flock *);
65 static void linux_to_bsd_flock(struct linux_flock *, struct flock *);
66 static void bsd_to_linux_stat(struct stat *, struct linux_stat *);
67 static int linux_stat1(struct proc *, void *, register_t *, int);
68 
69 
70 /*
71  * Some file-related calls are handled here. The usual flag conversion
72  * an structure conversion is done, and alternate emul path searching.
73  */
74 
75 /*
76  * The next two functions convert between the Linux and OpenBSD values
77  * of the flags used in open(2) and fcntl(2).
78  */
79 static int
linux_to_bsd_ioflags(lflags)80 linux_to_bsd_ioflags(lflags)
81 	int lflags;
82 {
83 	int res = 0;
84 
85 	res |= cvtto_bsd_mask(lflags, LINUX_O_WRONLY, O_WRONLY);
86 	res |= cvtto_bsd_mask(lflags, LINUX_O_RDONLY, O_RDONLY);
87 	res |= cvtto_bsd_mask(lflags, LINUX_O_RDWR, O_RDWR);
88 	res |= cvtto_bsd_mask(lflags, LINUX_O_CREAT, O_CREAT);
89 	res |= cvtto_bsd_mask(lflags, LINUX_O_EXCL, O_EXCL);
90 	res |= cvtto_bsd_mask(lflags, LINUX_O_NOCTTY, O_NOCTTY);
91 	res |= cvtto_bsd_mask(lflags, LINUX_O_TRUNC, O_TRUNC);
92 	res |= cvtto_bsd_mask(lflags, LINUX_O_NDELAY, O_NDELAY);
93 	res |= cvtto_bsd_mask(lflags, LINUX_O_SYNC, O_SYNC);
94 	res |= cvtto_bsd_mask(lflags, LINUX_FASYNC, O_ASYNC);
95 	res |= cvtto_bsd_mask(lflags, LINUX_O_APPEND, O_APPEND);
96 
97 	return res;
98 }
99 
100 static int
bsd_to_linux_ioflags(bflags)101 bsd_to_linux_ioflags(bflags)
102 	int bflags;
103 {
104 	int res = 0;
105 
106 	res |= cvtto_linux_mask(bflags, O_WRONLY, LINUX_O_WRONLY);
107 	res |= cvtto_linux_mask(bflags, O_RDONLY, LINUX_O_RDONLY);
108 	res |= cvtto_linux_mask(bflags, O_RDWR, LINUX_O_RDWR);
109 	res |= cvtto_linux_mask(bflags, O_CREAT, LINUX_O_CREAT);
110 	res |= cvtto_linux_mask(bflags, O_EXCL, LINUX_O_EXCL);
111 	res |= cvtto_linux_mask(bflags, O_NOCTTY, LINUX_O_NOCTTY);
112 	res |= cvtto_linux_mask(bflags, O_TRUNC, LINUX_O_TRUNC);
113 	res |= cvtto_linux_mask(bflags, O_NDELAY, LINUX_O_NDELAY);
114 	res |= cvtto_linux_mask(bflags, O_SYNC, LINUX_O_SYNC);
115 	res |= cvtto_linux_mask(bflags, O_ASYNC, LINUX_FASYNC);
116 	res |= cvtto_linux_mask(bflags, O_APPEND, LINUX_O_APPEND);
117 
118 	return res;
119 }
120 
121 /*
122  * creat(2) is an obsolete function, but it's present as a Linux
123  * system call, so let's deal with it.
124  *
125  * Just call open(2) with the TRUNC, CREAT and WRONLY flags.
126  */
127 int
linux_sys_creat(p,v,retval)128 linux_sys_creat(p, v, retval)
129 	struct proc *p;
130 	void *v;
131 	register_t *retval;
132 {
133 	struct linux_sys_creat_args /* {
134 		syscallarg(char *) path;
135 		syscallarg(int) mode;
136 	} */ *uap = v;
137 	struct sys_open_args oa;
138 	caddr_t sg;
139 
140 	sg = stackgap_init(p->p_emul);
141 	LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
142 
143 	SCARG(&oa, path) = SCARG(uap, path);
144 	SCARG(&oa, flags) = O_CREAT | O_TRUNC | O_WRONLY;
145 	SCARG(&oa, mode) = SCARG(uap, mode);
146 
147 	return sys_open(p, &oa, retval);
148 }
149 
150 /*
151  * open(2). Take care of the different flag values, and let the
152  * OpenBSD syscall do the real work. See if this operation
153  * gives the current process a controlling terminal.
154  * (XXX is this necessary?)
155  */
156 int
linux_sys_open(p,v,retval)157 linux_sys_open(p, v, retval)
158 	struct proc *p;
159 	void *v;
160 	register_t *retval;
161 {
162 	struct linux_sys_open_args /* {
163 		syscallarg(char *) path;
164 		syscallarg(int) flags;
165 		syscallarg(int) mode;
166 	} */ *uap = v;
167 	int error, fl;
168 	struct sys_open_args boa;
169 	caddr_t sg;
170 
171 	sg = stackgap_init(p->p_emul);
172 
173 	fl = linux_to_bsd_ioflags(SCARG(uap, flags));
174 
175 	if (fl & O_CREAT)
176 		LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
177 	else
178 		LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
179 
180 	SCARG(&boa, path) = SCARG(uap, path);
181 	SCARG(&boa, flags) = fl;
182 	SCARG(&boa, mode) = SCARG(uap, mode);
183 
184 	if ((error = sys_open(p, &boa, retval)))
185 		return error;
186 
187 	/*
188 	 * this bit from sunos_misc.c (and svr4_fcntl.c).
189 	 * If we are a session leader, and we don't have a controlling
190 	 * terminal yet, and the O_NOCTTY flag is not set, try to make
191 	 * this the controlling terminal.
192 	 */
193         if (!(fl & O_NOCTTY) && SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
194                 struct filedesc *fdp = p->p_fd;
195                 struct file     *fp;
196 
197 		if ((fp = fd_getfile(fdp, *retval)) == NULL)
198 			return (EBADF);
199 		FREF(fp);
200                 if (fp->f_type == DTYPE_VNODE)
201                         (fp->f_ops->fo_ioctl) (fp, TIOCSCTTY, (caddr_t) 0, p);
202 		FRELE(fp);
203         }
204 	return 0;
205 }
206 
207 /*
208  * This appears to be part of a Linux attempt to switch to 64 bits file sizes.
209  */
210 int
linux_sys_llseek(p,v,retval)211 linux_sys_llseek(p, v, retval)
212 	struct proc *p;
213 	void *v;
214 	register_t *retval;
215 {
216 	struct linux_sys_llseek_args /* {
217 		syscallarg(int) fd;
218 		syscallarg(uint32_t) ohigh;
219 		syscallarg(uint32_t) olow;
220 		syscallarg(caddr_t) res;
221 		syscallarg(int) whence;
222 	} */ *uap = v;
223 	struct sys_lseek_args bla;
224 	int error;
225 	off_t off;
226 
227 	off = SCARG(uap, olow) | (((off_t) SCARG(uap, ohigh)) << 32);
228 
229 	SCARG(&bla, fd) = SCARG(uap, fd);
230 	SCARG(&bla, offset) = off;
231 	SCARG(&bla, whence) = SCARG(uap, whence);
232 
233 	if ((error = sys_lseek(p, &bla, retval)))
234 		return error;
235 
236 	if ((error = copyout(retval, SCARG(uap, res), sizeof (off_t))))
237 		return error;
238 
239 	retval[0] = 0;
240 	return 0;
241 }
242 
243 /*
244  * The next two functions take care of converting the flock
245  * structure back and forth between Linux and OpenBSD format.
246  * The only difference in the structures is the order of
247  * the fields, and the 'whence' value.
248  */
249 static void
bsd_to_linux_flock(bfp,lfp)250 bsd_to_linux_flock(bfp, lfp)
251 	struct flock *bfp;
252 	struct linux_flock *lfp;
253 {
254 
255 	lfp->l_start = bfp->l_start;
256 	lfp->l_len = bfp->l_len;
257 	lfp->l_pid = bfp->l_pid;
258 	lfp->l_whence = bfp->l_whence;
259 	switch (bfp->l_type) {
260 	case F_RDLCK:
261 		lfp->l_type = LINUX_F_RDLCK;
262 		break;
263 	case F_UNLCK:
264 		lfp->l_type = LINUX_F_UNLCK;
265 		break;
266 	case F_WRLCK:
267 		lfp->l_type = LINUX_F_WRLCK;
268 		break;
269 	}
270 }
271 
272 static void
linux_to_bsd_flock(lfp,bfp)273 linux_to_bsd_flock(lfp, bfp)
274 	struct linux_flock *lfp;
275 	struct flock *bfp;
276 {
277 
278 	bfp->l_start = lfp->l_start;
279 	bfp->l_len = lfp->l_len;
280 	bfp->l_pid = lfp->l_pid;
281 	bfp->l_whence = lfp->l_whence;
282 	switch (lfp->l_type) {
283 	case LINUX_F_RDLCK:
284 		bfp->l_type = F_RDLCK;
285 		break;
286 	case LINUX_F_UNLCK:
287 		bfp->l_type = F_UNLCK;
288 		break;
289 	case LINUX_F_WRLCK:
290 		bfp->l_type = F_WRLCK;
291 		break;
292 	}
293 }
294 
295 /*
296  * Most actions in the fcntl() call are straightforward; simply
297  * pass control to the OpenBSD system call. A few commands need
298  * conversions after the actual system call has done its work,
299  * because the flag values and lock structure are different.
300  */
301 int
linux_sys_fcntl(p,v,retval)302 linux_sys_fcntl(p, v, retval)
303 	struct proc *p;
304 	void *v;
305 	register_t *retval;
306 {
307 	struct linux_sys_fcntl_args /* {
308 		syscallarg(int) fd;
309 		syscallarg(int) cmd;
310 		syscallarg(void *) arg;
311 	} */ *uap = v;
312 	int fd, cmd, error, val;
313 	caddr_t arg, sg;
314 	struct linux_flock lfl;
315 	struct flock *bfp, bfl;
316 	struct sys_fcntl_args fca;
317 	struct filedesc *fdp;
318 	struct file *fp;
319 	struct vnode *vp;
320 	struct vattr va;
321 	long pgid;
322 	struct pgrp *pgrp;
323 	struct tty *tp, *(*d_tty)(dev_t);
324 
325 	fd = SCARG(uap, fd);
326 	cmd = SCARG(uap, cmd);
327 	arg = (caddr_t) SCARG(uap, arg);
328 
329 	switch (cmd) {
330 	case LINUX_F_DUPFD:
331 		cmd = F_DUPFD;
332 		break;
333 	case LINUX_F_GETFD:
334 		cmd = F_GETFD;
335 		break;
336 	case LINUX_F_SETFD:
337 		cmd = F_SETFD;
338 		break;
339 	case LINUX_F_GETFL:
340 		SCARG(&fca, fd) = fd;
341 		SCARG(&fca, cmd) = F_GETFL;
342 		SCARG(&fca, arg) = arg;
343 		if ((error = sys_fcntl(p, &fca, retval)))
344 			return error;
345 		retval[0] = bsd_to_linux_ioflags(retval[0]);
346 		return 0;
347 	case LINUX_F_SETFL:
348 		val = linux_to_bsd_ioflags((int)SCARG(uap, arg));
349 		SCARG(&fca, fd) = fd;
350 		SCARG(&fca, cmd) = F_SETFL;
351 		SCARG(&fca, arg) = (caddr_t) val;
352 		return sys_fcntl(p, &fca, retval);
353 	case LINUX_F_GETLK:
354 		sg = stackgap_init(p->p_emul);
355 		if ((error = copyin(arg, &lfl, sizeof lfl)))
356 			return error;
357 		linux_to_bsd_flock(&lfl, &bfl);
358 		bfp = (struct flock *) stackgap_alloc(&sg, sizeof *bfp);
359 		SCARG(&fca, fd) = fd;
360 		SCARG(&fca, cmd) = F_GETLK;
361 		SCARG(&fca, arg) = bfp;
362 		if ((error = copyout(&bfl, bfp, sizeof bfl)))
363 			return error;
364 		if ((error = sys_fcntl(p, &fca, retval)))
365 			return error;
366 		if ((error = copyin(bfp, &bfl, sizeof bfl)))
367 			return error;
368 		bsd_to_linux_flock(&bfl, &lfl);
369 		error = copyout(&lfl, arg, sizeof lfl);
370 		return error;
371 		break;
372 	case LINUX_F_SETLK:
373 	case LINUX_F_SETLKW:
374 		cmd = (cmd == LINUX_F_SETLK ? F_SETLK : F_SETLKW);
375 		if ((error = copyin(arg, &lfl, sizeof lfl)))
376 			return error;
377 		linux_to_bsd_flock(&lfl, &bfl);
378 		sg = stackgap_init(p->p_emul);
379 		bfp = (struct flock *) stackgap_alloc(&sg, sizeof *bfp);
380 		if ((error = copyout(&bfl, bfp, sizeof bfl)))
381 			return error;
382 		SCARG(&fca, fd) = fd;
383 		SCARG(&fca, cmd) = cmd;
384 		SCARG(&fca, arg) = bfp;
385 		return sys_fcntl(p, &fca, retval);
386 		break;
387 	case LINUX_F_SETOWN:
388 	case LINUX_F_GETOWN:
389 		/*
390 		 * We need to route around the normal fcntl() for these calls,
391 		 * since it uses TIOC{G,S}PGRP, which is too restrictive for
392 		 * Linux F_{G,S}ETOWN semantics. For sockets, this problem
393 		 * does not exist.
394 		 */
395 		fdp = p->p_fd;
396 		if ((fp = fd_getfile(fdp, fd)) == NULL)
397 			return (EBADF);
398 		if (fp->f_type == DTYPE_SOCKET) {
399 			cmd = cmd == LINUX_F_SETOWN ? F_SETOWN : F_GETOWN;
400 			break;
401 		}
402 		vp = (struct vnode *)fp->f_data;
403 		if (vp->v_type != VCHR)
404 			return EINVAL;
405 		FREF(fp);
406 		error = VOP_GETATTR(vp, &va, p->p_ucred, p);
407 		FRELE(fp);
408 		if (error)
409 			return error;
410 		d_tty = cdevsw[major(va.va_rdev)].d_tty;
411 		if (!d_tty || (!(tp = (*d_tty)(va.va_rdev))))
412 			return EINVAL;
413 		if (cmd == LINUX_F_GETOWN) {
414 			retval[0] = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
415 			return 0;
416 		}
417 		if ((long)arg <= 0) {
418 			pgid = -(long)arg;
419 		} else {
420 			struct proc *p1 = pfind((long)arg);
421 			if (p1 == 0)
422 				return (ESRCH);
423 			pgid = (long)p1->p_pgrp->pg_id;
424 		}
425 		pgrp = pgfind(pgid);
426 		if (pgrp == NULL || pgrp->pg_session != p->p_session)
427 			return EPERM;
428 		tp->t_pgrp = pgrp;
429 		return 0;
430 	default:
431 		return EOPNOTSUPP;
432 	}
433 
434 	SCARG(&fca, fd) = fd;
435 	SCARG(&fca, cmd) = cmd;
436 	SCARG(&fca, arg) = arg;
437 
438 	return sys_fcntl(p, &fca, retval);
439 }
440 
441 /*
442  * Convert a OpenBSD stat structure to a Linux stat structure.
443  * Only the order of the fields and the padding in the structure
444  * is different. linux_fakedev is a machine-dependent function
445  * which optionally converts device driver major/minor numbers
446  * (XXX horrible, but what can you do against code that compares
447  * things against constant major device numbers? sigh)
448  */
449 static void
bsd_to_linux_stat(bsp,lsp)450 bsd_to_linux_stat(bsp, lsp)
451 	struct stat *bsp;
452 	struct linux_stat *lsp;
453 {
454 
455 	lsp->lst_dev     = bsp->st_dev;
456 	lsp->lst_ino     = bsp->st_ino;
457 	lsp->lst_mode    = bsp->st_mode;
458 	lsp->lst_nlink   = bsp->st_nlink;
459 	lsp->lst_uid     = bsp->st_uid;
460 	lsp->lst_gid     = bsp->st_gid;
461 	lsp->lst_rdev    = linux_fakedev(bsp->st_rdev);
462 	lsp->lst_size    = bsp->st_size;
463 	lsp->lst_blksize = bsp->st_blksize;
464 	lsp->lst_blocks  = bsp->st_blocks;
465 	lsp->lst_atime   = bsp->st_atime;
466 	lsp->lst_mtime   = bsp->st_mtime;
467 	lsp->lst_ctime   = bsp->st_ctime;
468 }
469 
470 /*
471  * The stat functions below are plain sailing. stat and lstat are handled
472  * by one function to avoid code duplication.
473  */
474 int
linux_sys_fstat(p,v,retval)475 linux_sys_fstat(p, v, retval)
476 	struct proc *p;
477 	void *v;
478 	register_t *retval;
479 {
480 	struct linux_sys_fstat_args /* {
481 		syscallarg(int) fd;
482 		syscallarg(linux_stat *) sp;
483 	} */ *uap = v;
484 	struct sys_fstat_args fsa;
485 	struct linux_stat tmplst;
486 	struct stat *st,tmpst;
487 	caddr_t sg;
488 	int error;
489 
490 	sg = stackgap_init(p->p_emul);
491 
492 	st = stackgap_alloc(&sg, sizeof (struct stat));
493 
494 	SCARG(&fsa, fd) = SCARG(uap, fd);
495 	SCARG(&fsa, sb) = st;
496 
497 	if ((error = sys_fstat(p, &fsa, retval)))
498 		return error;
499 
500 	if ((error = copyin(st, &tmpst, sizeof tmpst)))
501 		return error;
502 
503 	bsd_to_linux_stat(&tmpst, &tmplst);
504 
505 	if ((error = copyout(&tmplst, SCARG(uap, sp), sizeof tmplst)))
506 		return error;
507 
508 	return 0;
509 }
510 
511 static int
linux_stat1(p,v,retval,dolstat)512 linux_stat1(p, v, retval, dolstat)
513 	struct proc *p;
514 	void *v;
515 	register_t *retval;
516 	int dolstat;
517 {
518 	struct sys_stat_args sa;
519 	struct linux_stat tmplst;
520 	struct stat *st, tmpst;
521 	caddr_t sg;
522 	int error;
523 	struct linux_sys_stat_args *uap = v;
524 
525 	sg = stackgap_init(p->p_emul);
526 
527 	st = stackgap_alloc(&sg, sizeof (struct stat));
528 	LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
529 
530 	SCARG(&sa, ub) = st;
531 	SCARG(&sa, path) = SCARG(uap, path);
532 
533 	if ((error = (dolstat ? sys_lstat(p, &sa, retval) :
534 				sys_stat(p, &sa, retval))))
535 		return error;
536 
537 	if ((error = copyin(st, &tmpst, sizeof tmpst)))
538 		return error;
539 
540 	bsd_to_linux_stat(&tmpst, &tmplst);
541 
542 	if ((error = copyout(&tmplst, SCARG(uap, sp), sizeof tmplst)))
543 		return error;
544 
545 	return 0;
546 }
547 
548 int
linux_sys_stat(p,v,retval)549 linux_sys_stat(p, v, retval)
550 	struct proc *p;
551 	void *v;
552 	register_t *retval;
553 {
554 	struct linux_sys_stat_args /* {
555 		syscallarg(char *) path;
556 		syscallarg(struct linux_stat *) sp;
557 	} */ *uap = v;
558 
559 	return linux_stat1(p, uap, retval, 0);
560 }
561 
562 int
linux_sys_lstat(p,v,retval)563 linux_sys_lstat(p, v, retval)
564 	struct proc *p;
565 	void *v;
566 	register_t *retval;
567 {
568 	struct linux_sys_lstat_args /* {
569 		syscallarg(char *) path;
570 		syscallarg(struct linux_stat *) sp;
571 	} */ *uap = v;
572 
573 	return linux_stat1(p, uap, retval, 1);
574 }
575 
576 /*
577  * The following syscalls are mostly here because of the alternate path check.
578  */
579 int
linux_sys_access(p,v,retval)580 linux_sys_access(p, v, retval)
581 	struct proc *p;
582 	void *v;
583 	register_t *retval;
584 {
585 	struct linux_sys_access_args /* {
586 		syscallarg(char *) path;
587 		syscallarg(int) flags;
588 	} */ *uap = v;
589 	caddr_t sg = stackgap_init(p->p_emul);
590 
591 	LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
592 
593 	return sys_access(p, uap, retval);
594 }
595 
596 int
linux_sys_unlink(p,v,retval)597 linux_sys_unlink(p, v, retval)
598 	struct proc *p;
599 	void *v;
600 	register_t *retval;
601 
602 {
603 	struct linux_sys_unlink_args /* {
604 		syscallarg(char *) path;
605 	} */ *uap = v;
606 	caddr_t sg = stackgap_init(p->p_emul);
607 
608 	LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
609 
610 	return sys_unlink(p, uap, retval);
611 }
612 
613 int
linux_sys_chdir(p,v,retval)614 linux_sys_chdir(p, v, retval)
615 	struct proc *p;
616 	void *v;
617 	register_t *retval;
618 {
619 	struct linux_sys_chdir_args /* {
620 		syscallarg(char *) path;
621 	} */ *uap = v;
622 	caddr_t sg = stackgap_init(p->p_emul);
623 
624 	LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
625 
626 	return sys_chdir(p, uap, retval);
627 }
628 
629 int
linux_sys_mknod(p,v,retval)630 linux_sys_mknod(p, v, retval)
631 	struct proc *p;
632 	void *v;
633 	register_t *retval;
634 {
635 	struct linux_sys_mknod_args /* {
636 		syscallarg(char *) path;
637 		syscallarg(int) mode;
638 		syscallarg(int) dev;
639 	} */ *uap = v;
640 	caddr_t sg = stackgap_init(p->p_emul);
641 	struct sys_mkfifo_args bma;
642 
643 	LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
644 
645 	/*
646 	 * BSD handles FIFOs separately
647 	 */
648 	if (SCARG(uap, mode) & S_IFIFO) {
649 		SCARG(&bma, path) = SCARG(uap, path);
650 		SCARG(&bma, mode) = SCARG(uap, mode);
651 		return sys_mkfifo(p, uap, retval);
652 	} else
653 		return sys_mknod(p, uap, retval);
654 }
655 
656 int
linux_sys_chmod(p,v,retval)657 linux_sys_chmod(p, v, retval)
658 	struct proc *p;
659 	void *v;
660 	register_t *retval;
661 {
662 	struct linux_sys_chmod_args /* {
663 		syscallarg(char *) path;
664 		syscallarg(int) mode;
665 	} */ *uap = v;
666 	caddr_t sg = stackgap_init(p->p_emul);
667 
668 	LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
669 
670 	return sys_chmod(p, uap, retval);
671 }
672 
673 int
linux_sys_chown16(p,v,retval)674 linux_sys_chown16(p, v, retval)
675 	struct proc *p;
676 	void *v;
677 	register_t *retval;
678 {
679 	struct linux_sys_chown16_args /* {
680 		syscallarg(char *) path;
681 		syscallarg(int) uid;
682 		syscallarg(int) gid;
683 	} */ *uap = v;
684 	struct sys_chown_args bca;
685 	caddr_t sg = stackgap_init(p->p_emul);
686 
687 	LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
688 
689 	SCARG(&bca, path) = SCARG(uap, path);
690 	SCARG(&bca, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ?
691 		(uid_t)-1 : SCARG(uap, uid);
692 	SCARG(&bca, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ?
693 		(gid_t)-1 : SCARG(uap, gid);
694 
695 	return sys_chown(p, &bca, retval);
696 }
697 
698 int
linux_sys_fchown16(p,v,retval)699 linux_sys_fchown16(p, v, retval)
700 	struct proc *p;
701 	void *v;
702 	register_t *retval;
703 {
704 	struct linux_sys_fchown16_args /* {
705 		syscallarg(int) fd;
706 		syscallarg(int) uid;
707 		syscallarg(int) gid;
708 	} */ *uap = v;
709 	struct sys_fchown_args bfa;
710 
711 	SCARG(&bfa, fd) = SCARG(uap, fd);
712 	SCARG(&bfa, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ?
713 		(uid_t)-1 : SCARG(uap, uid);
714 	SCARG(&bfa, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ?
715 		(gid_t)-1 : SCARG(uap, gid);
716 
717 	return sys_fchown(p, &bfa, retval);
718 }
719 
720 int
linux_sys_lchown16(p,v,retval)721 linux_sys_lchown16(p, v, retval)
722 	struct proc *p;
723 	void *v;
724 	register_t *retval;
725 {
726 	struct linux_sys_lchown16_args /* {
727 		syscallarg(char *) path;
728 		syscallarg(int) uid;
729 		syscallarg(int) gid;
730 	} */ *uap = v;
731 	struct sys_lchown_args bla;
732 
733 	SCARG(&bla, path) = SCARG(uap, path);
734 	SCARG(&bla, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ?
735 		(uid_t)-1 : SCARG(uap, uid);
736 	SCARG(&bla, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ?
737 		(gid_t)-1 : SCARG(uap, gid);
738 
739 	return sys_lchown(p, &bla, retval);
740 }
741 
742 int
linux_sys_rename(p,v,retval)743 linux_sys_rename(p, v, retval)
744 	struct proc *p;
745 	void *v;
746 	register_t *retval;
747 {
748 	struct linux_sys_rename_args /* {
749 		syscallarg(char *) from;
750 		syscallarg(char *) to;
751 	} */ *uap = v;
752 	caddr_t sg = stackgap_init(p->p_emul);
753 
754 	LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, from));
755 	LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, to));
756 
757 	return sys_rename(p, uap, retval);
758 }
759 
760 int
linux_sys_mkdir(p,v,retval)761 linux_sys_mkdir(p, v, retval)
762 	struct proc *p;
763 	void *v;
764 	register_t *retval;
765 {
766 	struct linux_sys_mkdir_args /* {
767 		syscallarg(char *) path;
768 		syscallarg(int) mode;
769 	} */ *uap = v;
770 	caddr_t sg = stackgap_init(p->p_emul);
771 
772 	LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
773 
774 	return sys_mkdir(p, uap, retval);
775 }
776 
777 int
linux_sys_rmdir(p,v,retval)778 linux_sys_rmdir(p, v, retval)
779 	struct proc *p;
780 	void *v;
781 	register_t *retval;
782 {
783 	struct linux_sys_rmdir_args /* {
784 		syscallarg(char *) path;
785 	} */ *uap = v;
786 	caddr_t sg = stackgap_init(p->p_emul);
787 
788 	LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
789 
790 	return sys_rmdir(p, uap, retval);
791 }
792 
793 int
linux_sys_symlink(p,v,retval)794 linux_sys_symlink(p, v, retval)
795 	struct proc *p;
796 	void *v;
797 	register_t *retval;
798 {
799 	struct linux_sys_symlink_args /* {
800 		syscallarg(char *) path;
801 		syscallarg(char *) to;
802 	} */ *uap = v;
803 	caddr_t sg = stackgap_init(p->p_emul);
804 
805 	LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
806 	LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, to));
807 
808 	return sys_symlink(p, uap, retval);
809 }
810 
811 int
linux_sys_readlink(p,v,retval)812 linux_sys_readlink(p, v, retval)
813 	struct proc *p;
814 	void *v;
815 	register_t *retval;
816 {
817 	struct linux_sys_readlink_args /* {
818 		syscallarg(char *) name;
819 		syscallarg(char *) buf;
820 		syscallarg(int) count;
821 	} */ *uap = v;
822 	caddr_t sg = stackgap_init(p->p_emul);
823 
824 	LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, name));
825 
826 	return sys_readlink(p, uap, retval);
827 }
828 
829 int
linux_sys_truncate(p,v,retval)830 linux_sys_truncate(p, v, retval)
831 	struct proc *p;
832 	void *v;
833 	register_t *retval;
834 {
835 	struct linux_sys_truncate_args /* {
836 		syscallarg(char *) path;
837 		syscallarg(long) length;
838 	} */ *uap = v;
839 	caddr_t sg = stackgap_init(p->p_emul);
840 
841 	LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
842 
843 	return compat_43_sys_truncate(p, uap, retval);
844 }
845 
846 /*
847  * This is just fsync() for now (just as it is in the Linux kernel)
848  */
849 int
linux_sys_fdatasync(p,v,retval)850 linux_sys_fdatasync(p, v, retval)
851 	struct proc *p;
852 	void *v;
853 	register_t *retval;
854 {
855 	struct linux_sys_fdatasync_args /* {
856 		syscallarg(int) fd;
857 	} */ *uap = v;
858 	return sys_fsync(p, uap, retval);
859 }
860 
861 /*
862  * pread(2).
863  */
864 int
linux_sys_pread(p,v,retval)865 linux_sys_pread(p, v, retval)
866 	struct proc *p;
867 	void *v;
868 	register_t *retval;
869 {
870 	struct linux_sys_pread_args /* {
871 		syscallarg(int) fd;
872 		syscallarg(void *) buf;
873 		syscallarg(size_t) nbyte;
874 		syscallarg(linux_off_t) offset;
875 	} */ *uap = v;
876 	struct sys_pread_args pra;
877 
878 	SCARG(&pra, fd) = SCARG(uap, fd);
879 	SCARG(&pra, buf) = SCARG(uap, buf);
880 	SCARG(&pra, nbyte) = SCARG(uap, nbyte);
881 	SCARG(&pra, offset) = SCARG(uap, offset);
882 
883 	return sys_pread(p, &pra, retval);
884 }
885 
886 /*
887  * pwrite(2).
888  */
889 int
linux_sys_pwrite(p,v,retval)890 linux_sys_pwrite(p, v, retval)
891 	struct proc *p;
892 	void *v;
893 	register_t *retval;
894 {
895 	struct linux_sys_pwrite_args /* {
896 		syscallarg(int) fd;
897 		syscallarg(char *) buf;
898 		syscallarg(size_t) nbyte;
899 		syscallarg(linux_off_t) offset;
900 	} */ *uap = v;
901 	struct sys_pwrite_args pra;
902 
903 	SCARG(&pra, fd) = SCARG(uap, fd);
904 	SCARG(&pra, buf) = SCARG(uap, buf);
905 	SCARG(&pra, nbyte) = SCARG(uap, nbyte);
906 	SCARG(&pra, offset) = SCARG(uap, offset);
907 
908 	return sys_pwrite(p, &pra, retval);
909 }
910