Home | History | Annotate | Line # | Download | only in netbsd32
netbsd32_fs.c revision 1.66
      1 /*	$NetBSD: netbsd32_fs.c,v 1.66 2013/07/18 14:07:43 matt Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1998, 2001 Matthew R. Green
      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  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #include <sys/cdefs.h>
     30 __KERNEL_RCSID(0, "$NetBSD: netbsd32_fs.c,v 1.66 2013/07/18 14:07:43 matt Exp $");
     31 
     32 #include <sys/param.h>
     33 #include <sys/systm.h>
     34 #include <sys/mount.h>
     35 #include <sys/socket.h>
     36 #include <sys/socketvar.h>
     37 #include <sys/stat.h>
     38 #include <sys/time.h>
     39 #include <sys/ktrace.h>
     40 #include <sys/resourcevar.h>
     41 #include <sys/vnode.h>
     42 #include <sys/file.h>
     43 #include <sys/filedesc.h>
     44 #include <sys/namei.h>
     45 #include <sys/statvfs.h>
     46 #include <sys/syscallargs.h>
     47 #include <sys/proc.h>
     48 #include <sys/dirent.h>
     49 #include <sys/kauth.h>
     50 #include <sys/vfs_syscalls.h>
     51 
     52 #include <fs/cd9660/cd9660_mount.h>
     53 #include <fs/msdosfs/bpb.h>
     54 #include <fs/msdosfs/msdosfsmount.h>
     55 #include <ufs/ufs/ufsmount.h>
     56 
     57 #define NFS_ARGS_ONLY
     58 #include <nfs/nfsmount.h>
     59 
     60 #include <compat/netbsd32/netbsd32.h>
     61 #include <compat/netbsd32/netbsd32_syscallargs.h>
     62 #include <compat/netbsd32/netbsd32_conv.h>
     63 #include <compat/sys/mount.h>
     64 
     65 
     66 static int dofilereadv32(int, struct file *, struct netbsd32_iovec *,
     67 			      int, off_t *, int, register_t *);
     68 static int dofilewritev32(int, struct file *, struct netbsd32_iovec *,
     69 			       int,  off_t *, int, register_t *);
     70 
     71 struct iovec *
     72 netbsd32_get_iov(struct netbsd32_iovec *iov32, int iovlen, struct iovec *aiov,
     73     int aiov_len)
     74 {
     75 #define N_IOV32 8
     76 	struct netbsd32_iovec aiov32[N_IOV32];
     77 	struct iovec *iov = aiov;
     78 	struct iovec *iovp;
     79 	int i, n, j;
     80 	int error;
     81 
     82 	if (iovlen < 0 || iovlen > IOV_MAX)
     83 		return NULL;
     84 
     85 	if (iovlen > aiov_len)
     86 		iov = kmem_alloc(iovlen * sizeof(*iov), KM_SLEEP);
     87 
     88 	iovp = iov;
     89 	for (i = 0; i < iovlen; iov32 += N_IOV32, i += N_IOV32) {
     90 		n = iovlen - i;
     91 		if (n > N_IOV32)
     92 			n = N_IOV32;
     93 		error = copyin(iov32, aiov32, n * sizeof (*iov32));
     94 		if (error != 0) {
     95 			if (iov != aiov)
     96 				kmem_free(iov, iovlen * sizeof(*iov));
     97 			return NULL;
     98 		}
     99 		for (j = 0; j < n; iovp++, j++) {
    100 			iovp->iov_base = NETBSD32PTR64(aiov32[j].iov_base);
    101 			iovp->iov_len = aiov32[j].iov_len;
    102 		}
    103 	}
    104 	return iov;
    105 #undef N_IOV32
    106 }
    107 
    108 int
    109 netbsd32_readv(struct lwp *l, const struct netbsd32_readv_args *uap, register_t *retval)
    110 {
    111 	/* {
    112 		syscallarg(int) fd;
    113 		syscallarg(const netbsd32_iovecp_t) iovp;
    114 		syscallarg(int) iovcnt;
    115 	} */
    116 	int fd = SCARG(uap, fd);
    117 	file_t *fp;
    118 
    119 	if ((fp = fd_getfile(fd)) == NULL)
    120 		return (EBADF);
    121 
    122 	if ((fp->f_flag & FREAD) == 0) {
    123 		fd_putfile(fd);
    124 		return (EBADF);
    125 	}
    126 
    127 	return (dofilereadv32(fd, fp,
    128 	    (struct netbsd32_iovec *)SCARG_P32(uap, iovp),
    129 	    SCARG(uap, iovcnt), &fp->f_offset, FOF_UPDATE_OFFSET, retval));
    130 }
    131 
    132 /* Damn thing copies in the iovec! */
    133 int
    134 dofilereadv32(int fd, struct file *fp, struct netbsd32_iovec *iovp, int iovcnt, off_t *offset, int flags, register_t *retval)
    135 {
    136 	struct uio auio;
    137 	struct iovec *iov;
    138 	struct iovec *needfree;
    139 	struct iovec aiov[UIO_SMALLIOV];
    140 	long i, cnt, error = 0;
    141 	u_int iovlen;
    142 	struct iovec *ktriov = NULL;
    143 
    144 	/* note: can't use iovlen until iovcnt is validated */
    145 	iovlen = iovcnt * sizeof(struct iovec);
    146 	if ((u_int)iovcnt > UIO_SMALLIOV) {
    147 		if ((u_int)iovcnt > IOV_MAX) {
    148 			error = EINVAL;
    149 			goto out;
    150 		}
    151 		iov = kmem_alloc(iovlen, KM_SLEEP);
    152 		needfree = iov;
    153 	} else if ((u_int)iovcnt > 0) {
    154 		iov = aiov;
    155 		needfree = NULL;
    156 	} else {
    157 		error = EINVAL;
    158 		goto out;
    159 	}
    160 
    161 	auio.uio_iov = iov;
    162 	auio.uio_iovcnt = iovcnt;
    163 	auio.uio_rw = UIO_READ;
    164 	auio.uio_vmspace = curproc->p_vmspace;
    165 	error = netbsd32_to_iovecin(iovp, iov, iovcnt);
    166 	if (error)
    167 		goto done;
    168 	auio.uio_resid = 0;
    169 	for (i = 0; i < iovcnt; i++) {
    170 		auio.uio_resid += iov->iov_len;
    171 		/*
    172 		 * Reads return ssize_t because -1 is returned on error.
    173 		 * Therefore we must restrict the length to SSIZE_MAX to
    174 		 * avoid garbage return values.
    175 		 */
    176 		if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
    177 			error = EINVAL;
    178 			goto done;
    179 		}
    180 		iov++;
    181 	}
    182 
    183 	/*
    184 	 * if tracing, save a copy of iovec
    185 	 */
    186 	if (ktrpoint(KTR_GENIO)) {
    187 		ktriov = kmem_alloc(iovlen, KM_SLEEP);
    188 		memcpy((void *)ktriov, (void *)auio.uio_iov, iovlen);
    189 	}
    190 
    191 	cnt = auio.uio_resid;
    192 	error = (*fp->f_ops->fo_read)(fp, offset, &auio, fp->f_cred, flags);
    193 	if (error)
    194 		if (auio.uio_resid != cnt && (error == ERESTART ||
    195 		    error == EINTR || error == EWOULDBLOCK))
    196 			error = 0;
    197 	cnt -= auio.uio_resid;
    198 
    199 	if (ktriov != NULL) {
    200 		ktrgeniov(fd, UIO_READ, ktriov, cnt, error);
    201 		kmem_free(ktriov, iovlen);
    202 	}
    203 
    204 	*retval = cnt;
    205 done:
    206 	if (needfree)
    207 		kmem_free(needfree, iovlen);
    208 out:
    209 	fd_putfile(fd);
    210 	return (error);
    211 }
    212 
    213 int
    214 netbsd32_writev(struct lwp *l, const struct netbsd32_writev_args *uap, register_t *retval)
    215 {
    216 	/* {
    217 		syscallarg(int) fd;
    218 		syscallarg(const netbsd32_iovecp_t) iovp;
    219 		syscallarg(int) iovcnt;
    220 	} */
    221 	int fd = SCARG(uap, fd);
    222 	file_t *fp;
    223 
    224 	if ((fp = fd_getfile(fd)) == NULL)
    225 		return (EBADF);
    226 
    227 	if ((fp->f_flag & FWRITE) == 0) {
    228 		fd_putfile(fd);
    229 		return (EBADF);
    230 	}
    231 
    232 	return (dofilewritev32(fd, fp,
    233 	    (struct netbsd32_iovec *)SCARG_P32(uap, iovp),
    234 	    SCARG(uap, iovcnt), &fp->f_offset, FOF_UPDATE_OFFSET, retval));
    235 }
    236 
    237 int
    238 dofilewritev32(int fd, struct file *fp, struct netbsd32_iovec *iovp, int iovcnt, off_t *offset, int flags, register_t *retval)
    239 {
    240 	struct uio auio;
    241 	struct iovec *iov;
    242 	struct iovec *needfree;
    243 	struct iovec aiov[UIO_SMALLIOV];
    244 	long i, cnt, error = 0;
    245 	u_int iovlen;
    246 	struct iovec *ktriov = NULL;
    247 
    248 	/* note: can't use iovlen until iovcnt is validated */
    249 	iovlen = iovcnt * sizeof(struct iovec);
    250 	if ((u_int)iovcnt > UIO_SMALLIOV) {
    251 		if ((u_int)iovcnt > IOV_MAX) {
    252 			error = EINVAL;
    253 			goto out;
    254 		}
    255 		iov = kmem_alloc(iovlen, KM_SLEEP);
    256 		needfree = iov;
    257 	} else if ((u_int)iovcnt > 0) {
    258 		iov = aiov;
    259 		needfree = NULL;
    260 	} else {
    261 		error = EINVAL;
    262 		goto out;
    263 	}
    264 
    265 	auio.uio_iov = iov;
    266 	auio.uio_iovcnt = iovcnt;
    267 	auio.uio_rw = UIO_WRITE;
    268 	auio.uio_vmspace = curproc->p_vmspace;
    269 	error = netbsd32_to_iovecin(iovp, iov, iovcnt);
    270 	if (error)
    271 		goto done;
    272 	auio.uio_resid = 0;
    273 	for (i = 0; i < iovcnt; i++) {
    274 		auio.uio_resid += iov->iov_len;
    275 		/*
    276 		 * Writes return ssize_t because -1 is returned on error.
    277 		 * Therefore we must restrict the length to SSIZE_MAX to
    278 		 * avoid garbage return values.
    279 		 */
    280 		if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
    281 			error = EINVAL;
    282 			goto done;
    283 		}
    284 		iov++;
    285 	}
    286 
    287 	/*
    288 	 * if tracing, save a copy of iovec
    289 	 */
    290 	if (ktrpoint(KTR_GENIO))  {
    291 		ktriov = kmem_alloc(iovlen, KM_SLEEP);
    292 		memcpy((void *)ktriov, (void *)auio.uio_iov, iovlen);
    293 	}
    294 
    295 	cnt = auio.uio_resid;
    296 	error = (*fp->f_ops->fo_write)(fp, offset, &auio, fp->f_cred, flags);
    297 	if (error) {
    298 		if (auio.uio_resid != cnt && (error == ERESTART ||
    299 		    error == EINTR || error == EWOULDBLOCK))
    300 			error = 0;
    301 		if (error == EPIPE && (fp->f_flag & FNOSIGPIPE) == 0) {
    302 			mutex_enter(proc_lock);
    303 			psignal(curproc, SIGPIPE);
    304 			mutex_exit(proc_lock);
    305 		}
    306 	}
    307 	cnt -= auio.uio_resid;
    308 	if (ktriov != NULL) {
    309 		ktrgenio(fd, UIO_WRITE, ktriov, cnt, error);
    310 		kmem_free(ktriov, iovlen);
    311 	}
    312 	*retval = cnt;
    313 done:
    314 	if (needfree)
    315 		kmem_free(needfree, iovlen);
    316 out:
    317 	fd_putfile(fd);
    318 	return (error);
    319 }
    320 
    321 /*
    322  * Common routine to set access and modification times given a vnode.
    323  */
    324 static int
    325 get_utimes32(const netbsd32_timevalp_t *tptr, struct timeval *tv,
    326     struct timeval **tvp)
    327 {
    328 	int error;
    329 	struct netbsd32_timeval tv32[2];
    330 
    331 	if (tptr == NULL) {
    332 		*tvp = NULL;
    333 		return 0;
    334 	}
    335 
    336 	error = copyin(tptr, tv32, sizeof(tv32));
    337 	if (error)
    338 		return error;
    339 	netbsd32_to_timeval(&tv32[0], &tv[0]);
    340 	netbsd32_to_timeval(&tv32[1], &tv[1]);
    341 
    342 	*tvp = tv;
    343 	return 0;
    344 }
    345 
    346 int
    347 netbsd32___utimes50(struct lwp *l, const struct netbsd32___utimes50_args *uap, register_t *retval)
    348 {
    349 	/* {
    350 		syscallarg(const netbsd32_charp) path;
    351 		syscallarg(const netbsd32_timevalp_t) tptr;
    352 	} */
    353 	int error;
    354 	struct timeval tv[2], *tvp;
    355 
    356 	error = get_utimes32(SCARG_P32(uap, tptr), tv, &tvp);
    357 	if (error != 0)
    358 		return error;
    359 
    360 	return do_sys_utimes(l, NULL, SCARG_P32(uap, path), FOLLOW,
    361 			    tvp, UIO_SYSSPACE);
    362 }
    363 
    364 static int
    365 netbds32_copyout_statvfs(const void *kp, void *up, size_t len)
    366 {
    367 	struct netbsd32_statvfs *sbuf_32;
    368 	int error;
    369 
    370 	sbuf_32 = kmem_alloc(sizeof(*sbuf_32), KM_SLEEP);
    371 	netbsd32_from_statvfs(kp, sbuf_32);
    372 	error = copyout(sbuf_32, up, sizeof(*sbuf_32));
    373 	kmem_free(sbuf_32, sizeof(*sbuf_32));
    374 
    375 	return error;
    376 }
    377 
    378 int
    379 netbsd32_statvfs1(struct lwp *l, const struct netbsd32_statvfs1_args *uap, register_t *retval)
    380 {
    381 	/* {
    382 		syscallarg(const netbsd32_charp) path;
    383 		syscallarg(netbsd32_statvfsp_t) buf;
    384 		syscallarg(int) flags;
    385 	} */
    386 	struct statvfs *sb;
    387 	int error;
    388 
    389 	sb = STATVFSBUF_GET();
    390 	error = do_sys_pstatvfs(l, SCARG_P32(uap, path), SCARG(uap, flags), sb);
    391 	if (error == 0)
    392 		error = netbds32_copyout_statvfs(sb, SCARG_P32(uap, buf), 0);
    393 	STATVFSBUF_PUT(sb);
    394 	return error;
    395 }
    396 
    397 int
    398 netbsd32_fstatvfs1(struct lwp *l, const struct netbsd32_fstatvfs1_args *uap, register_t *retval)
    399 {
    400 	/* {
    401 		syscallarg(int) fd;
    402 		syscallarg(netbsd32_statvfsp_t) buf;
    403 		syscallarg(int) flags;
    404 	} */
    405 	struct statvfs *sb;
    406 	int error;
    407 
    408 	sb = STATVFSBUF_GET();
    409 	error = do_sys_fstatvfs(l, SCARG(uap, fd), SCARG(uap, flags), sb);
    410 	if (error == 0)
    411 		error = netbds32_copyout_statvfs(sb, SCARG_P32(uap, buf), 0);
    412 	STATVFSBUF_PUT(sb);
    413 	return error;
    414 }
    415 
    416 int
    417 netbsd32_getvfsstat(struct lwp *l, const struct netbsd32_getvfsstat_args *uap, register_t *retval)
    418 {
    419 	/* {
    420 		syscallarg(netbsd32_statvfsp_t) buf;
    421 		syscallarg(netbsd32_size_t) bufsize;
    422 		syscallarg(int) flags;
    423 	} */
    424 
    425 	return do_sys_getvfsstat(l, SCARG_P32(uap, buf), SCARG(uap, bufsize),
    426 	    SCARG(uap, flags), netbds32_copyout_statvfs,
    427 	    sizeof (struct netbsd32_statvfs), retval);
    428 }
    429 
    430 int
    431 netbsd32___fhstatvfs140(struct lwp *l, const struct netbsd32___fhstatvfs140_args *uap, register_t *retval)
    432 {
    433 	/* {
    434 		syscallarg(const netbsd32_pointer_t) fhp;
    435 		syscallarg(netbsd32_size_t) fh_size;
    436 		syscallarg(netbsd32_statvfsp_t) buf;
    437 		syscallarg(int) flags;
    438 	} */
    439 	struct statvfs *sb;
    440 	int error;
    441 
    442 	sb = STATVFSBUF_GET();
    443 	error = do_fhstatvfs(l, SCARG_P32(uap, fhp), SCARG(uap, fh_size), sb,
    444 	    SCARG(uap, flags));
    445 
    446 	if (error == 0)
    447 		error = netbds32_copyout_statvfs(sb, SCARG_P32(uap, buf), 0);
    448 	STATVFSBUF_PUT(sb);
    449 
    450 	return error;
    451 }
    452 
    453 int
    454 netbsd32___futimes50(struct lwp *l, const struct netbsd32___futimes50_args *uap, register_t *retval)
    455 {
    456 	/* {
    457 		syscallarg(int) fd;
    458 		syscallarg(const netbsd32_timevalp_t) tptr;
    459 	} */
    460 	int error;
    461 	file_t *fp;
    462 	struct timeval tv[2], *tvp;
    463 
    464 	error = get_utimes32(SCARG_P32(uap, tptr), tv, &tvp);
    465 	if (error != 0)
    466 		return error;
    467 
    468 	/* fd_getvnode() will use the descriptor for us */
    469 	if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
    470 		return (error);
    471 
    472 	error = do_sys_utimes(l, fp->f_data, NULL, 0, tvp, UIO_SYSSPACE);
    473 
    474 	fd_putfile(SCARG(uap, fd));
    475 	return (error);
    476 }
    477 
    478 int
    479 netbsd32___getdents30(struct lwp *l,
    480     const struct netbsd32___getdents30_args *uap, register_t *retval)
    481 {
    482 	/* {
    483 		syscallarg(int) fd;
    484 		syscallarg(netbsd32_charp) buf;
    485 		syscallarg(netbsd32_size_t) count;
    486 	} */
    487 	file_t *fp;
    488 	int error, done;
    489 
    490 	/* fd_getvnode() will use the descriptor for us */
    491 	if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
    492 		return (error);
    493 	if ((fp->f_flag & FREAD) == 0) {
    494 		error = EBADF;
    495 		goto out;
    496 	}
    497 	error = vn_readdir(fp, SCARG_P32(uap, buf),
    498 	    UIO_USERSPACE, SCARG(uap, count), &done, l, 0, 0);
    499 	*retval = done;
    500  out:
    501 	fd_putfile(SCARG(uap, fd));
    502 	return (error);
    503 }
    504 
    505 int
    506 netbsd32___lutimes50(struct lwp *l,
    507     const struct netbsd32___lutimes50_args *uap, register_t *retval)
    508 {
    509 	/* {
    510 		syscallarg(const netbsd32_charp) path;
    511 		syscallarg(const netbsd32_timevalp_t) tptr;
    512 	} */
    513 	int error;
    514 	struct timeval tv[2], *tvp;
    515 
    516 	error = get_utimes32(SCARG_P32(uap, tptr), tv, &tvp);
    517 	if (error != 0)
    518 		return error;
    519 
    520 	return do_sys_utimes(l, NULL, SCARG_P32(uap, path), NOFOLLOW,
    521 			    tvp, UIO_SYSSPACE);
    522 }
    523 
    524 int
    525 netbsd32___stat50(struct lwp *l, const struct netbsd32___stat50_args *uap, register_t *retval)
    526 {
    527 	/* {
    528 		syscallarg(const netbsd32_charp) path;
    529 		syscallarg(netbsd32_statp_t) ub;
    530 	} */
    531 	struct netbsd32_stat sb32;
    532 	struct stat sb;
    533 	int error;
    534 	const char *path;
    535 
    536 	path = SCARG_P32(uap, path);
    537 
    538 	error = do_sys_stat(path, FOLLOW, &sb);
    539 	if (error)
    540 		return (error);
    541 	netbsd32_from_stat(&sb, &sb32);
    542 	error = copyout(&sb32, SCARG_P32(uap, ub), sizeof(sb32));
    543 	return (error);
    544 }
    545 
    546 int
    547 netbsd32___fstat50(struct lwp *l, const struct netbsd32___fstat50_args *uap, register_t *retval)
    548 {
    549 	/* {
    550 		syscallarg(int) fd;
    551 		syscallarg(netbsd32_statp_t) sb;
    552 	} */
    553 	struct netbsd32_stat sb32;
    554 	struct stat ub;
    555 	int error;
    556 
    557 	error = do_sys_fstat(SCARG(uap, fd), &ub);
    558 	if (error == 0) {
    559 		netbsd32_from_stat(&ub, &sb32);
    560 		error = copyout(&sb32, SCARG_P32(uap, sb), sizeof(sb32));
    561 	}
    562 	return (error);
    563 }
    564 
    565 int
    566 netbsd32___lstat50(struct lwp *l, const struct netbsd32___lstat50_args *uap, register_t *retval)
    567 {
    568 	/* {
    569 		syscallarg(const netbsd32_charp) path;
    570 		syscallarg(netbsd32_statp_t) ub;
    571 	} */
    572 	struct netbsd32_stat sb32;
    573 	struct stat sb;
    574 	int error;
    575 	const char *path;
    576 
    577 	path = SCARG_P32(uap, path);
    578 
    579 	error = do_sys_stat(path, NOFOLLOW, &sb);
    580 	if (error)
    581 		return (error);
    582 	netbsd32_from_stat(&sb, &sb32);
    583 	error = copyout(&sb32, SCARG_P32(uap, ub), sizeof(sb32));
    584 	return (error);
    585 }
    586 
    587 int
    588 netbsd32___fhstat50(struct lwp *l, const struct netbsd32___fhstat50_args *uap, register_t *retval)
    589 {
    590 	/* {
    591 		syscallarg(const netbsd32_pointer_t) fhp;
    592 		syscallarg(netbsd32_size_t) fh_size;
    593 		syscallarg(netbsd32_statp_t) sb;
    594 	} */
    595 	struct stat sb;
    596 	struct netbsd32_stat sb32;
    597 	int error;
    598 
    599 	error = do_fhstat(l, SCARG_P32(uap, fhp), SCARG(uap, fh_size), &sb);
    600 	if (error == 0) {
    601 		netbsd32_from_stat(&sb, &sb32);
    602 		error = copyout(&sb32, SCARG_P32(uap, sb), sizeof(sb));
    603 	}
    604 	return error;
    605 }
    606 
    607 int
    608 netbsd32_preadv(struct lwp *l, const struct netbsd32_preadv_args *uap, register_t *retval)
    609 {
    610 	/* {
    611 		syscallarg(int) fd;
    612 		syscallarg(const netbsd32_iovecp_t) iovp;
    613 		syscallarg(int) iovcnt;
    614 		syscallarg(int) pad;
    615 		syscallarg(off_t) offset;
    616 	} */
    617 	file_t *fp;
    618 	struct vnode *vp;
    619 	off_t offset;
    620 	int error, fd = SCARG(uap, fd);
    621 
    622 	if ((fp = fd_getfile(fd)) == NULL)
    623 		return (EBADF);
    624 
    625 	if ((fp->f_flag & FREAD) == 0) {
    626 		fd_putfile(fd);
    627 		return (EBADF);
    628 	}
    629 
    630 	vp = fp->f_data;
    631 	if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
    632 		error = ESPIPE;
    633 		goto out;
    634 	}
    635 
    636 	offset = SCARG(uap, offset);
    637 
    638 	/*
    639 	 * XXX This works because no file systems actually
    640 	 * XXX take any action on the seek operation.
    641 	 */
    642 	if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
    643 		goto out;
    644 
    645 	return (dofilereadv32(fd, fp, SCARG_P32(uap, iovp),
    646 	    SCARG(uap, iovcnt), &offset, 0, retval));
    647 
    648 out:
    649 	fd_putfile(fd);
    650 	return (error);
    651 }
    652 
    653 int
    654 netbsd32_pwritev(struct lwp *l, const struct netbsd32_pwritev_args *uap, register_t *retval)
    655 {
    656 	/* {
    657 		syscallarg(int) fd;
    658 		syscallarg(const netbsd32_iovecp_t) iovp;
    659 		syscallarg(int) iovcnt;
    660 		syscallarg(int) pad;
    661 		syscallarg(off_t) offset;
    662 	} */
    663 	file_t *fp;
    664 	struct vnode *vp;
    665 	off_t offset;
    666 	int error, fd = SCARG(uap, fd);
    667 
    668 	if ((fp = fd_getfile(fd)) == NULL)
    669 		return (EBADF);
    670 
    671 	if ((fp->f_flag & FWRITE) == 0) {
    672 		fd_putfile(fd);
    673 		return (EBADF);
    674 	}
    675 
    676 	vp = fp->f_data;
    677 	if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
    678 		error = ESPIPE;
    679 		goto out;
    680 	}
    681 
    682 	offset = SCARG(uap, offset);
    683 
    684 	/*
    685 	 * XXX This works because no file systems actually
    686 	 * XXX take any action on the seek operation.
    687 	 */
    688 	if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
    689 		goto out;
    690 
    691 	return (dofilewritev32(fd, fp, SCARG_P32(uap, iovp),
    692 	    SCARG(uap, iovcnt), &offset, 0, retval));
    693 
    694 out:
    695 	fd_putfile(fd);
    696 	return (error);
    697 }
    698 
    699 /*
    700  * Find pathname of process's current directory.
    701  *
    702  * Use vfs vnode-to-name reverse cache; if that fails, fall back
    703  * to reading directory contents.
    704  */
    705 /* XXX NH Why does this exist */
    706 int
    707 getcwd_common(struct vnode *, struct vnode *,
    708 		   char **, char *, int, int, struct lwp *);
    709 
    710 int
    711 netbsd32___getcwd(struct lwp *l, const struct netbsd32___getcwd_args *uap, register_t *retval)
    712 {
    713 	/* {
    714 		syscallarg(char *) bufp;
    715 		syscallarg(size_t) length;
    716 	} */
    717 	struct proc *p = l->l_proc;
    718 	int     error;
    719 	char   *path;
    720 	char   *bp, *bend;
    721 	int     len = (int)SCARG(uap, length);
    722 	int	lenused;
    723 	struct	cwdinfo *cwdi;
    724 
    725 	if (len > MAXPATHLEN*4)
    726 		len = MAXPATHLEN*4;
    727 	else if (len < 2)
    728 		return ERANGE;
    729 
    730 	path = kmem_alloc(len, KM_SLEEP);
    731 	if (!path)
    732 		return ENOMEM;
    733 
    734 	bp = &path[len];
    735 	bend = bp;
    736 	*(--bp) = '\0';
    737 
    738 	/*
    739 	 * 5th argument here is "max number of vnodes to traverse".
    740 	 * Since each entry takes up at least 2 bytes in the output buffer,
    741 	 * limit it to N/2 vnodes for an N byte buffer.
    742 	 */
    743 #define GETCWD_CHECK_ACCESS 0x0001
    744 	cwdi = p->p_cwdi;
    745 	rw_enter(&cwdi->cwdi_lock, RW_READER);
    746 	error = getcwd_common (cwdi->cwdi_cdir, NULL, &bp, path, len/2,
    747 			       GETCWD_CHECK_ACCESS, l);
    748 	rw_exit(&cwdi->cwdi_lock);
    749 
    750 	if (error)
    751 		goto out;
    752 	lenused = bend - bp;
    753 	*retval = lenused;
    754 	/* put the result into user buffer */
    755 	error = copyout(bp, SCARG_P32(uap, bufp), lenused);
    756 
    757 out:
    758 	kmem_free(path, len);
    759 	return error;
    760 }
    761 
    762 int
    763 netbsd32___mount50(struct lwp *l, const struct netbsd32___mount50_args *uap,
    764 	register_t *retval)
    765 {
    766 	/* {
    767 		syscallarg(netbsd32_charp) type;
    768 		syscallarg(netbsd32_charp) path;
    769 		syscallarg(int) flags;
    770 		syscallarg(netbsd32_voidp) data;
    771 		syscallarg(netbsd32_size_t) data_len;
    772 	} */
    773 	char mtype[MNAMELEN];
    774 	union {
    775 		struct netbsd32_ufs_args ufs_args;
    776 		struct netbsd32_mfs_args mfs_args;
    777 		struct netbsd32_iso_args iso_args;
    778 		struct netbsd32_nfs_args nfs_args;
    779 		struct netbsd32_msdosfs_args msdosfs_args;
    780 	} fs_args32;
    781 	union {
    782 		struct ufs_args ufs_args;
    783 		struct mfs_args mfs_args;
    784 		struct iso_args iso_args;
    785 		struct nfs_args nfs_args;
    786 		struct msdosfs_args msdosfs_args;
    787 	} fs_args;
    788 	const char *type = SCARG_P32(uap, type);
    789 	const char *path = SCARG_P32(uap, path);
    790 	int flags = SCARG(uap, flags);
    791 	void *data = SCARG_P32(uap, data);
    792 	size_t data_len = SCARG(uap, data_len);
    793 	enum uio_seg data_seg;
    794 	size_t len;
    795 	int error;
    796 
    797 	error = copyinstr(type, mtype, sizeof(mtype), &len);
    798 	if (error)
    799 		return error;
    800 	if (strcmp(mtype, MOUNT_MFS) == 0) {
    801 		if (data_len != sizeof(fs_args32.mfs_args))
    802 			return EINVAL;
    803 		if ((flags & MNT_GETARGS) == 0) {
    804 			error = copyin(data, &fs_args32.mfs_args,
    805 			    sizeof(fs_args32.mfs_args));
    806 			if (error)
    807 				return error;
    808 			fs_args.mfs_args.fspec =
    809 			    NETBSD32PTR64(fs_args32.mfs_args.fspec);
    810 			memset(&fs_args.mfs_args._pad1, 0,
    811 			    sizeof(fs_args.mfs_args._pad1));
    812 			fs_args.mfs_args.base =
    813 			    NETBSD32PTR64(fs_args32.mfs_args.base);
    814 			fs_args.mfs_args.size = fs_args32.mfs_args.size;
    815 		}
    816 		data_seg = UIO_SYSSPACE;
    817 		data = &fs_args.mfs_args;
    818 		data_len = sizeof(fs_args.mfs_args);
    819 	} else if ((strcmp(mtype, MOUNT_UFS) == 0) ||
    820 		   (strcmp(mtype, MOUNT_EXT2FS) == 0) ||
    821 		   (strcmp(mtype, MOUNT_LFS) == 0)) {
    822 		if (data_len > sizeof(fs_args32.ufs_args))
    823 			return EINVAL;
    824 		if ((flags & MNT_GETARGS) == 0) {
    825 			error = copyin(data, &fs_args32.ufs_args,
    826 			    sizeof(fs_args32.ufs_args));
    827 			if (error)
    828 				return error;
    829 			fs_args.ufs_args.fspec =
    830 			    NETBSD32PTR64(fs_args32.ufs_args.fspec);
    831 		}
    832 		data_seg = UIO_SYSSPACE;
    833 		data = &fs_args.ufs_args;
    834 		data_len = sizeof(fs_args.ufs_args);
    835 	} else if (strcmp(mtype, MOUNT_CD9660) == 0) {
    836 		if (data_len != sizeof(fs_args32.iso_args))
    837 			return EINVAL;
    838 		if ((flags & MNT_GETARGS) == 0) {
    839 			error = copyin(data, &fs_args32.iso_args,
    840 			    sizeof(fs_args32.iso_args));
    841 			if (error)
    842 				return error;
    843 			fs_args.iso_args.fspec =
    844 			    NETBSD32PTR64(fs_args32.iso_args.fspec);
    845 			memset(&fs_args.iso_args._pad1, 0,
    846 			    sizeof(fs_args.iso_args._pad1));
    847 			fs_args.iso_args.flags = fs_args32.iso_args.flags;
    848 		}
    849 		data_seg = UIO_SYSSPACE;
    850 		data = &fs_args.iso_args;
    851 		data_len = sizeof(fs_args.iso_args);
    852 	} else if (strcmp(mtype, MOUNT_MSDOS) == 0) {
    853 		if (data_len != sizeof(fs_args32.msdosfs_args))
    854 			return EINVAL;
    855 		if ((flags & MNT_GETARGS) == 0) {
    856 			error = copyin(data, &fs_args32.msdosfs_args,
    857 			    sizeof(fs_args32.msdosfs_args));
    858 			if (error)
    859 				return error;
    860 			fs_args.msdosfs_args.fspec =
    861 			    NETBSD32PTR64(fs_args32.msdosfs_args.fspec);
    862 			memset(&fs_args.msdosfs_args._pad1, 0,
    863 			    sizeof(fs_args.msdosfs_args._pad1));
    864 			fs_args.msdosfs_args.uid =
    865 			    fs_args32.msdosfs_args.uid;
    866 			fs_args.msdosfs_args.gid =
    867 			    fs_args32.msdosfs_args.gid;
    868 			fs_args.msdosfs_args.mask =
    869 			    fs_args32.msdosfs_args.mask;
    870 			fs_args.msdosfs_args.flags =
    871 			    fs_args32.msdosfs_args.flags;
    872 			fs_args.msdosfs_args.version =
    873 			    fs_args32.msdosfs_args.version;
    874 			fs_args.msdosfs_args.dirmask =
    875 			    fs_args32.msdosfs_args.dirmask;
    876 			fs_args.msdosfs_args.gmtoff =
    877 			    fs_args32.msdosfs_args.gmtoff;
    878 		}
    879 		data_seg = UIO_SYSSPACE;
    880 		data = &fs_args.msdosfs_args;
    881 		data_len = sizeof(fs_args.msdosfs_args);
    882 	} else if (strcmp(mtype, MOUNT_NFS) == 0) {
    883 		if (data_len != sizeof(fs_args32.nfs_args))
    884 			return EINVAL;
    885 		if ((flags & MNT_GETARGS) == 0) {
    886 			error = copyin(data, &fs_args32.nfs_args,
    887 			    sizeof(fs_args32.nfs_args));
    888 			if (error)
    889 				return error;
    890 			fs_args.nfs_args.version = fs_args32.nfs_args.version;
    891 			fs_args.nfs_args.addr =
    892 			    NETBSD32PTR64(fs_args32.nfs_args.addr);
    893 			memcpy(&fs_args.nfs_args.addrlen,
    894 			    &fs_args32.nfs_args.addrlen,
    895 			    offsetof(struct nfs_args, fh)
    896 				- offsetof(struct nfs_args, addrlen));
    897 			fs_args.nfs_args.fh =
    898 			    NETBSD32PTR64(fs_args32.nfs_args.fh);
    899 			memcpy(&fs_args.nfs_args.fhsize,
    900 			    &fs_args32.nfs_args.fhsize,
    901 			    offsetof(struct nfs_args, hostname)
    902 				- offsetof(struct nfs_args, fhsize));
    903 			fs_args.nfs_args.hostname =
    904 			    NETBSD32PTR64(fs_args32.nfs_args.hostname);
    905 		}
    906 		data_seg = UIO_SYSSPACE;
    907 		data = &fs_args.nfs_args;
    908 		data_len = sizeof(fs_args.nfs_args);
    909 	} else {
    910 		data_seg = UIO_USERSPACE;
    911 	}
    912 	error = do_sys_mount(l, NULL, type, path, flags, data, data_seg,
    913 	    data_len, retval);
    914 	if (error)
    915 		return error;
    916 	if (flags & MNT_GETARGS) {
    917 		data_len = *retval;
    918 		if (strcmp(mtype, MOUNT_MFS) == 0) {
    919 			if (data_len != sizeof(fs_args.mfs_args))
    920 				return EINVAL;
    921 			NETBSD32PTR32(fs_args32.mfs_args.fspec,
    922 			    fs_args.mfs_args.fspec);
    923 			memset(&fs_args32.mfs_args._pad1, 0,
    924 			    sizeof(fs_args32.mfs_args._pad1));
    925 			NETBSD32PTR32(fs_args32.mfs_args.base,
    926 			    fs_args.mfs_args.base);
    927 			fs_args32.mfs_args.size = fs_args.mfs_args.size;
    928 			error = copyout(&fs_args32.mfs_args, data,
    929 				    sizeof(fs_args32.mfs_args));
    930 		} else if (strcmp(mtype, MOUNT_UFS) == 0) {
    931 			if (data_len != sizeof(fs_args.ufs_args))
    932 				return EINVAL;
    933 			NETBSD32PTR32(fs_args32.ufs_args.fspec,
    934 			    fs_args.ufs_args.fspec);
    935 			error = copyout(&fs_args32.ufs_args, data,
    936 			    sizeof(fs_args32.ufs_args));
    937 		} else if (strcmp(mtype, MOUNT_CD9660) == 0) {
    938 			if (data_len != sizeof(fs_args.iso_args))
    939 				return EINVAL;
    940 			NETBSD32PTR32(fs_args32.iso_args.fspec,
    941 			    fs_args.iso_args.fspec);
    942 			memset(&fs_args32.iso_args._pad1, 0,
    943 			    sizeof(fs_args32.iso_args._pad1));
    944 			fs_args32.iso_args.flags = fs_args.iso_args.flags;
    945 			error = copyout(&fs_args32.iso_args, data,
    946 				    sizeof(fs_args32.iso_args));
    947 		} else if (strcmp(mtype, MOUNT_NFS) == 0) {
    948 			if (data_len != sizeof(fs_args.nfs_args))
    949 				return EINVAL;
    950 			error = copyin(data, &fs_args32.nfs_args,
    951 			    sizeof(fs_args32.nfs_args));
    952 			if (error)
    953 				return error;
    954 			fs_args.nfs_args.version = fs_args32.nfs_args.version;
    955 			NETBSD32PTR32(fs_args32.nfs_args.addr,
    956 			    fs_args.nfs_args.addr);
    957 			memcpy(&fs_args32.nfs_args.addrlen,
    958 			    &fs_args.nfs_args.addrlen,
    959 			    offsetof(struct nfs_args, fh)
    960 				- offsetof(struct nfs_args, addrlen));
    961 			NETBSD32PTR32(fs_args32.nfs_args.fh,
    962 			    fs_args.nfs_args.fh);
    963 			memcpy(&fs_args32.nfs_args.fhsize,
    964 			    &fs_args.nfs_args.fhsize,
    965 			    offsetof(struct nfs_args, hostname)
    966 				- offsetof(struct nfs_args, fhsize));
    967 			NETBSD32PTR32(fs_args32.nfs_args.hostname,
    968 			    fs_args.nfs_args.hostname);
    969 			error = copyout(&fs_args32.nfs_args, data,
    970 			    sizeof(fs_args32.nfs_args));
    971 		}
    972 	}
    973 	return error;
    974 }
    975 
    976 int
    977 netbsd32_linkat(struct lwp *l, const struct netbsd32_linkat_args *uap,
    978 		 register_t *retval)
    979 {
    980 	/* {
    981 		syscallarg(int) fd1;
    982 		syscallarg(const netbsd32_charp) name1;
    983 		syscallarg(int) fd2;
    984 		syscallarg(const netbsd32_charp) name2;
    985 		syscallarg(int) flags;
    986 	} */
    987 	struct sys_linkat_args ua;
    988 
    989 	NETBSD32TO64_UAP(fd1);
    990 	NETBSD32TOP_UAP(name1, const char);
    991 	NETBSD32TO64_UAP(fd2);
    992 	NETBSD32TOP_UAP(name2, const char);
    993 	NETBSD32TO64_UAP(flags);
    994 
    995 	return sys_linkat(l, &ua, retval);
    996 }
    997 
    998 int
    999 netbsd32_renameat(struct lwp *l, const struct netbsd32_renameat_args *uap,
   1000 		 register_t *retval)
   1001 {
   1002 	/* {
   1003 		syscallarg(int) fromfd;
   1004 		syscallarg(const netbsd32_charp) from;
   1005 		syscallarg(int) tofd;
   1006 		syscallarg(const netbsd32_charp) to;
   1007 	} */
   1008 	struct sys_renameat_args ua;
   1009 
   1010 	NETBSD32TO64_UAP(fromfd);
   1011 	NETBSD32TOP_UAP(from, const char);
   1012 	NETBSD32TO64_UAP(tofd);
   1013 	NETBSD32TOP_UAP(to, const char);
   1014 
   1015 	return sys_renameat(l, &ua, retval);
   1016 }
   1017 
   1018 int
   1019 netbsd32_mkfifoat(struct lwp *l, const struct netbsd32_mkfifoat_args *uap,
   1020 		 register_t *retval)
   1021 {
   1022 	/* {
   1023 		syscallarg(int) fd;
   1024 		syscallarg(const netbsd32_charp) path;
   1025 		syscallarg(mode_t) mode;
   1026 	} */
   1027 	struct sys_mkfifoat_args ua;
   1028 
   1029 	NETBSD32TO64_UAP(fd);
   1030 	NETBSD32TOP_UAP(path, const char);
   1031 	NETBSD32TO64_UAP(mode);
   1032 
   1033 	return sys_mkfifoat(l, &ua, retval);
   1034 }
   1035 
   1036 int
   1037 netbsd32_mknodat(struct lwp *l, const struct netbsd32_mknodat_args *uap,
   1038 		 register_t *retval)
   1039 {
   1040 	/* {
   1041 		syscallarg(int) fd;
   1042 		syscallarg(netbsd32_charp) path;
   1043 		syscallarg(mode_t) mode;
   1044 		syscallarg(uint32_t) dev;
   1045 	} */
   1046 	struct sys_mknodat_args ua;
   1047 
   1048 	NETBSD32TO64_UAP(fd);
   1049 	NETBSD32TOP_UAP(path, const char);
   1050 	NETBSD32TO64_UAP(mode);
   1051 	NETBSD32TO64_UAP(dev);
   1052 
   1053 	return sys_mknodat(l, &ua, retval);
   1054 }
   1055 
   1056 int
   1057 netbsd32_mkdirat(struct lwp *l, const struct netbsd32_mkdirat_args *uap,
   1058 		 register_t *retval)
   1059 {
   1060 	/* {
   1061 		syscallarg(int) fd;
   1062 		syscallarg(netbsd32_charp) path;
   1063 		syscallarg(mode_t) mode;
   1064 	} */
   1065 	struct sys_mkdirat_args ua;
   1066 
   1067 	NETBSD32TO64_UAP(fd);
   1068 	NETBSD32TOP_UAP(path, const char);
   1069 	NETBSD32TO64_UAP(mode);
   1070 
   1071 	return sys_mkdirat(l, &ua, retval);
   1072 }
   1073 
   1074 int
   1075 netbsd32_faccessat(struct lwp *l, const struct netbsd32_faccessat_args *uap,
   1076 		 register_t *retval)
   1077 {
   1078 	/* {
   1079 		syscallarg(int) fd;
   1080 		syscallarg(netbsd32_charp) path;
   1081 		syscallarg(int) amode;
   1082 		syscallarg(int) flag;
   1083 	} */
   1084 	struct sys_faccessat_args ua;
   1085 
   1086 	NETBSD32TO64_UAP(fd);
   1087 	NETBSD32TOP_UAP(path, const char);
   1088 	NETBSD32TO64_UAP(amode);
   1089 	NETBSD32TO64_UAP(flag);
   1090 
   1091 	return sys_faccessat(l, &ua, retval);
   1092 }
   1093 
   1094 int
   1095 netbsd32_fchmodat(struct lwp *l, const struct netbsd32_fchmodat_args *uap,
   1096 		 register_t *retval)
   1097 {
   1098 	/* {
   1099 		syscallarg(int) fd;
   1100 		syscallarg(netbsd32_charp) path;
   1101 		syscallarg(mode_t) mode;
   1102 		syscallarg(int) flag;
   1103 	} */
   1104 	struct sys_fchmodat_args ua;
   1105 
   1106 	NETBSD32TO64_UAP(fd);
   1107 	NETBSD32TOP_UAP(path, const char);
   1108 	NETBSD32TO64_UAP(mode);
   1109 	NETBSD32TO64_UAP(flag);
   1110 
   1111 	return sys_fchmodat(l, &ua, retval);
   1112 }
   1113 
   1114 int
   1115 netbsd32_fchownat(struct lwp *l, const struct netbsd32_fchownat_args *uap,
   1116 		 register_t *retval)
   1117 {
   1118 	/* {
   1119 		syscallarg(int) fd;
   1120 		syscallarg(netbsd32_charp) path;
   1121 		syscallarg(uid_t) owner;
   1122 		syscallarg(gid_t) group;
   1123 		syscallarg(int) flag;
   1124 	} */
   1125 	struct sys_fchownat_args ua;
   1126 
   1127 	NETBSD32TO64_UAP(fd);
   1128 	NETBSD32TOP_UAP(path, const char);
   1129 	NETBSD32TO64_UAP(owner);
   1130 	NETBSD32TO64_UAP(group);
   1131 	NETBSD32TO64_UAP(flag);
   1132 
   1133 	return sys_fchownat(l, &ua, retval);
   1134 }
   1135 
   1136 int
   1137 netbsd32_fstatat(struct lwp *l, const struct netbsd32_fstatat_args *uap,
   1138 		 register_t *retval)
   1139 {
   1140 	/* {
   1141 		syscallarg(int) fd;
   1142 		syscallarg(netbsd32_charp) path;
   1143 		syscallarg(netbsd32_statp_t) buf;
   1144 		syscallarg(int) flag;
   1145 	} */
   1146 	struct netbsd32_stat sb32;
   1147 	struct stat sb;
   1148 	int follow;
   1149 	int error;
   1150 
   1151 	follow = (SCARG(uap, flag) & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW;
   1152 
   1153 	error = do_sys_statat(l, SCARG(uap, fd), SCARG_P32(uap, path),
   1154 	    follow, &sb);
   1155 	if (error)
   1156 		return error;
   1157 	netbsd32_from_stat(&sb, &sb32);
   1158 	return copyout(&sb32, SCARG_P32(uap, buf), sizeof(sb32));
   1159 }
   1160 
   1161 int
   1162 netbsd32_utimensat(struct lwp *l, const struct netbsd32_utimensat_args *uap,
   1163 		 register_t *retval)
   1164 {
   1165 	/* {
   1166 		syscallarg(int) fd;
   1167 		syscallarg(netbsd32_charp) path;
   1168 		syscallarg(netbsd32_timespecp_t) tptr;
   1169 		syscallarg(int) flag;
   1170 	} */
   1171 	struct netbsd32_timespec ts32[2];
   1172 	struct timespec ts[2];
   1173 	int follow;
   1174 	int error;
   1175 
   1176 	if ((error = copyin(SCARG_P32(uap, tptr), ts32, sizeof(ts32))) != 0)
   1177 		return (error);
   1178 
   1179 	netbsd32_to_timespec(&ts32[0], &ts[0]);
   1180 	netbsd32_to_timespec(&ts32[1], &ts[1]);
   1181 
   1182 	follow = (SCARG(uap, flag) & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW;
   1183 
   1184 	error = do_sys_utimensat(l, SCARG(uap, fd), NULL,
   1185 	    SCARG_P32(uap, path), follow, ts, UIO_SYSSPACE);
   1186 
   1187 	return error;
   1188 }
   1189 
   1190 int
   1191 netbsd32_openat(struct lwp *l, const struct netbsd32_openat_args *uap,
   1192 		 register_t *retval)
   1193 {
   1194 	/* {
   1195 		syscallarg(int) fd;
   1196 		syscallarg(netbsd32_charp) path;
   1197 		syscallarg(int) oflags;
   1198 		syscallarg(mode_t) mode;
   1199 	} */
   1200 	struct sys_openat_args ua;
   1201 
   1202 	NETBSD32TO64_UAP(fd);
   1203 	NETBSD32TOP_UAP(path, const char);
   1204 	NETBSD32TO64_UAP(oflags);
   1205 	NETBSD32TO64_UAP(mode);
   1206 
   1207 	return sys_openat(l, &ua, retval);
   1208 }
   1209 
   1210 int
   1211 netbsd32_readlinkat(struct lwp *l, const struct netbsd32_readlinkat_args *uap,
   1212 		 register_t *retval)
   1213 {
   1214 	/* {
   1215 		syscallarg(int) fd;
   1216 		syscallarg(netbsd32_charp) path;
   1217 		syscallarg(netbsd32_charp) buf;
   1218 		syscallarg(netbsd32_size_t) bufsize;
   1219 	} */
   1220 	struct sys_readlinkat_args ua;
   1221 
   1222 	NETBSD32TO64_UAP(fd);
   1223 	NETBSD32TOP_UAP(path, const char *);
   1224 	NETBSD32TOP_UAP(buf, char *);
   1225 	NETBSD32TOX_UAP(bufsize, size_t);
   1226 
   1227 	return sys_readlinkat(l, &ua, retval);
   1228 }
   1229 
   1230 int
   1231 netbsd32_symlinkat(struct lwp *l, const struct netbsd32_symlinkat_args *uap,
   1232 		 register_t *retval)
   1233 {
   1234 	/* {
   1235 		syscallarg(netbsd32_charp) path1;
   1236 		syscallarg(int) fd;
   1237 		syscallarg(netbsd32_charp) path2;
   1238 	} */
   1239 	struct sys_symlinkat_args ua;
   1240 
   1241 	NETBSD32TOP_UAP(path1, const char *);
   1242 	NETBSD32TO64_UAP(fd);
   1243 	NETBSD32TOP_UAP(path2, const char *);
   1244 
   1245 	return sys_symlinkat(l, &ua, retval);
   1246 }
   1247 
   1248 int
   1249 netbsd32_unlinkat(struct lwp *l, const struct netbsd32_unlinkat_args *uap,
   1250 		 register_t *retval)
   1251 {
   1252 	/* {
   1253 		syscallarg(int) fd;
   1254 		syscallarg(netbsd32_charp) path;
   1255 		syscallarg(int) flag;
   1256 	} */
   1257 	struct sys_unlinkat_args ua;
   1258 
   1259 	NETBSD32TO64_UAP(fd);
   1260 	NETBSD32TOP_UAP(path, const char *);
   1261 	NETBSD32TO64_UAP(flag);
   1262 
   1263 	return sys_unlinkat(l, &ua, retval);
   1264 }
   1265 
   1266 int
   1267 netbsd32_futimens(struct lwp *l, const struct netbsd32_futimens_args *uap,
   1268 		 register_t *retval)
   1269 {
   1270 	/* {
   1271 		syscallarg(int) fd;
   1272 		syscallarg(netbsd32_timespecp_t) tptr;
   1273 	} */
   1274 	struct netbsd32_timespec ts32;
   1275 	struct timespec ts;
   1276 	file_t *fp;
   1277 	int error;
   1278 
   1279 	if ((error = copyin(SCARG_P32(uap, tptr), &ts32, sizeof(ts32))) != 0)
   1280 		return (error);
   1281 
   1282 	netbsd32_to_timespec(&ts32, &ts);
   1283 
   1284 	/* fd_getvnode() will use the descriptor for us */
   1285 	if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
   1286 		return (error);
   1287 	error = do_sys_utimensat(l, AT_FDCWD, fp->f_data, NULL, 0,
   1288 	    &ts, UIO_SYSSPACE);
   1289 	fd_putfile(SCARG(uap, fd));
   1290 	return (error);
   1291 }
   1292