Home | History | Annotate | Line # | Download | only in netbsd32
netbsd32_fs.c revision 1.46.8.1
      1  1.46.8.1       mjf /*	$NetBSD: netbsd32_fs.c,v 1.46.8.1 2007/12/08 18:18:59 mjf Exp $	*/
      2       1.1       mrg 
      3       1.1       mrg /*
      4       1.1       mrg  * Copyright (c) 1998, 2001 Matthew R. Green
      5       1.1       mrg  * All rights reserved.
      6       1.1       mrg  *
      7       1.1       mrg  * Redistribution and use in source and binary forms, with or without
      8       1.1       mrg  * modification, are permitted provided that the following conditions
      9       1.1       mrg  * are met:
     10       1.1       mrg  * 1. Redistributions of source code must retain the above copyright
     11       1.1       mrg  *    notice, this list of conditions and the following disclaimer.
     12       1.1       mrg  * 2. Redistributions in binary form must reproduce the above copyright
     13       1.1       mrg  *    notice, this list of conditions and the following disclaimer in the
     14       1.1       mrg  *    documentation and/or other materials provided with the distribution.
     15       1.1       mrg  * 3. The name of the author may not be used to endorse or promote products
     16       1.1       mrg  *    derived from this software without specific prior written permission.
     17       1.1       mrg  *
     18       1.1       mrg  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     19       1.1       mrg  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     20       1.1       mrg  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     21       1.1       mrg  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     22       1.1       mrg  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     23       1.1       mrg  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     24       1.1       mrg  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     25       1.1       mrg  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     26       1.1       mrg  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     27       1.1       mrg  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     28       1.1       mrg  * SUCH DAMAGE.
     29       1.1       mrg  */
     30       1.7     lukem 
     31       1.7     lukem #include <sys/cdefs.h>
     32  1.46.8.1       mjf __KERNEL_RCSID(0, "$NetBSD: netbsd32_fs.c,v 1.46.8.1 2007/12/08 18:18:59 mjf Exp $");
     33       1.1       mrg 
     34       1.1       mrg #include <sys/param.h>
     35       1.1       mrg #include <sys/systm.h>
     36       1.1       mrg #include <sys/malloc.h>
     37       1.1       mrg #include <sys/mount.h>
     38       1.1       mrg #include <sys/socket.h>
     39       1.1       mrg #include <sys/socketvar.h>
     40       1.1       mrg #include <sys/stat.h>
     41       1.1       mrg #include <sys/time.h>
     42       1.1       mrg #include <sys/ktrace.h>
     43       1.1       mrg #include <sys/resourcevar.h>
     44       1.1       mrg #include <sys/vnode.h>
     45       1.1       mrg #include <sys/file.h>
     46       1.1       mrg #include <sys/filedesc.h>
     47       1.1       mrg #include <sys/namei.h>
     48      1.18      cube #include <sys/statvfs.h>
     49       1.1       mrg #include <sys/syscallargs.h>
     50       1.1       mrg #include <sys/proc.h>
     51      1.22  christos #include <sys/dirent.h>
     52      1.27      elad #include <sys/kauth.h>
     53      1.37       dsl #include <sys/vfs_syscalls.h>
     54       1.1       mrg 
     55       1.1       mrg #include <compat/netbsd32/netbsd32.h>
     56       1.1       mrg #include <compat/netbsd32/netbsd32_syscallargs.h>
     57       1.1       mrg #include <compat/netbsd32/netbsd32_conv.h>
     58      1.28    martin #include <compat/sys/mount.h>
     59       1.1       mrg 
     60       1.1       mrg 
     61  1.46.8.1       mjf static int dofilereadv32(struct lwp *, int, struct file *, struct netbsd32_iovec *,
     62  1.46.8.1       mjf 			      int, off_t *, int, register_t *);
     63  1.46.8.1       mjf static int dofilewritev32(struct lwp *, int, struct file *, struct netbsd32_iovec *,
     64  1.46.8.1       mjf 			       int,  off_t *, int, register_t *);
     65       1.1       mrg 
     66      1.45       dsl struct iovec *
     67      1.45       dsl netbsd32_get_iov(struct netbsd32_iovec *iov32, int iovlen, struct iovec *aiov,
     68      1.45       dsl     int aiov_len)
     69      1.45       dsl {
     70      1.45       dsl #define N_IOV32 8
     71      1.45       dsl 	struct netbsd32_iovec aiov32[N_IOV32];
     72      1.45       dsl 	struct iovec *iov = aiov;
     73      1.45       dsl 	struct iovec *iovp;
     74      1.45       dsl 	int i, n, j;
     75      1.45       dsl 	int error;
     76      1.45       dsl 
     77      1.45       dsl 	if (iovlen < 0 || iovlen > IOV_MAX)
     78      1.45       dsl 		return NULL;
     79      1.45       dsl 
     80      1.45       dsl 	if (iovlen > aiov_len)
     81      1.45       dsl 		iov = malloc(iovlen * sizeof (*iov), M_TEMP, M_WAITOK);
     82      1.45       dsl 
     83      1.45       dsl 	iovp = iov;
     84      1.45       dsl 	for (i = 0; i < iovlen; iov32 += N_IOV32, i += N_IOV32) {
     85      1.45       dsl 		n = iovlen - i;
     86      1.45       dsl 		if (n > N_IOV32)
     87      1.45       dsl 			n = N_IOV32;
     88      1.45       dsl 		error = copyin(iov32, aiov32, n * sizeof (*iov32));
     89      1.45       dsl 		if (error != 0) {
     90      1.45       dsl 			if (iov != aiov)
     91      1.45       dsl 				free(iov, M_TEMP);
     92      1.45       dsl 			return NULL;
     93      1.45       dsl 		}
     94      1.45       dsl 		for (j = 0; j < n; iovp++, j++) {
     95      1.45       dsl 			iovp->iov_base = NETBSD32PTR64(aiov32[j].iov_base);
     96      1.45       dsl 			iovp->iov_len = aiov32[j].iov_len;
     97      1.45       dsl 		}
     98      1.45       dsl 	}
     99      1.45       dsl 	return iov;
    100      1.45       dsl #undef N_IOV32
    101      1.45       dsl }
    102      1.45       dsl 
    103       1.1       mrg int
    104      1.11   thorpej netbsd32_readv(l, v, retval)
    105      1.11   thorpej 	struct lwp *l;
    106       1.1       mrg 	void *v;
    107       1.1       mrg 	register_t *retval;
    108       1.1       mrg {
    109       1.1       mrg 	struct netbsd32_readv_args /* {
    110       1.1       mrg 		syscallarg(int) fd;
    111       1.1       mrg 		syscallarg(const netbsd32_iovecp_t) iovp;
    112       1.1       mrg 		syscallarg(int) iovcnt;
    113       1.1       mrg 	} */ *uap = v;
    114       1.1       mrg 	int fd = SCARG(uap, fd);
    115      1.11   thorpej 	struct proc *p = l->l_proc;
    116       1.1       mrg 	struct file *fp;
    117       1.1       mrg 	struct filedesc *fdp = p->p_fd;
    118       1.1       mrg 
    119       1.6   thorpej 	if ((fp = fd_getfile(fdp, fd)) == NULL)
    120       1.6   thorpej 		return (EBADF);
    121       1.6   thorpej 
    122       1.6   thorpej 	if ((fp->f_flag & FREAD) == 0)
    123       1.1       mrg 		return (EBADF);
    124       1.1       mrg 
    125       1.9  jdolecek 	FILE_USE(fp);
    126       1.9  jdolecek 
    127      1.23  christos 	return (dofilereadv32(l, fd, fp,
    128      1.39       dsl 	    (struct netbsd32_iovec *)SCARG_P32(uap, iovp),
    129      1.10       scw 	    SCARG(uap, iovcnt), &fp->f_offset, FOF_UPDATE_OFFSET, retval));
    130       1.1       mrg }
    131       1.1       mrg 
    132       1.1       mrg /* Damn thing copies in the iovec! */
    133       1.1       mrg int
    134      1.23  christos dofilereadv32(l, fd, fp, iovp, iovcnt, offset, flags, retval)
    135      1.23  christos 	struct lwp *l;
    136       1.1       mrg 	int fd;
    137       1.1       mrg 	struct file *fp;
    138       1.1       mrg 	struct netbsd32_iovec *iovp;
    139       1.1       mrg 	int iovcnt;
    140       1.1       mrg 	off_t *offset;
    141       1.1       mrg 	int flags;
    142       1.1       mrg 	register_t *retval;
    143       1.1       mrg {
    144       1.1       mrg 	struct uio auio;
    145       1.1       mrg 	struct iovec *iov;
    146       1.1       mrg 	struct iovec *needfree;
    147       1.1       mrg 	struct iovec aiov[UIO_SMALLIOV];
    148       1.1       mrg 	long i, cnt, error = 0;
    149       1.1       mrg 	u_int iovlen;
    150       1.1       mrg 	struct iovec *ktriov = NULL;
    151       1.1       mrg 
    152       1.1       mrg 	/* note: can't use iovlen until iovcnt is validated */
    153       1.1       mrg 	iovlen = iovcnt * sizeof(struct iovec);
    154       1.1       mrg 	if ((u_int)iovcnt > UIO_SMALLIOV) {
    155       1.9  jdolecek 		if ((u_int)iovcnt > IOV_MAX) {
    156       1.9  jdolecek 			error = EINVAL;
    157       1.9  jdolecek 			goto out;
    158       1.9  jdolecek 		}
    159       1.9  jdolecek 		iov = malloc(iovlen, M_IOV, M_WAITOK);
    160       1.1       mrg 		needfree = iov;
    161       1.1       mrg 	} else if ((u_int)iovcnt > 0) {
    162       1.1       mrg 		iov = aiov;
    163       1.1       mrg 		needfree = NULL;
    164       1.9  jdolecek 	} else {
    165       1.9  jdolecek 		error = EINVAL;
    166       1.9  jdolecek 		goto out;
    167       1.9  jdolecek 	}
    168       1.1       mrg 
    169       1.1       mrg 	auio.uio_iov = iov;
    170       1.1       mrg 	auio.uio_iovcnt = iovcnt;
    171       1.1       mrg 	auio.uio_rw = UIO_READ;
    172      1.24      yamt 	auio.uio_vmspace = l->l_proc->p_vmspace;
    173       1.1       mrg 	error = netbsd32_to_iovecin(iovp, iov, iovcnt);
    174       1.1       mrg 	if (error)
    175       1.1       mrg 		goto done;
    176       1.1       mrg 	auio.uio_resid = 0;
    177       1.1       mrg 	for (i = 0; i < iovcnt; i++) {
    178       1.1       mrg 		auio.uio_resid += iov->iov_len;
    179       1.1       mrg 		/*
    180       1.1       mrg 		 * Reads return ssize_t because -1 is returned on error.
    181       1.1       mrg 		 * Therefore we must restrict the length to SSIZE_MAX to
    182       1.1       mrg 		 * avoid garbage return values.
    183       1.1       mrg 		 */
    184       1.1       mrg 		if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
    185       1.1       mrg 			error = EINVAL;
    186       1.1       mrg 			goto done;
    187       1.1       mrg 		}
    188       1.1       mrg 		iov++;
    189       1.1       mrg 	}
    190      1.46        ad 
    191       1.1       mrg 	/*
    192       1.1       mrg 	 * if tracing, save a copy of iovec
    193       1.1       mrg 	 */
    194      1.46        ad 	if (ktrpoint(KTR_GENIO)) {
    195       1.9  jdolecek 		ktriov = malloc(iovlen, M_TEMP, M_WAITOK);
    196      1.36  christos 		memcpy((void *)ktriov, (void *)auio.uio_iov, iovlen);
    197       1.1       mrg 	}
    198      1.46        ad 
    199       1.1       mrg 	cnt = auio.uio_resid;
    200       1.1       mrg 	error = (*fp->f_ops->fo_read)(fp, offset, &auio, fp->f_cred, flags);
    201       1.1       mrg 	if (error)
    202       1.1       mrg 		if (auio.uio_resid != cnt && (error == ERESTART ||
    203       1.1       mrg 		    error == EINTR || error == EWOULDBLOCK))
    204       1.1       mrg 			error = 0;
    205       1.1       mrg 	cnt -= auio.uio_resid;
    206      1.46        ad 
    207      1.46        ad 	if (ktriov != NULL) {
    208      1.46        ad 		ktrgeniov(fd, UIO_READ, ktriov, cnt, error);
    209       1.9  jdolecek 		free(ktriov, M_TEMP);
    210       1.1       mrg 	}
    211      1.46        ad 
    212       1.1       mrg 	*retval = cnt;
    213       1.1       mrg done:
    214       1.1       mrg 	if (needfree)
    215       1.9  jdolecek 		free(needfree, M_IOV);
    216       1.9  jdolecek out:
    217      1.23  christos 	FILE_UNUSE(fp, l);
    218       1.1       mrg 	return (error);
    219       1.1       mrg }
    220       1.1       mrg 
    221       1.1       mrg int
    222      1.11   thorpej netbsd32_writev(l, v, retval)
    223      1.11   thorpej 	struct lwp *l;
    224       1.1       mrg 	void *v;
    225       1.1       mrg 	register_t *retval;
    226       1.1       mrg {
    227       1.1       mrg 	struct netbsd32_writev_args /* {
    228       1.1       mrg 		syscallarg(int) fd;
    229       1.1       mrg 		syscallarg(const netbsd32_iovecp_t) iovp;
    230       1.1       mrg 		syscallarg(int) iovcnt;
    231       1.1       mrg 	} */ *uap = v;
    232       1.1       mrg 	int fd = SCARG(uap, fd);
    233       1.1       mrg 	struct file *fp;
    234      1.11   thorpej 	struct proc *p = l->l_proc;
    235       1.1       mrg 	struct filedesc *fdp = p->p_fd;
    236       1.1       mrg 
    237       1.6   thorpej 	if ((fp = fd_getfile(fdp, fd)) == NULL)
    238       1.6   thorpej 		return (EBADF);
    239       1.6   thorpej 
    240       1.6   thorpej 	if ((fp->f_flag & FWRITE) == 0)
    241       1.1       mrg 		return (EBADF);
    242       1.1       mrg 
    243       1.9  jdolecek 	FILE_USE(fp);
    244       1.9  jdolecek 
    245      1.23  christos 	return (dofilewritev32(l, fd, fp,
    246      1.39       dsl 	    (struct netbsd32_iovec *)SCARG_P32(uap, iovp),
    247      1.10       scw 	    SCARG(uap, iovcnt), &fp->f_offset, FOF_UPDATE_OFFSET, retval));
    248       1.1       mrg }
    249       1.1       mrg 
    250       1.1       mrg int
    251      1.23  christos dofilewritev32(l, fd, fp, iovp, iovcnt, offset, flags, retval)
    252      1.23  christos 	struct lwp *l;
    253       1.1       mrg 	int fd;
    254       1.1       mrg 	struct file *fp;
    255       1.1       mrg 	struct netbsd32_iovec *iovp;
    256       1.1       mrg 	int iovcnt;
    257       1.1       mrg 	off_t *offset;
    258       1.1       mrg 	int flags;
    259       1.1       mrg 	register_t *retval;
    260       1.1       mrg {
    261       1.1       mrg 	struct uio auio;
    262       1.1       mrg 	struct iovec *iov;
    263       1.1       mrg 	struct iovec *needfree;
    264       1.1       mrg 	struct iovec aiov[UIO_SMALLIOV];
    265      1.23  christos 	struct proc *p = l->l_proc;
    266       1.1       mrg 	long i, cnt, error = 0;
    267       1.1       mrg 	u_int iovlen;
    268       1.1       mrg 	struct iovec *ktriov = NULL;
    269       1.1       mrg 
    270       1.1       mrg 	/* note: can't use iovlen until iovcnt is validated */
    271       1.1       mrg 	iovlen = iovcnt * sizeof(struct iovec);
    272       1.1       mrg 	if ((u_int)iovcnt > UIO_SMALLIOV) {
    273       1.9  jdolecek 		if ((u_int)iovcnt > IOV_MAX) {
    274       1.9  jdolecek 			error = EINVAL;
    275       1.9  jdolecek 			goto out;
    276       1.9  jdolecek 		}
    277       1.9  jdolecek 		iov = malloc(iovlen, M_IOV, M_WAITOK);
    278       1.1       mrg 		needfree = iov;
    279       1.1       mrg 	} else if ((u_int)iovcnt > 0) {
    280       1.1       mrg 		iov = aiov;
    281       1.1       mrg 		needfree = NULL;
    282       1.9  jdolecek 	} else {
    283       1.9  jdolecek 		error = EINVAL;
    284       1.9  jdolecek 		goto out;
    285       1.9  jdolecek 	}
    286       1.1       mrg 
    287       1.1       mrg 	auio.uio_iov = iov;
    288       1.1       mrg 	auio.uio_iovcnt = iovcnt;
    289       1.1       mrg 	auio.uio_rw = UIO_WRITE;
    290      1.24      yamt 	auio.uio_vmspace = l->l_proc->p_vmspace;
    291       1.1       mrg 	error = netbsd32_to_iovecin(iovp, iov, iovcnt);
    292       1.1       mrg 	if (error)
    293       1.1       mrg 		goto done;
    294       1.1       mrg 	auio.uio_resid = 0;
    295       1.1       mrg 	for (i = 0; i < iovcnt; i++) {
    296       1.1       mrg 		auio.uio_resid += iov->iov_len;
    297       1.1       mrg 		/*
    298       1.1       mrg 		 * Writes return ssize_t because -1 is returned on error.
    299       1.1       mrg 		 * Therefore we must restrict the length to SSIZE_MAX to
    300       1.1       mrg 		 * avoid garbage return values.
    301       1.1       mrg 		 */
    302       1.1       mrg 		if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
    303       1.1       mrg 			error = EINVAL;
    304       1.1       mrg 			goto done;
    305       1.1       mrg 		}
    306       1.1       mrg 		iov++;
    307       1.1       mrg 	}
    308      1.46        ad 
    309       1.1       mrg 	/*
    310       1.1       mrg 	 * if tracing, save a copy of iovec
    311       1.1       mrg 	 */
    312      1.46        ad 	if (ktrpoint(KTR_GENIO))  {
    313       1.9  jdolecek 		ktriov = malloc(iovlen, M_TEMP, M_WAITOK);
    314      1.36  christos 		memcpy((void *)ktriov, (void *)auio.uio_iov, iovlen);
    315       1.1       mrg 	}
    316      1.46        ad 
    317       1.1       mrg 	cnt = auio.uio_resid;
    318       1.1       mrg 	error = (*fp->f_ops->fo_write)(fp, offset, &auio, fp->f_cred, flags);
    319       1.1       mrg 	if (error) {
    320       1.1       mrg 		if (auio.uio_resid != cnt && (error == ERESTART ||
    321       1.1       mrg 		    error == EINTR || error == EWOULDBLOCK))
    322       1.1       mrg 			error = 0;
    323      1.44        ad 		if (error == EPIPE) {
    324      1.44        ad 			mutex_enter(&proclist_mutex);
    325      1.14      fvdl 			psignal(p, SIGPIPE);
    326      1.44        ad 			mutex_exit(&proclist_mutex);
    327      1.44        ad 		}
    328       1.1       mrg 	}
    329       1.1       mrg 	cnt -= auio.uio_resid;
    330      1.46        ad 	if (ktriov != NULL) {
    331      1.46        ad 		ktrgenio(fd, UIO_WRITE, ktriov, cnt, error);
    332       1.9  jdolecek 		free(ktriov, M_TEMP);
    333       1.1       mrg 	}
    334       1.1       mrg 	*retval = cnt;
    335       1.1       mrg done:
    336       1.1       mrg 	if (needfree)
    337       1.9  jdolecek 		free(needfree, M_IOV);
    338       1.9  jdolecek out:
    339      1.23  christos 	FILE_UNUSE(fp, l);
    340       1.1       mrg 	return (error);
    341       1.1       mrg }
    342       1.1       mrg 
    343      1.43       dsl /*
    344      1.43       dsl  * Common routine to set access and modification times given a vnode.
    345      1.43       dsl  */
    346      1.43       dsl static int
    347      1.43       dsl get_utimes32(const netbsd32_timevalp_t *tptr, struct timeval *tv,
    348      1.43       dsl     struct timeval **tvp)
    349      1.43       dsl {
    350      1.43       dsl 	int error;
    351      1.43       dsl 	struct netbsd32_timeval tv32[2];
    352      1.43       dsl 
    353      1.43       dsl 	if (tptr == NULL) {
    354      1.43       dsl 		*tvp = NULL;
    355      1.43       dsl 		return 0;
    356      1.43       dsl 	}
    357      1.43       dsl 
    358      1.43       dsl 	error = copyin(tptr, tv32, sizeof(tv32));
    359      1.43       dsl 	if (error)
    360      1.43       dsl 		return error;
    361      1.43       dsl 	netbsd32_to_timeval(&tv32[0], &tv[0]);
    362      1.43       dsl 	netbsd32_to_timeval(&tv32[1], &tv[1]);
    363      1.43       dsl 
    364      1.43       dsl 	*tvp = tv;
    365      1.43       dsl 	return 0;
    366      1.43       dsl }
    367      1.43       dsl 
    368       1.1       mrg int
    369      1.11   thorpej netbsd32_utimes(l, v, retval)
    370      1.11   thorpej 	struct lwp *l;
    371       1.1       mrg 	void *v;
    372       1.1       mrg 	register_t *retval;
    373       1.1       mrg {
    374       1.1       mrg 	struct netbsd32_utimes_args /* {
    375       1.1       mrg 		syscallarg(const netbsd32_charp) path;
    376       1.1       mrg 		syscallarg(const netbsd32_timevalp_t) tptr;
    377       1.1       mrg 	} */ *uap = v;
    378       1.1       mrg 	int error;
    379      1.43       dsl 	struct timeval tv[2], *tvp;
    380       1.1       mrg 
    381      1.43       dsl 	error = get_utimes32(SCARG_P32(uap, tptr), tv, &tvp);
    382      1.43       dsl 	if (error != 0)
    383      1.43       dsl 		return error;
    384       1.1       mrg 
    385      1.43       dsl 	return do_sys_utimes(l, NULL, SCARG_P32(uap, path), FOLLOW,
    386      1.43       dsl 			    tvp, UIO_SYSSPACE);
    387       1.1       mrg }
    388       1.1       mrg 
    389      1.42       dsl static int
    390      1.42       dsl netbds32_copyout_statvfs(const void *kp, void *up, size_t len)
    391      1.42       dsl {
    392      1.42       dsl 	struct netbsd32_statvfs *sbuf_32;
    393      1.42       dsl 	int error;
    394      1.42       dsl 
    395      1.42       dsl 	sbuf_32 = malloc(sizeof *sbuf_32, M_TEMP, M_WAITOK);
    396      1.42       dsl 	netbsd32_from_statvfs(kp, sbuf_32);
    397      1.42       dsl 	error = copyout(sbuf_32, up, sizeof(*sbuf_32));
    398      1.42       dsl 	free(sbuf_32, M_TEMP);
    399      1.42       dsl 
    400      1.42       dsl 	return error;
    401      1.42       dsl }
    402      1.42       dsl 
    403       1.1       mrg int
    404      1.18      cube netbsd32_statvfs1(l, v, retval)
    405      1.11   thorpej 	struct lwp *l;
    406       1.1       mrg 	void *v;
    407       1.1       mrg 	register_t *retval;
    408       1.1       mrg {
    409      1.18      cube 	struct netbsd32_statvfs1_args /* {
    410       1.1       mrg 		syscallarg(const netbsd32_charp) path;
    411      1.18      cube 		syscallarg(netbsd32_statvfsp_t) buf;
    412      1.18      cube 		syscallarg(int) flags;
    413       1.1       mrg 	} */ *uap = v;
    414      1.42       dsl 	struct statvfs *sb;
    415       1.1       mrg 	int error;
    416       1.1       mrg 
    417      1.42       dsl 	sb = STATVFSBUF_GET();
    418      1.42       dsl 	error = do_sys_pstatvfs(l, SCARG_P32(uap, path), SCARG(uap, flags), sb);
    419      1.42       dsl 	if (error == 0)
    420      1.42       dsl 		error = netbds32_copyout_statvfs(sb, SCARG_P32(uap, buf), 0);
    421      1.42       dsl 	STATVFSBUF_PUT(sb);
    422      1.42       dsl 	return error;
    423       1.1       mrg }
    424       1.1       mrg 
    425       1.1       mrg int
    426      1.18      cube netbsd32_fstatvfs1(l, v, retval)
    427      1.11   thorpej 	struct lwp *l;
    428       1.1       mrg 	void *v;
    429       1.1       mrg 	register_t *retval;
    430       1.1       mrg {
    431      1.18      cube 	struct netbsd32_fstatvfs1_args /* {
    432       1.1       mrg 		syscallarg(int) fd;
    433      1.18      cube 		syscallarg(netbsd32_statvfsp_t) buf;
    434      1.18      cube 		syscallarg(int) flags;
    435       1.1       mrg 	} */ *uap = v;
    436      1.42       dsl 	struct statvfs *sb;
    437       1.1       mrg 	int error;
    438       1.1       mrg 
    439      1.42       dsl 	sb = STATVFSBUF_GET();
    440      1.42       dsl 	error = do_sys_fstatvfs(l, SCARG(uap, fd), SCARG(uap, flags), sb);
    441      1.42       dsl 	if (error == 0)
    442      1.42       dsl 		error = netbds32_copyout_statvfs(sb, SCARG_P32(uap, buf), 0);
    443      1.42       dsl 	STATVFSBUF_PUT(sb);
    444      1.18      cube 	return error;
    445      1.18      cube }
    446      1.18      cube 
    447      1.18      cube int
    448      1.18      cube netbsd32_getvfsstat(l, v, retval)
    449      1.18      cube 	struct lwp *l;
    450      1.18      cube 	void *v;
    451      1.18      cube 	register_t *retval;
    452      1.18      cube {
    453      1.18      cube 	struct netbsd32_getvfsstat_args /* {
    454      1.18      cube 		syscallarg(netbsd32_statvfsp_t) buf;
    455      1.18      cube 		syscallarg(netbsd32_size_t) bufsize;
    456      1.18      cube 		syscallarg(int) flags;
    457      1.18      cube 	} */ *uap = v;
    458      1.18      cube 
    459      1.42       dsl 	return do_sys_getvfsstat(l, SCARG_P32(uap, buf), SCARG(uap, bufsize),
    460      1.42       dsl 	    SCARG(uap, flags), netbds32_copyout_statvfs,
    461      1.42       dsl 	    sizeof (struct netbsd32_statvfs), retval);
    462      1.18      cube }
    463      1.18      cube 
    464      1.18      cube int
    465      1.32    martin netbsd32___fhstatvfs140(l, v, retval)
    466      1.18      cube 	struct lwp *l;
    467      1.18      cube 	void *v;
    468      1.18      cube 	register_t *retval;
    469      1.18      cube {
    470      1.32    martin 	struct netbsd32___fhstatvfs140_args /* {
    471      1.32    martin 		syscallarg(const netbsd32_pointer_t) fhp;
    472      1.32    martin 		syscallarg(netbsd32_size_t) fh_size;
    473      1.18      cube 		syscallarg(netbsd32_statvfsp_t) buf;
    474      1.18      cube 		syscallarg(int) flags;
    475      1.18      cube 	} */ *uap = v;
    476      1.42       dsl 	struct statvfs *sb;
    477      1.18      cube 	int error;
    478      1.18      cube 
    479      1.42       dsl 	sb = STATVFSBUF_GET();
    480      1.42       dsl 	error = do_fhstatvfs(l, SCARG_P32(uap, fhp), SCARG(uap, fh_size), sb,
    481      1.42       dsl 	    SCARG(uap, flags));
    482      1.42       dsl 
    483      1.42       dsl 	if (error == 0)
    484      1.42       dsl 		error = netbds32_copyout_statvfs(sb, SCARG_P32(uap, buf), 0);
    485      1.42       dsl 	STATVFSBUF_PUT(sb);
    486      1.18      cube 
    487      1.42       dsl 	return error;
    488       1.1       mrg }
    489       1.1       mrg 
    490       1.1       mrg int
    491      1.11   thorpej netbsd32_futimes(l, v, retval)
    492      1.11   thorpej 	struct lwp *l;
    493       1.1       mrg 	void *v;
    494       1.1       mrg 	register_t *retval;
    495       1.1       mrg {
    496       1.1       mrg 	struct netbsd32_futimes_args /* {
    497       1.1       mrg 		syscallarg(int) fd;
    498       1.1       mrg 		syscallarg(const netbsd32_timevalp_t) tptr;
    499       1.1       mrg 	} */ *uap = v;
    500       1.1       mrg 	int error;
    501       1.1       mrg 	struct file *fp;
    502      1.43       dsl 	struct timeval tv[2], *tvp;
    503      1.43       dsl 
    504      1.43       dsl 	error = get_utimes32(SCARG_P32(uap, tptr), tv, &tvp);
    505      1.43       dsl 	if (error != 0)
    506      1.43       dsl 		return error;
    507       1.1       mrg 
    508       1.1       mrg 	/* getvnode() will use the descriptor for us */
    509      1.43       dsl 	if ((error = getvnode(l->l_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
    510       1.1       mrg 		return (error);
    511       1.1       mrg 
    512      1.43       dsl 	error = do_sys_utimes(l, fp->f_data, NULL, 0, tvp, UIO_SYSSPACE);
    513      1.43       dsl 
    514      1.23  christos 	FILE_UNUSE(fp, l);
    515       1.1       mrg 	return (error);
    516       1.1       mrg }
    517       1.1       mrg 
    518       1.1       mrg int
    519      1.22  christos netbsd32_sys___getdents30(l, v, retval)
    520      1.11   thorpej 	struct lwp *l;
    521       1.1       mrg 	void *v;
    522       1.1       mrg 	register_t *retval;
    523       1.1       mrg {
    524      1.22  christos 	struct netbsd32_sys___getdents30_args /* {
    525       1.1       mrg 		syscallarg(int) fd;
    526       1.1       mrg 		syscallarg(netbsd32_charp) buf;
    527       1.1       mrg 		syscallarg(netbsd32_size_t) count;
    528       1.1       mrg 	} */ *uap = v;
    529       1.1       mrg 	struct file *fp;
    530       1.1       mrg 	int error, done;
    531      1.11   thorpej 	struct proc *p = l->l_proc;
    532       1.1       mrg 
    533       1.1       mrg 	/* getvnode() will use the descriptor for us */
    534       1.1       mrg 	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
    535       1.1       mrg 		return (error);
    536       1.1       mrg 	if ((fp->f_flag & FREAD) == 0) {
    537       1.1       mrg 		error = EBADF;
    538       1.1       mrg 		goto out;
    539       1.1       mrg 	}
    540      1.39       dsl 	error = vn_readdir(fp, SCARG_P32(uap, buf),
    541      1.23  christos 	    UIO_USERSPACE, SCARG(uap, count), &done, l, 0, 0);
    542       1.1       mrg 	*retval = done;
    543       1.1       mrg  out:
    544      1.23  christos 	FILE_UNUSE(fp, l);
    545       1.1       mrg 	return (error);
    546       1.1       mrg }
    547       1.1       mrg 
    548       1.1       mrg int
    549      1.11   thorpej netbsd32_lutimes(l, v, retval)
    550      1.11   thorpej 	struct lwp *l;
    551       1.1       mrg 	void *v;
    552       1.1       mrg 	register_t *retval;
    553       1.1       mrg {
    554       1.1       mrg 	struct netbsd32_lutimes_args /* {
    555       1.1       mrg 		syscallarg(const netbsd32_charp) path;
    556       1.1       mrg 		syscallarg(const netbsd32_timevalp_t) tptr;
    557       1.1       mrg 	} */ *uap = v;
    558       1.1       mrg 	int error;
    559      1.43       dsl 	struct timeval tv[2], *tvp;
    560       1.1       mrg 
    561      1.43       dsl 	error = get_utimes32(SCARG_P32(uap, tptr), tv, &tvp);
    562      1.43       dsl 	if (error != 0)
    563      1.43       dsl 		return error;
    564       1.1       mrg 
    565      1.43       dsl 	return do_sys_utimes(l, NULL, SCARG_P32(uap, path), NOFOLLOW,
    566      1.43       dsl 			    tvp, UIO_SYSSPACE);
    567       1.1       mrg }
    568       1.1       mrg 
    569       1.1       mrg int
    570      1.22  christos netbsd32_sys___stat30(l, v, retval)
    571      1.11   thorpej 	struct lwp *l;
    572       1.1       mrg 	void *v;
    573       1.1       mrg 	register_t *retval;
    574       1.1       mrg {
    575      1.22  christos 	struct netbsd32_sys___stat30_args /* {
    576       1.1       mrg 		syscallarg(const netbsd32_charp) path;
    577       1.1       mrg 		syscallarg(netbsd32_statp_t) ub;
    578       1.1       mrg 	} */ *uap = v;
    579       1.1       mrg 	struct netbsd32_stat sb32;
    580       1.1       mrg 	struct stat sb;
    581       1.1       mrg 	int error;
    582       1.1       mrg 	const char *path;
    583       1.1       mrg 
    584      1.39       dsl 	path = SCARG_P32(uap, path);
    585       1.1       mrg 
    586      1.37       dsl 	error = do_sys_stat(l, path, FOLLOW, &sb);
    587      1.41       dsl 	if (error)
    588      1.41       dsl 		return (error);
    589      1.22  christos 	netbsd32_from___stat30(&sb, &sb32);
    590      1.39       dsl 	error = copyout(&sb32, SCARG_P32(uap, ub), sizeof(sb32));
    591       1.1       mrg 	return (error);
    592       1.1       mrg }
    593       1.1       mrg 
    594       1.1       mrg int
    595      1.22  christos netbsd32_sys___fstat30(l, v, retval)
    596      1.11   thorpej 	struct lwp *l;
    597       1.1       mrg 	void *v;
    598       1.1       mrg 	register_t *retval;
    599       1.1       mrg {
    600      1.22  christos 	struct netbsd32_sys___fstat30_args /* {
    601       1.1       mrg 		syscallarg(int) fd;
    602       1.1       mrg 		syscallarg(netbsd32_statp_t) sb;
    603       1.1       mrg 	} */ *uap = v;
    604       1.1       mrg 	int fd = SCARG(uap, fd);
    605      1.14      fvdl 	struct proc *p = l->l_proc;
    606      1.14      fvdl 	struct filedesc *fdp = p->p_fd;
    607       1.1       mrg 	struct file *fp;
    608       1.1       mrg 	struct netbsd32_stat sb32;
    609       1.1       mrg 	struct stat ub;
    610       1.1       mrg 	int error = 0;
    611       1.1       mrg 
    612       1.6   thorpej 	if ((fp = fd_getfile(fdp, fd)) == NULL)
    613       1.1       mrg 		return (EBADF);
    614       1.1       mrg 
    615       1.3  jdolecek 	FILE_USE(fp);
    616      1.23  christos 	error = (*fp->f_ops->fo_stat)(fp, &ub, l);
    617      1.23  christos 	FILE_UNUSE(fp, l);
    618       1.3  jdolecek 
    619       1.1       mrg 	if (error == 0) {
    620      1.22  christos 		netbsd32_from___stat30(&ub, &sb32);
    621      1.39       dsl 		error = copyout(&sb32, SCARG_P32(uap, sb), sizeof(sb32));
    622       1.1       mrg 	}
    623       1.1       mrg 	return (error);
    624       1.1       mrg }
    625       1.1       mrg 
    626       1.1       mrg int
    627      1.22  christos netbsd32_sys___lstat30(l, v, retval)
    628      1.11   thorpej 	struct lwp *l;
    629       1.1       mrg 	void *v;
    630       1.1       mrg 	register_t *retval;
    631       1.1       mrg {
    632      1.22  christos 	struct netbsd32_sys___lstat30_args /* {
    633       1.1       mrg 		syscallarg(const netbsd32_charp) path;
    634       1.1       mrg 		syscallarg(netbsd32_statp_t) ub;
    635       1.1       mrg 	} */ *uap = v;
    636       1.1       mrg 	struct netbsd32_stat sb32;
    637       1.1       mrg 	struct stat sb;
    638       1.1       mrg 	int error;
    639       1.1       mrg 	const char *path;
    640       1.1       mrg 
    641      1.39       dsl 	path = SCARG_P32(uap, path);
    642       1.1       mrg 
    643      1.37       dsl 	error = do_sys_stat(l, path, NOFOLLOW, &sb);
    644       1.1       mrg 	if (error)
    645       1.1       mrg 		return (error);
    646      1.22  christos 	netbsd32_from___stat30(&sb, &sb32);
    647      1.39       dsl 	error = copyout(&sb32, SCARG_P32(uap, ub), sizeof(sb32));
    648       1.1       mrg 	return (error);
    649       1.1       mrg }
    650       1.1       mrg 
    651      1.32    martin int netbsd32___fhstat40(l, v, retval)
    652      1.26      cube 	struct lwp *l;
    653      1.26      cube 	void *v;
    654      1.26      cube 	register_t *retval;
    655      1.26      cube {
    656      1.32    martin 	struct netbsd32___fhstat40_args /* {
    657      1.32    martin 		syscallarg(const netbsd32_pointer_t) fhp;
    658      1.32    martin 		syscallarg(netbsd32_size_t) fh_size;
    659      1.26      cube 		syscallarg(netbsd32_statp_t) sb;
    660      1.26      cube 	} */ *uap = v;
    661      1.26      cube 	struct stat sb;
    662      1.26      cube 	struct netbsd32_stat sb32;
    663      1.26      cube 	int error;
    664      1.26      cube 
    665      1.42       dsl 	error = do_fhstat(l, SCARG_P32(uap, fhp), SCARG(uap, fh_size), &sb);
    666      1.42       dsl 	if (error != 0) {
    667      1.42       dsl 		netbsd32_from___stat30(&sb, &sb32);
    668      1.42       dsl 		error = copyout(&sb32, SCARG_P32(uap, sb), sizeof(sb));
    669      1.42       dsl 	}
    670      1.29    martin 	return error;
    671      1.26      cube }
    672      1.26      cube 
    673       1.1       mrg int
    674      1.11   thorpej netbsd32_preadv(l, v, retval)
    675      1.11   thorpej 	struct lwp *l;
    676       1.1       mrg 	void *v;
    677       1.1       mrg 	register_t *retval;
    678       1.1       mrg {
    679       1.1       mrg 	struct netbsd32_preadv_args /* {
    680       1.1       mrg 		syscallarg(int) fd;
    681       1.1       mrg 		syscallarg(const netbsd32_iovecp_t) iovp;
    682       1.1       mrg 		syscallarg(int) iovcnt;
    683       1.1       mrg 		syscallarg(int) pad;
    684       1.1       mrg 		syscallarg(off_t) offset;
    685       1.1       mrg 	} */ *uap = v;
    686      1.14      fvdl 	struct proc *p = l->l_proc;
    687      1.14      fvdl 	struct filedesc *fdp = p->p_fd;
    688       1.1       mrg 	struct file *fp;
    689       1.1       mrg 	struct vnode *vp;
    690       1.1       mrg 	off_t offset;
    691       1.1       mrg 	int error, fd = SCARG(uap, fd);
    692       1.1       mrg 
    693       1.6   thorpej 	if ((fp = fd_getfile(fdp, fd)) == NULL)
    694       1.6   thorpej 		return (EBADF);
    695       1.6   thorpej 
    696       1.6   thorpej 	if ((fp->f_flag & FREAD) == 0)
    697       1.1       mrg 		return (EBADF);
    698       1.1       mrg 
    699       1.9  jdolecek 	FILE_USE(fp);
    700       1.9  jdolecek 
    701       1.1       mrg 	vp = (struct vnode *)fp->f_data;
    702       1.9  jdolecek 	if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
    703       1.9  jdolecek 		error = ESPIPE;
    704       1.9  jdolecek 		goto out;
    705       1.9  jdolecek 	}
    706       1.1       mrg 
    707       1.1       mrg 	offset = SCARG(uap, offset);
    708       1.1       mrg 
    709       1.1       mrg 	/*
    710       1.1       mrg 	 * XXX This works because no file systems actually
    711       1.1       mrg 	 * XXX take any action on the seek operation.
    712       1.1       mrg 	 */
    713       1.1       mrg 	if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
    714       1.9  jdolecek 		goto out;
    715       1.1       mrg 
    716      1.39       dsl 	return (dofilereadv32(l, fd, fp, SCARG_P32(uap, iovp),
    717      1.10       scw 	    SCARG(uap, iovcnt), &offset, 0, retval));
    718       1.9  jdolecek 
    719       1.9  jdolecek out:
    720      1.23  christos 	FILE_UNUSE(fp, l);
    721       1.9  jdolecek 	return (error);
    722       1.1       mrg }
    723       1.1       mrg 
    724       1.1       mrg int
    725      1.11   thorpej netbsd32_pwritev(l, v, retval)
    726      1.11   thorpej 	struct lwp *l;
    727       1.1       mrg 	void *v;
    728       1.1       mrg 	register_t *retval;
    729       1.1       mrg {
    730       1.1       mrg 	struct netbsd32_pwritev_args /* {
    731       1.1       mrg 		syscallarg(int) fd;
    732       1.1       mrg 		syscallarg(const netbsd32_iovecp_t) iovp;
    733       1.1       mrg 		syscallarg(int) iovcnt;
    734       1.1       mrg 		syscallarg(int) pad;
    735       1.1       mrg 		syscallarg(off_t) offset;
    736       1.1       mrg 	} */ *uap = v;
    737      1.14      fvdl 	struct proc *p = l->l_proc;
    738      1.14      fvdl 	struct filedesc *fdp = p->p_fd;
    739       1.1       mrg 	struct file *fp;
    740       1.1       mrg 	struct vnode *vp;
    741       1.1       mrg 	off_t offset;
    742       1.1       mrg 	int error, fd = SCARG(uap, fd);
    743       1.1       mrg 
    744       1.6   thorpej 	if ((fp = fd_getfile(fdp, fd)) == NULL)
    745       1.6   thorpej 		return (EBADF);
    746       1.6   thorpej 
    747       1.6   thorpej 	if ((fp->f_flag & FWRITE) == 0)
    748       1.1       mrg 		return (EBADF);
    749       1.1       mrg 
    750       1.9  jdolecek 	FILE_USE(fp);
    751       1.9  jdolecek 
    752       1.1       mrg 	vp = (struct vnode *)fp->f_data;
    753       1.9  jdolecek 	if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
    754       1.9  jdolecek 		error = ESPIPE;
    755       1.9  jdolecek 		goto out;
    756       1.9  jdolecek 	}
    757       1.1       mrg 
    758       1.1       mrg 	offset = SCARG(uap, offset);
    759       1.1       mrg 
    760       1.1       mrg 	/*
    761       1.1       mrg 	 * XXX This works because no file systems actually
    762       1.1       mrg 	 * XXX take any action on the seek operation.
    763       1.1       mrg 	 */
    764       1.1       mrg 	if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
    765       1.9  jdolecek 		goto out;
    766       1.1       mrg 
    767      1.39       dsl 	return (dofilewritev32(l, fd, fp, SCARG_P32(uap, iovp),
    768      1.10       scw 	    SCARG(uap, iovcnt), &offset, 0, retval));
    769       1.9  jdolecek 
    770       1.9  jdolecek out:
    771      1.23  christos 	FILE_UNUSE(fp, l);
    772       1.9  jdolecek 	return (error);
    773       1.1       mrg }
    774       1.1       mrg 
    775       1.1       mrg /*
    776       1.1       mrg  * Find pathname of process's current directory.
    777       1.1       mrg  *
    778       1.1       mrg  * Use vfs vnode-to-name reverse cache; if that fails, fall back
    779       1.1       mrg  * to reading directory contents.
    780       1.1       mrg  */
    781      1.23  christos /* XXX NH Why does this exist */
    782      1.14      fvdl int
    783  1.46.8.1       mjf getcwd_common(struct vnode *, struct vnode *,
    784  1.46.8.1       mjf 		   char **, char *, int, int, struct lwp *);
    785      1.14      fvdl 
    786      1.19     perry int netbsd32___getcwd(l, v, retval)
    787      1.11   thorpej 	struct lwp *l;
    788       1.1       mrg 	void   *v;
    789       1.1       mrg 	register_t *retval;
    790       1.1       mrg {
    791       1.1       mrg 	struct netbsd32___getcwd_args /* {
    792       1.1       mrg 		syscallarg(char *) bufp;
    793       1.1       mrg 		syscallarg(size_t) length;
    794       1.1       mrg 	} */ *uap = v;
    795      1.11   thorpej 	struct proc *p = l->l_proc;
    796       1.1       mrg 	int     error;
    797       1.1       mrg 	char   *path;
    798       1.1       mrg 	char   *bp, *bend;
    799       1.1       mrg 	int     len = (int)SCARG(uap, length);
    800       1.1       mrg 	int	lenused;
    801       1.1       mrg 
    802       1.1       mrg 	if (len > MAXPATHLEN*4)
    803       1.1       mrg 		len = MAXPATHLEN*4;
    804       1.1       mrg 	else if (len < 2)
    805       1.1       mrg 		return ERANGE;
    806       1.1       mrg 
    807       1.1       mrg 	path = (char *)malloc(len, M_TEMP, M_WAITOK);
    808       1.1       mrg 	if (!path)
    809       1.1       mrg 		return ENOMEM;
    810       1.1       mrg 
    811       1.1       mrg 	bp = &path[len];
    812       1.1       mrg 	bend = bp;
    813       1.1       mrg 	*(--bp) = '\0';
    814       1.1       mrg 
    815       1.1       mrg 	/*
    816       1.1       mrg 	 * 5th argument here is "max number of vnodes to traverse".
    817       1.1       mrg 	 * Since each entry takes up at least 2 bytes in the output buffer,
    818       1.1       mrg 	 * limit it to N/2 vnodes for an N byte buffer.
    819       1.1       mrg 	 */
    820       1.1       mrg #define GETCWD_CHECK_ACCESS 0x0001
    821       1.1       mrg 	error = getcwd_common (p->p_cwdi->cwdi_cdir, NULL, &bp, path, len/2,
    822      1.23  christos 			       GETCWD_CHECK_ACCESS, l);
    823       1.1       mrg 
    824       1.1       mrg 	if (error)
    825       1.1       mrg 		goto out;
    826       1.1       mrg 	lenused = bend - bp;
    827       1.1       mrg 	*retval = lenused;
    828       1.1       mrg 	/* put the result into user buffer */
    829      1.39       dsl 	error = copyout(bp, SCARG_P32(uap, bufp), lenused);
    830       1.1       mrg 
    831       1.1       mrg out:
    832       1.1       mrg 	free(path, M_TEMP);
    833       1.1       mrg 	return error;
    834       1.1       mrg }
    835