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