netbsd32_fs.c revision 1.46.10.1 1 /* $NetBSD: netbsd32_fs.c,v 1.46.10.1 2007/12/08 17:56:58 ad 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 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: netbsd32_fs.c,v 1.46.10.1 2007/12/08 17:56:58 ad Exp $");
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/malloc.h>
37 #include <sys/mount.h>
38 #include <sys/socket.h>
39 #include <sys/socketvar.h>
40 #include <sys/stat.h>
41 #include <sys/time.h>
42 #include <sys/ktrace.h>
43 #include <sys/resourcevar.h>
44 #include <sys/vnode.h>
45 #include <sys/file.h>
46 #include <sys/filedesc.h>
47 #include <sys/namei.h>
48 #include <sys/statvfs.h>
49 #include <sys/syscallargs.h>
50 #include <sys/proc.h>
51 #include <sys/dirent.h>
52 #include <sys/kauth.h>
53 #include <sys/vfs_syscalls.h>
54
55 #include <compat/netbsd32/netbsd32.h>
56 #include <compat/netbsd32/netbsd32_syscallargs.h>
57 #include <compat/netbsd32/netbsd32_conv.h>
58 #include <compat/sys/mount.h>
59
60
61 static int dofilereadv32(struct lwp *, int, struct file *, struct netbsd32_iovec *,
62 int, off_t *, int, register_t *);
63 static int dofilewritev32(struct lwp *, int, struct file *, struct netbsd32_iovec *,
64 int, off_t *, int, register_t *);
65
66 struct iovec *
67 netbsd32_get_iov(struct netbsd32_iovec *iov32, int iovlen, struct iovec *aiov,
68 int aiov_len)
69 {
70 #define N_IOV32 8
71 struct netbsd32_iovec aiov32[N_IOV32];
72 struct iovec *iov = aiov;
73 struct iovec *iovp;
74 int i, n, j;
75 int error;
76
77 if (iovlen < 0 || iovlen > IOV_MAX)
78 return NULL;
79
80 if (iovlen > aiov_len)
81 iov = malloc(iovlen * sizeof (*iov), M_TEMP, M_WAITOK);
82
83 iovp = iov;
84 for (i = 0; i < iovlen; iov32 += N_IOV32, i += N_IOV32) {
85 n = iovlen - i;
86 if (n > N_IOV32)
87 n = N_IOV32;
88 error = copyin(iov32, aiov32, n * sizeof (*iov32));
89 if (error != 0) {
90 if (iov != aiov)
91 free(iov, M_TEMP);
92 return NULL;
93 }
94 for (j = 0; j < n; iovp++, j++) {
95 iovp->iov_base = NETBSD32PTR64(aiov32[j].iov_base);
96 iovp->iov_len = aiov32[j].iov_len;
97 }
98 }
99 return iov;
100 #undef N_IOV32
101 }
102
103 int
104 netbsd32_readv(l, v, retval)
105 struct lwp *l;
106 void *v;
107 register_t *retval;
108 {
109 struct netbsd32_readv_args /* {
110 syscallarg(int) fd;
111 syscallarg(const netbsd32_iovecp_t) iovp;
112 syscallarg(int) iovcnt;
113 } */ *uap = v;
114 int fd = SCARG(uap, fd);
115 struct proc *p = l->l_proc;
116 struct file *fp;
117 struct filedesc *fdp = p->p_fd;
118
119 if ((fp = fd_getfile(fdp, fd)) == NULL)
120 return (EBADF);
121
122 if ((fp->f_flag & FREAD) == 0)
123 return (EBADF);
124
125 FILE_USE(fp);
126
127 return (dofilereadv32(l, 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(l, fd, fp, iovp, iovcnt, offset, flags, retval)
135 struct lwp *l;
136 int fd;
137 struct file *fp;
138 struct netbsd32_iovec *iovp;
139 int iovcnt;
140 off_t *offset;
141 int flags;
142 register_t *retval;
143 {
144 struct uio auio;
145 struct iovec *iov;
146 struct iovec *needfree;
147 struct iovec aiov[UIO_SMALLIOV];
148 long i, cnt, error = 0;
149 u_int iovlen;
150 struct iovec *ktriov = NULL;
151
152 /* note: can't use iovlen until iovcnt is validated */
153 iovlen = iovcnt * sizeof(struct iovec);
154 if ((u_int)iovcnt > UIO_SMALLIOV) {
155 if ((u_int)iovcnt > IOV_MAX) {
156 error = EINVAL;
157 goto out;
158 }
159 iov = malloc(iovlen, M_IOV, M_WAITOK);
160 needfree = iov;
161 } else if ((u_int)iovcnt > 0) {
162 iov = aiov;
163 needfree = NULL;
164 } else {
165 error = EINVAL;
166 goto out;
167 }
168
169 auio.uio_iov = iov;
170 auio.uio_iovcnt = iovcnt;
171 auio.uio_rw = UIO_READ;
172 auio.uio_vmspace = l->l_proc->p_vmspace;
173 error = netbsd32_to_iovecin(iovp, iov, iovcnt);
174 if (error)
175 goto done;
176 auio.uio_resid = 0;
177 for (i = 0; i < iovcnt; i++) {
178 auio.uio_resid += iov->iov_len;
179 /*
180 * Reads return ssize_t because -1 is returned on error.
181 * Therefore we must restrict the length to SSIZE_MAX to
182 * avoid garbage return values.
183 */
184 if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
185 error = EINVAL;
186 goto done;
187 }
188 iov++;
189 }
190
191 /*
192 * if tracing, save a copy of iovec
193 */
194 if (ktrpoint(KTR_GENIO)) {
195 ktriov = malloc(iovlen, M_TEMP, M_WAITOK);
196 memcpy((void *)ktriov, (void *)auio.uio_iov, iovlen);
197 }
198
199 cnt = auio.uio_resid;
200 error = (*fp->f_ops->fo_read)(fp, offset, &auio, fp->f_cred, flags);
201 if (error)
202 if (auio.uio_resid != cnt && (error == ERESTART ||
203 error == EINTR || error == EWOULDBLOCK))
204 error = 0;
205 cnt -= auio.uio_resid;
206
207 if (ktriov != NULL) {
208 ktrgeniov(fd, UIO_READ, ktriov, cnt, error);
209 free(ktriov, M_TEMP);
210 }
211
212 *retval = cnt;
213 done:
214 if (needfree)
215 free(needfree, M_IOV);
216 out:
217 FILE_UNUSE(fp, l);
218 return (error);
219 }
220
221 int
222 netbsd32_writev(l, v, retval)
223 struct lwp *l;
224 void *v;
225 register_t *retval;
226 {
227 struct netbsd32_writev_args /* {
228 syscallarg(int) fd;
229 syscallarg(const netbsd32_iovecp_t) iovp;
230 syscallarg(int) iovcnt;
231 } */ *uap = v;
232 int fd = SCARG(uap, fd);
233 struct file *fp;
234 struct proc *p = l->l_proc;
235 struct filedesc *fdp = p->p_fd;
236
237 if ((fp = fd_getfile(fdp, fd)) == NULL)
238 return (EBADF);
239
240 if ((fp->f_flag & FWRITE) == 0)
241 return (EBADF);
242
243 FILE_USE(fp);
244
245 return (dofilewritev32(l, fd, fp,
246 (struct netbsd32_iovec *)SCARG_P32(uap, iovp),
247 SCARG(uap, iovcnt), &fp->f_offset, FOF_UPDATE_OFFSET, retval));
248 }
249
250 int
251 dofilewritev32(l, fd, fp, iovp, iovcnt, offset, flags, retval)
252 struct lwp *l;
253 int fd;
254 struct file *fp;
255 struct netbsd32_iovec *iovp;
256 int iovcnt;
257 off_t *offset;
258 int flags;
259 register_t *retval;
260 {
261 struct uio auio;
262 struct iovec *iov;
263 struct iovec *needfree;
264 struct iovec aiov[UIO_SMALLIOV];
265 struct proc *p = l->l_proc;
266 long i, cnt, error = 0;
267 u_int iovlen;
268 struct iovec *ktriov = NULL;
269
270 /* note: can't use iovlen until iovcnt is validated */
271 iovlen = iovcnt * sizeof(struct iovec);
272 if ((u_int)iovcnt > UIO_SMALLIOV) {
273 if ((u_int)iovcnt > IOV_MAX) {
274 error = EINVAL;
275 goto out;
276 }
277 iov = malloc(iovlen, M_IOV, M_WAITOK);
278 needfree = iov;
279 } else if ((u_int)iovcnt > 0) {
280 iov = aiov;
281 needfree = NULL;
282 } else {
283 error = EINVAL;
284 goto out;
285 }
286
287 auio.uio_iov = iov;
288 auio.uio_iovcnt = iovcnt;
289 auio.uio_rw = UIO_WRITE;
290 auio.uio_vmspace = l->l_proc->p_vmspace;
291 error = netbsd32_to_iovecin(iovp, iov, iovcnt);
292 if (error)
293 goto done;
294 auio.uio_resid = 0;
295 for (i = 0; i < iovcnt; i++) {
296 auio.uio_resid += iov->iov_len;
297 /*
298 * Writes return ssize_t because -1 is returned on error.
299 * Therefore we must restrict the length to SSIZE_MAX to
300 * avoid garbage return values.
301 */
302 if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
303 error = EINVAL;
304 goto done;
305 }
306 iov++;
307 }
308
309 /*
310 * if tracing, save a copy of iovec
311 */
312 if (ktrpoint(KTR_GENIO)) {
313 ktriov = malloc(iovlen, M_TEMP, M_WAITOK);
314 memcpy((void *)ktriov, (void *)auio.uio_iov, iovlen);
315 }
316
317 cnt = auio.uio_resid;
318 error = (*fp->f_ops->fo_write)(fp, offset, &auio, fp->f_cred, flags);
319 if (error) {
320 if (auio.uio_resid != cnt && (error == ERESTART ||
321 error == EINTR || error == EWOULDBLOCK))
322 error = 0;
323 if (error == EPIPE) {
324 mutex_enter(&proclist_mutex);
325 psignal(p, SIGPIPE);
326 mutex_exit(&proclist_mutex);
327 }
328 }
329 cnt -= auio.uio_resid;
330 if (ktriov != NULL) {
331 ktrgenio(fd, UIO_WRITE, ktriov, cnt, error);
332 free(ktriov, M_TEMP);
333 }
334 *retval = cnt;
335 done:
336 if (needfree)
337 free(needfree, M_IOV);
338 out:
339 FILE_UNUSE(fp, l);
340 return (error);
341 }
342
343 /*
344 * Common routine to set access and modification times given a vnode.
345 */
346 static int
347 get_utimes32(const netbsd32_timevalp_t *tptr, struct timeval *tv,
348 struct timeval **tvp)
349 {
350 int error;
351 struct netbsd32_timeval tv32[2];
352
353 if (tptr == NULL) {
354 *tvp = NULL;
355 return 0;
356 }
357
358 error = copyin(tptr, tv32, sizeof(tv32));
359 if (error)
360 return error;
361 netbsd32_to_timeval(&tv32[0], &tv[0]);
362 netbsd32_to_timeval(&tv32[1], &tv[1]);
363
364 *tvp = tv;
365 return 0;
366 }
367
368 int
369 netbsd32_utimes(l, v, retval)
370 struct lwp *l;
371 void *v;
372 register_t *retval;
373 {
374 struct netbsd32_utimes_args /* {
375 syscallarg(const netbsd32_charp) path;
376 syscallarg(const netbsd32_timevalp_t) tptr;
377 } */ *uap = v;
378 int error;
379 struct timeval tv[2], *tvp;
380
381 error = get_utimes32(SCARG_P32(uap, tptr), tv, &tvp);
382 if (error != 0)
383 return error;
384
385 return do_sys_utimes(l, NULL, SCARG_P32(uap, path), FOLLOW,
386 tvp, UIO_SYSSPACE);
387 }
388
389 static int
390 netbds32_copyout_statvfs(const void *kp, void *up, size_t len)
391 {
392 struct netbsd32_statvfs *sbuf_32;
393 int error;
394
395 sbuf_32 = malloc(sizeof *sbuf_32, M_TEMP, M_WAITOK);
396 netbsd32_from_statvfs(kp, sbuf_32);
397 error = copyout(sbuf_32, up, sizeof(*sbuf_32));
398 free(sbuf_32, M_TEMP);
399
400 return error;
401 }
402
403 int
404 netbsd32_statvfs1(l, v, retval)
405 struct lwp *l;
406 void *v;
407 register_t *retval;
408 {
409 struct netbsd32_statvfs1_args /* {
410 syscallarg(const netbsd32_charp) path;
411 syscallarg(netbsd32_statvfsp_t) buf;
412 syscallarg(int) flags;
413 } */ *uap = v;
414 struct statvfs *sb;
415 int error;
416
417 sb = STATVFSBUF_GET();
418 error = do_sys_pstatvfs(l, SCARG_P32(uap, path), SCARG(uap, flags), sb);
419 if (error == 0)
420 error = netbds32_copyout_statvfs(sb, SCARG_P32(uap, buf), 0);
421 STATVFSBUF_PUT(sb);
422 return error;
423 }
424
425 int
426 netbsd32_fstatvfs1(l, v, retval)
427 struct lwp *l;
428 void *v;
429 register_t *retval;
430 {
431 struct netbsd32_fstatvfs1_args /* {
432 syscallarg(int) fd;
433 syscallarg(netbsd32_statvfsp_t) buf;
434 syscallarg(int) flags;
435 } */ *uap = v;
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 = netbds32_copyout_statvfs(sb, SCARG_P32(uap, buf), 0);
443 STATVFSBUF_PUT(sb);
444 return error;
445 }
446
447 int
448 netbsd32_getvfsstat(l, v, retval)
449 struct lwp *l;
450 void *v;
451 register_t *retval;
452 {
453 struct netbsd32_getvfsstat_args /* {
454 syscallarg(netbsd32_statvfsp_t) buf;
455 syscallarg(netbsd32_size_t) bufsize;
456 syscallarg(int) flags;
457 } */ *uap = v;
458
459 return do_sys_getvfsstat(l, SCARG_P32(uap, buf), SCARG(uap, bufsize),
460 SCARG(uap, flags), netbds32_copyout_statvfs,
461 sizeof (struct netbsd32_statvfs), retval);
462 }
463
464 int
465 netbsd32___fhstatvfs140(l, v, retval)
466 struct lwp *l;
467 void *v;
468 register_t *retval;
469 {
470 struct netbsd32___fhstatvfs140_args /* {
471 syscallarg(const netbsd32_pointer_t) fhp;
472 syscallarg(netbsd32_size_t) fh_size;
473 syscallarg(netbsd32_statvfsp_t) buf;
474 syscallarg(int) flags;
475 } */ *uap = v;
476 struct statvfs *sb;
477 int error;
478
479 sb = STATVFSBUF_GET();
480 error = do_fhstatvfs(l, SCARG_P32(uap, fhp), SCARG(uap, fh_size), sb,
481 SCARG(uap, flags));
482
483 if (error == 0)
484 error = netbds32_copyout_statvfs(sb, SCARG_P32(uap, buf), 0);
485 STATVFSBUF_PUT(sb);
486
487 return error;
488 }
489
490 int
491 netbsd32_futimes(l, v, retval)
492 struct lwp *l;
493 void *v;
494 register_t *retval;
495 {
496 struct netbsd32_futimes_args /* {
497 syscallarg(int) fd;
498 syscallarg(const netbsd32_timevalp_t) tptr;
499 } */ *uap = v;
500 int error;
501 struct file *fp;
502 struct timeval tv[2], *tvp;
503
504 error = get_utimes32(SCARG_P32(uap, tptr), tv, &tvp);
505 if (error != 0)
506 return error;
507
508 /* getvnode() will use the descriptor for us */
509 if ((error = getvnode(l->l_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
510 return (error);
511
512 error = do_sys_utimes(l, fp->f_data, NULL, 0, tvp, UIO_SYSSPACE);
513
514 FILE_UNUSE(fp, l);
515 return (error);
516 }
517
518 int
519 netbsd32_sys___getdents30(l, v, retval)
520 struct lwp *l;
521 void *v;
522 register_t *retval;
523 {
524 struct netbsd32_sys___getdents30_args /* {
525 syscallarg(int) fd;
526 syscallarg(netbsd32_charp) buf;
527 syscallarg(netbsd32_size_t) count;
528 } */ *uap = v;
529 struct file *fp;
530 int error, done;
531 struct proc *p = l->l_proc;
532
533 /* getvnode() will use the descriptor for us */
534 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
535 return (error);
536 if ((fp->f_flag & FREAD) == 0) {
537 error = EBADF;
538 goto out;
539 }
540 error = vn_readdir(fp, SCARG_P32(uap, buf),
541 UIO_USERSPACE, SCARG(uap, count), &done, l, 0, 0);
542 *retval = done;
543 out:
544 FILE_UNUSE(fp, l);
545 return (error);
546 }
547
548 int
549 netbsd32_lutimes(l, v, retval)
550 struct lwp *l;
551 void *v;
552 register_t *retval;
553 {
554 struct netbsd32_lutimes_args /* {
555 syscallarg(const netbsd32_charp) path;
556 syscallarg(const netbsd32_timevalp_t) tptr;
557 } */ *uap = v;
558 int error;
559 struct timeval tv[2], *tvp;
560
561 error = get_utimes32(SCARG_P32(uap, tptr), tv, &tvp);
562 if (error != 0)
563 return error;
564
565 return do_sys_utimes(l, NULL, SCARG_P32(uap, path), NOFOLLOW,
566 tvp, UIO_SYSSPACE);
567 }
568
569 int
570 netbsd32_sys___stat30(l, v, retval)
571 struct lwp *l;
572 void *v;
573 register_t *retval;
574 {
575 struct netbsd32_sys___stat30_args /* {
576 syscallarg(const netbsd32_charp) path;
577 syscallarg(netbsd32_statp_t) ub;
578 } */ *uap = v;
579 struct netbsd32_stat sb32;
580 struct stat sb;
581 int error;
582 const char *path;
583
584 path = SCARG_P32(uap, path);
585
586 error = do_sys_stat(l, path, FOLLOW, &sb);
587 if (error)
588 return (error);
589 netbsd32_from___stat30(&sb, &sb32);
590 error = copyout(&sb32, SCARG_P32(uap, ub), sizeof(sb32));
591 return (error);
592 }
593
594 int
595 netbsd32_sys___fstat30(l, v, retval)
596 struct lwp *l;
597 void *v;
598 register_t *retval;
599 {
600 struct netbsd32_sys___fstat30_args /* {
601 syscallarg(int) fd;
602 syscallarg(netbsd32_statp_t) sb;
603 } */ *uap = v;
604 int fd = SCARG(uap, fd);
605 struct proc *p = l->l_proc;
606 struct filedesc *fdp = p->p_fd;
607 struct file *fp;
608 struct netbsd32_stat sb32;
609 struct stat ub;
610 int error = 0;
611
612 if ((fp = fd_getfile(fdp, fd)) == NULL)
613 return (EBADF);
614
615 FILE_USE(fp);
616 error = (*fp->f_ops->fo_stat)(fp, &ub, l);
617 FILE_UNUSE(fp, l);
618
619 if (error == 0) {
620 netbsd32_from___stat30(&ub, &sb32);
621 error = copyout(&sb32, SCARG_P32(uap, sb), sizeof(sb32));
622 }
623 return (error);
624 }
625
626 int
627 netbsd32_sys___lstat30(l, v, retval)
628 struct lwp *l;
629 void *v;
630 register_t *retval;
631 {
632 struct netbsd32_sys___lstat30_args /* {
633 syscallarg(const netbsd32_charp) path;
634 syscallarg(netbsd32_statp_t) ub;
635 } */ *uap = v;
636 struct netbsd32_stat sb32;
637 struct stat sb;
638 int error;
639 const char *path;
640
641 path = SCARG_P32(uap, path);
642
643 error = do_sys_stat(l, path, NOFOLLOW, &sb);
644 if (error)
645 return (error);
646 netbsd32_from___stat30(&sb, &sb32);
647 error = copyout(&sb32, SCARG_P32(uap, ub), sizeof(sb32));
648 return (error);
649 }
650
651 int netbsd32___fhstat40(l, v, retval)
652 struct lwp *l;
653 void *v;
654 register_t *retval;
655 {
656 struct netbsd32___fhstat40_args /* {
657 syscallarg(const netbsd32_pointer_t) fhp;
658 syscallarg(netbsd32_size_t) fh_size;
659 syscallarg(netbsd32_statp_t) sb;
660 } */ *uap = v;
661 struct stat sb;
662 struct netbsd32_stat sb32;
663 int error;
664
665 error = do_fhstat(l, SCARG_P32(uap, fhp), SCARG(uap, fh_size), &sb);
666 if (error != 0) {
667 netbsd32_from___stat30(&sb, &sb32);
668 error = copyout(&sb32, SCARG_P32(uap, sb), sizeof(sb));
669 }
670 return error;
671 }
672
673 int
674 netbsd32_preadv(l, v, retval)
675 struct lwp *l;
676 void *v;
677 register_t *retval;
678 {
679 struct netbsd32_preadv_args /* {
680 syscallarg(int) fd;
681 syscallarg(const netbsd32_iovecp_t) iovp;
682 syscallarg(int) iovcnt;
683 syscallarg(int) pad;
684 syscallarg(off_t) offset;
685 } */ *uap = v;
686 struct proc *p = l->l_proc;
687 struct filedesc *fdp = p->p_fd;
688 struct file *fp;
689 struct vnode *vp;
690 off_t offset;
691 int error, fd = SCARG(uap, fd);
692
693 if ((fp = fd_getfile(fdp, fd)) == NULL)
694 return (EBADF);
695
696 if ((fp->f_flag & FREAD) == 0)
697 return (EBADF);
698
699 FILE_USE(fp);
700
701 vp = (struct vnode *)fp->f_data;
702 if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
703 error = ESPIPE;
704 goto out;
705 }
706
707 offset = SCARG(uap, offset);
708
709 /*
710 * XXX This works because no file systems actually
711 * XXX take any action on the seek operation.
712 */
713 if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
714 goto out;
715
716 return (dofilereadv32(l, fd, fp, SCARG_P32(uap, iovp),
717 SCARG(uap, iovcnt), &offset, 0, retval));
718
719 out:
720 FILE_UNUSE(fp, l);
721 return (error);
722 }
723
724 int
725 netbsd32_pwritev(l, v, retval)
726 struct lwp *l;
727 void *v;
728 register_t *retval;
729 {
730 struct netbsd32_pwritev_args /* {
731 syscallarg(int) fd;
732 syscallarg(const netbsd32_iovecp_t) iovp;
733 syscallarg(int) iovcnt;
734 syscallarg(int) pad;
735 syscallarg(off_t) offset;
736 } */ *uap = v;
737 struct proc *p = l->l_proc;
738 struct filedesc *fdp = p->p_fd;
739 struct file *fp;
740 struct vnode *vp;
741 off_t offset;
742 int error, fd = SCARG(uap, fd);
743
744 if ((fp = fd_getfile(fdp, fd)) == NULL)
745 return (EBADF);
746
747 if ((fp->f_flag & FWRITE) == 0)
748 return (EBADF);
749
750 FILE_USE(fp);
751
752 vp = (struct vnode *)fp->f_data;
753 if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
754 error = ESPIPE;
755 goto out;
756 }
757
758 offset = SCARG(uap, offset);
759
760 /*
761 * XXX This works because no file systems actually
762 * XXX take any action on the seek operation.
763 */
764 if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
765 goto out;
766
767 return (dofilewritev32(l, fd, fp, SCARG_P32(uap, iovp),
768 SCARG(uap, iovcnt), &offset, 0, retval));
769
770 out:
771 FILE_UNUSE(fp, l);
772 return (error);
773 }
774
775 /*
776 * Find pathname of process's current directory.
777 *
778 * Use vfs vnode-to-name reverse cache; if that fails, fall back
779 * to reading directory contents.
780 */
781 /* XXX NH Why does this exist */
782 int
783 getcwd_common(struct vnode *, struct vnode *,
784 char **, char *, int, int, struct lwp *);
785
786 int netbsd32___getcwd(l, v, retval)
787 struct lwp *l;
788 void *v;
789 register_t *retval;
790 {
791 struct netbsd32___getcwd_args /* {
792 syscallarg(char *) bufp;
793 syscallarg(size_t) length;
794 } */ *uap = v;
795 struct proc *p = l->l_proc;
796 int error;
797 char *path;
798 char *bp, *bend;
799 int len = (int)SCARG(uap, length);
800 int lenused;
801
802 if (len > MAXPATHLEN*4)
803 len = MAXPATHLEN*4;
804 else if (len < 2)
805 return ERANGE;
806
807 path = (char *)malloc(len, M_TEMP, M_WAITOK);
808 if (!path)
809 return ENOMEM;
810
811 bp = &path[len];
812 bend = bp;
813 *(--bp) = '\0';
814
815 /*
816 * 5th argument here is "max number of vnodes to traverse".
817 * Since each entry takes up at least 2 bytes in the output buffer,
818 * limit it to N/2 vnodes for an N byte buffer.
819 */
820 #define GETCWD_CHECK_ACCESS 0x0001
821 error = getcwd_common (p->p_cwdi->cwdi_cdir, NULL, &bp, path, len/2,
822 GETCWD_CHECK_ACCESS, l);
823
824 if (error)
825 goto out;
826 lenused = bend - bp;
827 *retval = lenused;
828 /* put the result into user buffer */
829 error = copyout(bp, SCARG_P32(uap, bufp), lenused);
830
831 out:
832 free(path, M_TEMP);
833 return error;
834 }
835