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