Home | History | Annotate | Line # | Download | only in common
linux_llseek.c revision 1.13
      1 /*	$NetBSD: linux_llseek.c,v 1.13 1995/10/08 22:53:43 fvdl 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 
     34 #include <sys/param.h>
     35 #include <sys/systm.h>
     36 #include <sys/namei.h>
     37 #include <sys/proc.h>
     38 #include <sys/file.h>
     39 #include <sys/stat.h>
     40 #include <sys/filedesc.h>
     41 #include <sys/ioctl.h>
     42 #include <sys/kernel.h>
     43 #include <sys/mount.h>
     44 #include <sys/malloc.h>
     45 #include <sys/vnode.h>
     46 #include <sys/tty.h>
     47 #include <sys/conf.h>
     48 
     49 #include <sys/syscallargs.h>
     50 
     51 #include <compat/linux/linux_types.h>
     52 #include <compat/linux/linux_signal.h>
     53 #include <compat/linux/linux_syscallargs.h>
     54 #include <compat/linux/linux_fcntl.h>
     55 #include <compat/linux/linux_util.h>
     56 
     57 /*
     58  * Some file-related calls are handled here. The usual flag conversion
     59  * an structure conversion is done, and alternate emul path searching.
     60  */
     61 
     62 /*
     63  * The next two functions convert between the Linux and NetBSD values
     64  * of the flags used in open(2) and fcntl(2).
     65  */
     66 static int
     67 linux_to_bsd_ioflags(int lflags)
     68 {
     69 	int res = 0;
     70 
     71 	res |= cvtto_bsd_mask(lflags, LINUX_O_WRONLY, O_WRONLY);
     72 	res |= cvtto_bsd_mask(lflags, LINUX_O_RDONLY, O_RDONLY);
     73 	res |= cvtto_bsd_mask(lflags, LINUX_O_RDWR, O_RDWR);
     74 	res |= cvtto_bsd_mask(lflags, LINUX_O_CREAT, O_CREAT);
     75 	res |= cvtto_bsd_mask(lflags, LINUX_O_EXCL, O_EXCL);
     76 	res |= cvtto_bsd_mask(lflags, LINUX_O_NOCTTY, O_NOCTTY);
     77 	res |= cvtto_bsd_mask(lflags, LINUX_O_TRUNC, O_TRUNC);
     78 	res |= cvtto_bsd_mask(lflags, LINUX_O_NDELAY, O_NDELAY);
     79 	res |= cvtto_bsd_mask(lflags, LINUX_O_SYNC, O_FSYNC);
     80 	res |= cvtto_bsd_mask(lflags, LINUX_FASYNC, O_ASYNC);
     81 	res |= cvtto_bsd_mask(lflags, LINUX_O_APPEND, O_APPEND);
     82 
     83 	return res;
     84 }
     85 
     86 static int
     87 bsd_to_linux_ioflags(int bflags)
     88 {
     89 	int res = 0;
     90 
     91 	res |= cvtto_linux_mask(bflags, O_WRONLY, LINUX_O_WRONLY);
     92 	res |= cvtto_linux_mask(bflags, O_RDONLY, LINUX_O_RDONLY);
     93 	res |= cvtto_linux_mask(bflags, O_RDWR, LINUX_O_RDWR);
     94 	res |= cvtto_linux_mask(bflags, O_CREAT, LINUX_O_CREAT);
     95 	res |= cvtto_linux_mask(bflags, O_EXCL, LINUX_O_EXCL);
     96 	res |= cvtto_linux_mask(bflags, O_NOCTTY, LINUX_O_NOCTTY);
     97 	res |= cvtto_linux_mask(bflags, O_TRUNC, LINUX_O_TRUNC);
     98 	res |= cvtto_linux_mask(bflags, O_NDELAY, LINUX_O_NDELAY);
     99 	res |= cvtto_linux_mask(bflags, O_FSYNC, LINUX_O_SYNC);
    100 	res |= cvtto_linux_mask(bflags, O_ASYNC, LINUX_FASYNC);
    101 	res |= cvtto_linux_mask(bflags, O_APPEND, LINUX_O_APPEND);
    102 
    103 	return res;
    104 }
    105 
    106 /*
    107  * creat(2) is an obsolete function, but it's present as a Linux
    108  * system call, so let's deal with it.
    109  *
    110  * Just call open(2) with the TRUNC, CREAT and WRONLY flags.
    111  */
    112 int
    113 linux_sys_creat(p, v, retval)
    114 	struct proc *p;
    115 	void *v;
    116 	register_t *retval;
    117 {
    118 	struct linux_sys_creat_args /* {
    119 		syscallarg(char *) path;
    120 		syscallarg(int) mode;
    121 	} */ *uap = v;
    122 	struct sys_open_args oa;
    123 	caddr_t sg;
    124 
    125 	sg = stackgap_init(p->p_emul);
    126 	LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
    127 
    128 	SCARG(&oa, path) = SCARG(uap, path);
    129 	SCARG(&oa, flags) = O_CREAT | O_TRUNC | O_WRONLY;
    130 	SCARG(&oa, mode) = SCARG(uap, mode);
    131 
    132 	return sys_open(p, &oa, retval);
    133 }
    134 
    135 /*
    136  * open(2). Take care of the different flag values, and let the
    137  * NetBSD syscall do the real work. See if this operation
    138  * gives the current process a controlling terminal.
    139  * (XXX is this necessary?)
    140  */
    141 int
    142 linux_sys_open(p, v, retval)
    143 	struct proc *p;
    144 	void *v;
    145 	register_t *retval;
    146 {
    147 	struct linux_sys_open_args /* {
    148 		syscallarg(char *) path;
    149 		syscallarg(int) flags;
    150 		syscallarg(int) mode;
    151 	} */ *uap = v;
    152 	int error, fl;
    153 	struct sys_open_args boa;
    154 	caddr_t sg;
    155 
    156 	sg = stackgap_init(p->p_emul);
    157 
    158 	fl = linux_to_bsd_ioflags(SCARG(uap, flags));
    159 
    160 	if (fl & O_CREAT)
    161 		LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
    162 	else
    163 		LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
    164 
    165 	SCARG(&boa, path) = SCARG(uap, path);
    166 	SCARG(&boa, flags) = fl;
    167 	SCARG(&boa, mode) = SCARG(uap, mode);
    168 
    169 	if ((error = sys_open(p, &boa, retval)))
    170 		return error;
    171 
    172 	/*
    173 	 * this bit from sunos_misc.c (and svr4_fcntl.c).
    174 	 * If we are a session leader, and we don't have a controlling
    175 	 * terminal yet, and the O_NOCTTY flag is not set, try to make
    176 	 * this the controlling terminal.
    177 	 */
    178         if (!(fl & O_NOCTTY) && SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
    179                 struct filedesc *fdp = p->p_fd;
    180                 struct file     *fp = fdp->fd_ofiles[*retval];
    181 
    182                 /* ignore any error, just give it a try */
    183                 if (fp->f_type == DTYPE_VNODE)
    184                         (fp->f_ops->fo_ioctl) (fp, TIOCSCTTY, (caddr_t) 0, p);
    185         }
    186 	return 0;
    187 }
    188 
    189 /*
    190  * This appears to be part of a Linux attempt to switch to 64 bits file sizes.
    191  */
    192 int
    193 linux_sys_llseek(p, v, retval)
    194 	struct proc *p;
    195 	void *v;
    196 	register_t *retval;
    197 {
    198 	struct linux_sys_llseek_args /* {
    199 		syscallarg(int) fd;
    200 		syscallarg(uint32_t) ohigh;
    201 		syscallarg(uint32_t) olow;
    202 		syscallarg(caddr_t) res;
    203 		syscallarg(int) whence;
    204 	} */ *uap = v;
    205 	struct sys_lseek_args bla;
    206 	int error;
    207 	off_t off;
    208 
    209 	off = SCARG(uap, olow) | (((off_t) SCARG(uap, ohigh)) << 32);
    210 
    211 	SCARG(&bla, fd) = SCARG(uap, fd);
    212 	SCARG(&bla, offset) = off;
    213 	SCARG(&bla, whence) = SCARG(uap, whence);
    214 
    215 	if ((error = sys_lseek(p, &bla, retval)))
    216 		return error;
    217 
    218 	if ((error = copyout(retval, SCARG(uap, res), sizeof (off_t))))
    219 		return error;
    220 
    221 	retval[0] = 0;
    222 	return 0;
    223 }
    224 
    225 /*
    226  * The next two functions take care of converting the flock
    227  * structure back and forth between Linux and NetBSD format.
    228  * The only difference in the structures is the order of
    229  * the fields, and the 'whence' value.
    230  */
    231 static void
    232 bsd_to_linux_flock(bfp, lfp)
    233 	struct flock *bfp;
    234 	struct linux_flock *lfp;
    235 {
    236 
    237 	lfp->l_start = bfp->l_start;
    238 	lfp->l_len = bfp->l_len;
    239 	lfp->l_pid = bfp->l_pid;
    240 	lfp->l_whence = bfp->l_whence;
    241 	switch (bfp->l_type) {
    242 	case F_RDLCK:
    243 		lfp->l_type = LINUX_F_RDLCK;
    244 		break;
    245 	case F_UNLCK:
    246 		lfp->l_type = LINUX_F_UNLCK;
    247 		break;
    248 	case F_WRLCK:
    249 		lfp->l_type = LINUX_F_WRLCK;
    250 		break;
    251 	}
    252 }
    253 
    254 static void
    255 linux_to_bsd_flock(lfp, bfp)
    256 	struct linux_flock *lfp;
    257 	struct flock *bfp;
    258 {
    259 
    260 	bfp->l_start = lfp->l_start;
    261 	bfp->l_len = lfp->l_len;
    262 	bfp->l_pid = lfp->l_pid;
    263 	bfp->l_whence = lfp->l_whence;
    264 	switch (lfp->l_type) {
    265 	case LINUX_F_RDLCK:
    266 		bfp->l_type = F_RDLCK;
    267 		break;
    268 	case LINUX_F_UNLCK:
    269 		bfp->l_type = F_UNLCK;
    270 		break;
    271 	case LINUX_F_WRLCK:
    272 		bfp->l_type = F_WRLCK;
    273 		break;
    274 	}
    275 }
    276 
    277 /*
    278  * Most actions in the fcntl() call are straightforward; simply
    279  * pass control to the NetBSD system call. A few commands need
    280  * conversions after the actual system call has done its work,
    281  * because the flag values and lock structure are different.
    282  */
    283 int
    284 linux_sys_fcntl(p, v, retval)
    285 	struct proc *p;
    286 	void *v;
    287 	register_t *retval;
    288 {
    289 	struct linux_sys_fcntl_args /* {
    290 		syscallarg(int) fd;
    291 		syscallarg(int) cmd;
    292 		syscallarg(void *) arg;
    293 	} */ *uap = v;
    294 	int fd, cmd, error, val;
    295 	caddr_t arg, sg;
    296 	struct linux_flock lfl;
    297 	struct flock *bfp, bfl;
    298 	struct sys_fcntl_args fca;
    299 	struct filedesc *fdp;
    300 	struct file *fp;
    301 	struct vnode *vp;
    302 	struct vattr va;
    303 	long pgid;
    304 	struct pgrp *pgrp;
    305 	struct tty *tp, *(*d_tty) __P((dev_t));
    306 
    307 	fd = SCARG(uap, fd);
    308 	cmd = SCARG(uap, cmd);
    309 	arg = (caddr_t) SCARG(uap, arg);
    310 
    311 	switch (cmd) {
    312 	case LINUX_F_DUPFD:
    313 		cmd = F_DUPFD;
    314 		break;
    315 	case LINUX_F_GETFD:
    316 		cmd = F_GETFD;
    317 		break;
    318 	case LINUX_F_SETFD:
    319 		cmd = F_SETFD;
    320 		break;
    321 	case LINUX_F_GETFL:
    322 		SCARG(&fca, fd) = fd;
    323 		SCARG(&fca, cmd) = F_GETFL;
    324 		SCARG(&fca, arg) = arg;
    325 		if ((error = sys_fcntl(p, &fca, retval)))
    326 			return error;
    327 		retval[0] = bsd_to_linux_ioflags(retval[0]);
    328 		return 0;
    329 	case LINUX_F_SETFL:
    330 		val = linux_to_bsd_ioflags((int)SCARG(uap, arg));
    331 		SCARG(&fca, fd) = fd;
    332 		SCARG(&fca, cmd) = F_SETFL;
    333 		SCARG(&fca, arg) = (caddr_t) val;
    334 		return sys_fcntl(p, &fca, retval);
    335 	case LINUX_F_GETLK:
    336 		sg = stackgap_init(p->p_emul);
    337 		bfp = (struct flock *) stackgap_alloc(&sg, sizeof *bfp);
    338 		SCARG(&fca, fd) = fd;
    339 		SCARG(&fca, cmd) = F_GETLK;
    340 		SCARG(&fca, arg) = bfp;
    341 		if ((error = sys_fcntl(p, &fca, retval)))
    342 			return error;
    343 		if ((error = copyin(bfp, &bfl, sizeof bfl)))
    344 			return error;
    345 		bsd_to_linux_flock(&bfl, &lfl);
    346 		return copyout(&lfl, arg, sizeof lfl);
    347 		break;
    348 	case LINUX_F_SETLK:
    349 	case LINUX_F_SETLKW:
    350 		cmd = (cmd == LINUX_F_SETLK ? F_SETLK : F_SETLKW);
    351 		if ((error = copyin(arg, &lfl, sizeof lfl)))
    352 			return error;
    353 		linux_to_bsd_flock(&lfl, &bfl);
    354 		sg = stackgap_init(p->p_emul);
    355 		bfp = (struct flock *) stackgap_alloc(&sg, sizeof *bfp);
    356 		if ((error = copyout(&bfl, bfp, sizeof bfl)))
    357 			return error;
    358 		SCARG(&fca, fd) = fd;
    359 		SCARG(&fca, cmd) = cmd;
    360 		SCARG(&fca, arg) = bfp;
    361 		return sys_fcntl(p, &fca, retval);
    362 		break;
    363 	case LINUX_F_SETOWN:
    364 	case LINUX_F_GETOWN:
    365 		/*
    366 		 * We need to route around the normal fcntl() for these calls,
    367 		 * since it uses TIOC{G,S}PGRP, which is too restrictive for
    368 		 * Linux F_{G,S}ETOWN semantics. For sockets, this problem
    369 		 * does not exist.
    370 		 */
    371 		fdp = p->p_fd;
    372 		if ((u_int)fd >= fdp->fd_nfiles ||
    373 		    (fp = fdp->fd_ofiles[fd]) == NULL)
    374 			return EBADF;
    375 		if (fp->f_type == DTYPE_SOCKET) {
    376 			cmd = cmd == LINUX_F_SETOWN ? F_SETOWN : F_GETOWN;
    377 			break;
    378 		}
    379 		vp = (struct vnode *)fp->f_data;
    380 		if (vp->v_type != VCHR)
    381 			return EINVAL;
    382 		if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)))
    383 			return error;
    384 		d_tty = cdevsw[major(va.va_rdev)].d_tty;
    385 		if (!d_tty || (!(tp = (*d_tty)(va.va_rdev))))
    386 			return EINVAL;
    387 		if (cmd == LINUX_F_GETOWN) {
    388 			retval[0] = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
    389 			return 0;
    390 		}
    391 		if ((long)arg <= 0) {
    392 			pgid = -(long)arg;
    393 		} else {
    394 			struct proc *p1 = pfind((long)arg);
    395 			if (p1 == 0)
    396 				return (ESRCH);
    397 			pgid = (long)p1->p_pgrp->pg_id;
    398 		}
    399 		pgrp = pgfind(pgid);
    400 		if (pgrp == NULL || pgrp->pg_session != p->p_session)
    401 			return EPERM;
    402 		tp->t_pgrp = pgrp;
    403 		return 0;
    404 	default:
    405 		return EOPNOTSUPP;
    406 	}
    407 
    408 	SCARG(&fca, fd) = fd;
    409 	SCARG(&fca, cmd) = cmd;
    410 	SCARG(&fca, arg) = arg;
    411 
    412 	return sys_fcntl(p, &fca, retval);
    413 }
    414 
    415 /*
    416  * Convert a NetBSD stat structure to a Linux stat structure.
    417  * Only the order of the fields and the padding in the structure
    418  * is different. linux_fakedev is a machine-dependent function
    419  * which optionally converts device driver major/minor numbers
    420  * (XXX horrible, but what can you do against code that compares
    421  * things against constant major device numbers? sigh)
    422  */
    423 static void
    424 bsd_to_linux_stat(bsp, lsp)
    425 	struct stat *bsp;
    426 	struct linux_stat *lsp;
    427 {
    428 
    429 	lsp->lst_dev     = bsp->st_dev;
    430 	lsp->lst_ino     = bsp->st_ino;
    431 	lsp->lst_mode    = bsp->st_mode;
    432 	lsp->lst_nlink   = bsp->st_nlink;
    433 	lsp->lst_uid     = bsp->st_uid;
    434 	lsp->lst_gid     = bsp->st_gid;
    435 	lsp->lst_rdev    = linux_fakedev(bsp->st_rdev);
    436 	lsp->lst_size    = bsp->st_size;
    437 	lsp->lst_blksize = bsp->st_blksize;
    438 	lsp->lst_blocks  = bsp->st_blocks;
    439 	lsp->lst_atime   = bsp->st_atime;
    440 	lsp->lst_mtime   = bsp->st_mtime;
    441 	lsp->lst_ctime   = bsp->st_ctime;
    442 }
    443 
    444 /*
    445  * The stat functions below are plain sailing. stat and lstat are handled
    446  * by one function to avoid code duplication.
    447  */
    448 int
    449 linux_sys_fstat(p, v, retval)
    450 	struct proc *p;
    451 	void *v;
    452 	register_t *retval;
    453 {
    454 	struct linux_sys_fstat_args /* {
    455 		syscallarg(int) fd;
    456 		syscallarg(linux_stat *) sp;
    457 	} */ *uap = v;
    458 	struct sys_fstat_args fsa;
    459 	struct linux_stat tmplst;
    460 	struct stat *st,tmpst;
    461 	caddr_t sg;
    462 	int error;
    463 
    464 	sg = stackgap_init(p->p_emul);
    465 
    466 	st = stackgap_alloc(&sg, sizeof (struct stat));
    467 
    468 	SCARG(&fsa, fd) = SCARG(uap, fd);
    469 	SCARG(&fsa, sb) = st;
    470 
    471 	if ((error = sys_fstat(p, &fsa, retval)))
    472 		return error;
    473 
    474 	if ((error = copyin(st, &tmpst, sizeof tmpst)))
    475 		return error;
    476 
    477 	bsd_to_linux_stat(&tmpst, &tmplst);
    478 
    479 	if ((error = copyout(&tmplst, SCARG(uap, sp), sizeof tmplst)))
    480 		return error;
    481 
    482 	return 0;
    483 }
    484 
    485 static int
    486 linux_stat1(p, uap, retval, dolstat)
    487 	struct proc *p;
    488 	struct linux_sys_stat_args *uap;
    489 	register_t *retval;
    490 	int dolstat;
    491 {
    492 	struct sys_stat_args sa;
    493 	struct linux_stat tmplst;
    494 	struct stat *st, tmpst;
    495 	caddr_t sg;
    496 	int error;
    497 
    498 	sg = stackgap_init(p->p_emul);
    499 
    500 	LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
    501 
    502 	st = stackgap_alloc(&sg, sizeof (struct stat));
    503 	SCARG(&sa, ub) = st;
    504 	SCARG(&sa, path) = SCARG(uap, path);
    505 
    506 	if ((error = (dolstat ? sys_lstat(p, &sa, retval) :
    507 				sys_stat(p, &sa, retval))))
    508 		return error;
    509 
    510 	if ((error = copyin(st, &tmpst, sizeof tmpst)))
    511 		return error;
    512 
    513 	bsd_to_linux_stat(&tmpst, &tmplst);
    514 
    515 	if ((error = copyout(&tmplst, SCARG(uap, sp), sizeof tmplst)))
    516 		return error;
    517 
    518 	return 0;
    519 }
    520 
    521 int
    522 linux_sys_stat(p, v, retval)
    523 	struct proc *p;
    524 	void *v;
    525 	register_t *retval;
    526 {
    527 	struct linux_sys_stat_args /* {
    528 		syscallarg(char *) path;
    529 		syscallarg(struct linux_stat *) sp;
    530 	} */ *uap = v;
    531 
    532 	return linux_stat1(p, uap, retval, 0);
    533 }
    534 
    535 int
    536 linux_sys_lstat(p, v, retval)
    537 	struct proc *p;
    538 	void *v;
    539 	register_t *retval;
    540 {
    541 	struct linux_sys_lstat_args /* {
    542 		syscallarg(char *) path;
    543 		syscallarg(struct linux_stat *) sp;
    544 	} */ *uap = v;
    545 
    546 	return linux_stat1(p, uap, retval, 1);
    547 }
    548 
    549 /*
    550  * The following syscalls are mostly here because of the alternate path check.
    551  */
    552 int
    553 linux_sys_access(p, v, retval)
    554 	struct proc *p;
    555 	void *v;
    556 	register_t *retval;
    557 {
    558 	struct linux_sys_access_args /* {
    559 		syscallarg(char *) path;
    560 		syscallarg(int) flags;
    561 	} */ *uap = v;
    562 	caddr_t sg = stackgap_init(p->p_emul);
    563 
    564 	LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
    565 
    566 	return sys_access(p, uap, retval);
    567 }
    568 
    569 int
    570 linux_sys_unlink(p, v, retval)
    571 	struct proc *p;
    572 	void *v;
    573 	register_t *retval;
    574 
    575 {
    576 	struct linux_sys_unlink_args /* {
    577 		syscallarg(char *) path;
    578 	} */ *uap = v;
    579 	caddr_t sg = stackgap_init(p->p_emul);
    580 
    581 	LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
    582 
    583 	return sys_unlink(p, uap, retval);
    584 }
    585 
    586 int
    587 linux_sys_chdir(p, v, retval)
    588 	struct proc *p;
    589 	void *v;
    590 	register_t *retval;
    591 {
    592 	struct linux_sys_chdir_args /* {
    593 		syscallarg(char *) path;
    594 	} */ *uap = v;
    595 	caddr_t sg = stackgap_init(p->p_emul);
    596 
    597 	LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
    598 
    599 	return sys_chdir(p, uap, retval);
    600 }
    601 
    602 int
    603 linux_sys_mknod(p, v, retval)
    604 	struct proc *p;
    605 	void *v;
    606 	register_t *retval;
    607 {
    608 	struct linux_sys_mknod_args /* {
    609 		syscallarg(char *) path;
    610 		syscallarg(int) mode;
    611 		syscallarg(int) dev;
    612 	} */ *uap = v;
    613 	caddr_t sg = stackgap_init(p->p_emul);
    614 	struct sys_mkfifo_args bma;
    615 
    616 	LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
    617 
    618 	/*
    619 	 * BSD handles FIFOs seperately
    620 	 */
    621 	if (SCARG(uap, mode) & S_IFIFO) {
    622 		SCARG(&bma, path) = SCARG(uap, path);
    623 		SCARG(&bma, mode) = SCARG(uap, mode);
    624 		return sys_mkfifo(p, uap, retval);
    625 	} else
    626 		return sys_mknod(p, uap, retval);
    627 }
    628 
    629 int
    630 linux_sys_chmod(p, v, retval)
    631 	struct proc *p;
    632 	void *v;
    633 	register_t *retval;
    634 {
    635 	struct linux_sys_chmod_args /* {
    636 		syscallarg(char *) path;
    637 		syscallarg(int) mode;
    638 	} */ *uap = v;
    639 	caddr_t sg = stackgap_init(p->p_emul);
    640 
    641 	LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
    642 
    643 	return sys_chmod(p, uap, retval);
    644 }
    645 
    646 int
    647 linux_sys_chown(p, v, retval)
    648 	struct proc *p;
    649 	void *v;
    650 	register_t *retval;
    651 {
    652 	struct linux_sys_chown_args /* {
    653 		syscallarg(char *) path;
    654 		syscallarg(int) uid;
    655 		syscallarg(int) gid;
    656 	} */ *uap = v;
    657 	struct sys_chown_args bca;
    658 	caddr_t sg = stackgap_init(p->p_emul);
    659 
    660 	LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
    661 
    662 	SCARG(&bca, path) = SCARG(uap, path);
    663 	SCARG(&bca, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ?
    664 		(uid_t)-1 : SCARG(uap, uid);
    665 	SCARG(&bca, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ?
    666 		(gid_t)-1 : SCARG(uap, gid);
    667 
    668 	return sys_chown(p, &bca, retval);
    669 }
    670 
    671 int
    672 linux_sys_fchown(p, v, retval)
    673 	struct proc *p;
    674 	void *v;
    675 	register_t *retval;
    676 {
    677 	struct linux_sys_fchown_args /* {
    678 		syscallarg(int) fd;
    679 		syscallarg(int) uid;
    680 		syscallarg(int) gid;
    681 	} */ *uap = v;
    682 	struct sys_fchown_args bfa;
    683 
    684 	SCARG(&bfa, fd) = SCARG(uap, fd);
    685 	SCARG(&bfa, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ?
    686 		(uid_t)-1 : SCARG(uap, uid);
    687 	SCARG(&bfa, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ?
    688 		(gid_t)-1 : SCARG(uap, gid);
    689 
    690 	return sys_fchown(p, &bfa, retval);
    691 }
    692 
    693 int
    694 linux_sys_rename(p, v, retval)
    695 	struct proc *p;
    696 	void *v;
    697 	register_t *retval;
    698 {
    699 	struct linux_sys_rename_args /* {
    700 		syscallarg(char *) from;
    701 		syscallarg(char *) to;
    702 	} */ *uap = v;
    703 	caddr_t sg = stackgap_init(p->p_emul);
    704 
    705 	LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, from));
    706 	LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, to));
    707 
    708 	return sys_rename(p, uap, retval);
    709 }
    710 
    711 int
    712 linux_sys_mkdir(p, v, retval)
    713 	struct proc *p;
    714 	void *v;
    715 	register_t *retval;
    716 {
    717 	struct linux_sys_mkdir_args /* {
    718 		syscallarg(char *) path;
    719 		syscallarg(int) mode;
    720 	} */ *uap = v;
    721 	caddr_t sg = stackgap_init(p->p_emul);
    722 
    723 	LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
    724 
    725 	return sys_mkdir(p, uap, retval);
    726 }
    727 
    728 int
    729 linux_sys_rmdir(p, v, retval)
    730 	struct proc *p;
    731 	void *v;
    732 	register_t *retval;
    733 {
    734 	struct linux_sys_rmdir_args /* {
    735 		syscallarg(char *) path;
    736 	} */ *uap = v;
    737 	caddr_t sg = stackgap_init(p->p_emul);
    738 
    739 	LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
    740 
    741 	return sys_rmdir(p, uap, retval);
    742 }
    743 
    744 int
    745 linux_sys_symlink(p, v, retval)
    746 	struct proc *p;
    747 	void *v;
    748 	register_t *retval;
    749 {
    750 	struct linux_sys_symlink_args /* {
    751 		syscallarg(char *) path;
    752 		syscallarg(char *) to;
    753 	} */ *uap = v;
    754 	caddr_t sg = stackgap_init(p->p_emul);
    755 
    756 	LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
    757 	LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, to));
    758 
    759 	return sys_symlink(p, uap, retval);
    760 }
    761 
    762 int
    763 linux_sys_readlink(p, v, retval)
    764 	struct proc *p;
    765 	void *v;
    766 	register_t *retval;
    767 {
    768 	struct linux_sys_readlink_args /* {
    769 		syscallarg(char *) name;
    770 		syscallarg(char *) buf;
    771 		syscallarg(int) count;
    772 	} */ *uap = v;
    773 	caddr_t sg = stackgap_init(p->p_emul);
    774 
    775 	LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, name));
    776 
    777 	return sys_readlink(p, uap, retval);
    778 }
    779 
    780 int
    781 linux_sys_truncate(p, v, retval)
    782 	struct proc *p;
    783 	void *v;
    784 	register_t *retval;
    785 {
    786 	struct linux_sys_truncate_args /* {
    787 		syscallarg(char *) path;
    788 		syscallarg(long) length;
    789 	} */ *uap = v;
    790 	caddr_t sg = stackgap_init(p->p_emul);
    791 
    792 	LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
    793 
    794 	return compat_43_sys_truncate(p, uap, retval);
    795 }
    796