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