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