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