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