1 /* $NetBSD: netbsd32_fs.c,v 1.46 2007/08/15 12:07:31 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 2007/08/15 12:07:31 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 __P((struct lwp *, int, struct file *, struct netbsd32_iovec *, 62 int, off_t *, int, register_t *)); 63 static int dofilewritev32 __P((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 __P((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