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