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