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