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