Home | History | Annotate | Line # | Download | only in netbsd32
netbsd32_fs.c revision 1.46.10.1
      1  1.46.10.1        ad /*	$NetBSD: netbsd32_fs.c,v 1.46.10.1 2007/12/08 17:56:58 ad 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.10.1        ad __KERNEL_RCSID(0, "$NetBSD: netbsd32_fs.c,v 1.46.10.1 2007/12/08 17:56:58 ad 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.10.1        ad static int dofilereadv32(struct lwp *, int, struct file *, struct netbsd32_iovec *,
     62  1.46.10.1        ad 			      int, off_t *, int, register_t *);
     63  1.46.10.1        ad static int dofilewritev32(struct lwp *, int, struct file *, struct netbsd32_iovec *,
     64  1.46.10.1        ad 			       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.10.1        ad getcwd_common(struct vnode *, struct vnode *,
    784  1.46.10.1        ad 		   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