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