1 /* $NetBSD: netbsd32_fs.c,v 1.68 2013/07/30 17:22:31 njoly 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 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: netbsd32_fs.c,v 1.68 2013/07/30 17:22:31 njoly Exp $"); 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/mount.h> 35 #include <sys/socket.h> 36 #include <sys/socketvar.h> 37 #include <sys/stat.h> 38 #include <sys/time.h> 39 #include <sys/ktrace.h> 40 #include <sys/resourcevar.h> 41 #include <sys/vnode.h> 42 #include <sys/file.h> 43 #include <sys/filedesc.h> 44 #include <sys/namei.h> 45 #include <sys/statvfs.h> 46 #include <sys/syscallargs.h> 47 #include <sys/proc.h> 48 #include <sys/dirent.h> 49 #include <sys/kauth.h> 50 #include <sys/vfs_syscalls.h> 51 52 #include <fs/cd9660/cd9660_mount.h> 53 #include <fs/msdosfs/bpb.h> 54 #include <fs/msdosfs/msdosfsmount.h> 55 #include <ufs/ufs/ufsmount.h> 56 57 #define NFS_ARGS_ONLY 58 #include <nfs/nfsmount.h> 59 60 #include <compat/netbsd32/netbsd32.h> 61 #include <compat/netbsd32/netbsd32_syscallargs.h> 62 #include <compat/netbsd32/netbsd32_conv.h> 63 #include <compat/sys/mount.h> 64 65 66 static int dofilereadv32(int, struct file *, struct netbsd32_iovec *, 67 int, off_t *, int, register_t *); 68 static int dofilewritev32(int, struct file *, struct netbsd32_iovec *, 69 int, off_t *, int, register_t *); 70 71 struct iovec * 72 netbsd32_get_iov(struct netbsd32_iovec *iov32, int iovlen, struct iovec *aiov, 73 int aiov_len) 74 { 75 #define N_IOV32 8 76 struct netbsd32_iovec aiov32[N_IOV32]; 77 struct iovec *iov = aiov; 78 struct iovec *iovp; 79 int i, n, j; 80 int error; 81 82 if (iovlen < 0 || iovlen > IOV_MAX) 83 return NULL; 84 85 if (iovlen > aiov_len) 86 iov = kmem_alloc(iovlen * sizeof(*iov), KM_SLEEP); 87 88 iovp = iov; 89 for (i = 0; i < iovlen; iov32 += N_IOV32, i += N_IOV32) { 90 n = iovlen - i; 91 if (n > N_IOV32) 92 n = N_IOV32; 93 error = copyin(iov32, aiov32, n * sizeof (*iov32)); 94 if (error != 0) { 95 if (iov != aiov) 96 kmem_free(iov, iovlen * sizeof(*iov)); 97 return NULL; 98 } 99 for (j = 0; j < n; iovp++, j++) { 100 iovp->iov_base = NETBSD32PTR64(aiov32[j].iov_base); 101 iovp->iov_len = aiov32[j].iov_len; 102 } 103 } 104 return iov; 105 #undef N_IOV32 106 } 107 108 int 109 netbsd32_readv(struct lwp *l, const struct netbsd32_readv_args *uap, register_t *retval) 110 { 111 /* { 112 syscallarg(int) fd; 113 syscallarg(const netbsd32_iovecp_t) iovp; 114 syscallarg(int) iovcnt; 115 } */ 116 int fd = SCARG(uap, fd); 117 file_t *fp; 118 119 if ((fp = fd_getfile(fd)) == NULL) 120 return (EBADF); 121 122 if ((fp->f_flag & FREAD) == 0) { 123 fd_putfile(fd); 124 return (EBADF); 125 } 126 127 return (dofilereadv32(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(int fd, struct file *fp, struct netbsd32_iovec *iovp, int iovcnt, off_t *offset, int flags, register_t *retval) 135 { 136 struct uio auio; 137 struct iovec *iov; 138 struct iovec *needfree; 139 struct iovec aiov[UIO_SMALLIOV]; 140 long i, cnt, error = 0; 141 u_int iovlen; 142 struct iovec *ktriov = NULL; 143 144 /* note: can't use iovlen until iovcnt is validated */ 145 iovlen = iovcnt * sizeof(struct iovec); 146 if ((u_int)iovcnt > UIO_SMALLIOV) { 147 if ((u_int)iovcnt > IOV_MAX) { 148 error = EINVAL; 149 goto out; 150 } 151 iov = kmem_alloc(iovlen, KM_SLEEP); 152 needfree = iov; 153 } else if ((u_int)iovcnt > 0) { 154 iov = aiov; 155 needfree = NULL; 156 } else { 157 error = EINVAL; 158 goto out; 159 } 160 161 auio.uio_iov = iov; 162 auio.uio_iovcnt = iovcnt; 163 auio.uio_rw = UIO_READ; 164 auio.uio_vmspace = curproc->p_vmspace; 165 error = netbsd32_to_iovecin(iovp, iov, iovcnt); 166 if (error) 167 goto done; 168 auio.uio_resid = 0; 169 for (i = 0; i < iovcnt; i++) { 170 auio.uio_resid += iov->iov_len; 171 /* 172 * Reads return ssize_t because -1 is returned on error. 173 * Therefore we must restrict the length to SSIZE_MAX to 174 * avoid garbage return values. 175 */ 176 if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) { 177 error = EINVAL; 178 goto done; 179 } 180 iov++; 181 } 182 183 /* 184 * if tracing, save a copy of iovec 185 */ 186 if (ktrpoint(KTR_GENIO)) { 187 ktriov = kmem_alloc(iovlen, KM_SLEEP); 188 memcpy((void *)ktriov, (void *)auio.uio_iov, iovlen); 189 } 190 191 cnt = auio.uio_resid; 192 error = (*fp->f_ops->fo_read)(fp, offset, &auio, fp->f_cred, flags); 193 if (error) 194 if (auio.uio_resid != cnt && (error == ERESTART || 195 error == EINTR || error == EWOULDBLOCK)) 196 error = 0; 197 cnt -= auio.uio_resid; 198 199 if (ktriov != NULL) { 200 ktrgeniov(fd, UIO_READ, ktriov, cnt, error); 201 kmem_free(ktriov, iovlen); 202 } 203 204 *retval = cnt; 205 done: 206 if (needfree) 207 kmem_free(needfree, iovlen); 208 out: 209 fd_putfile(fd); 210 return (error); 211 } 212 213 int 214 netbsd32_writev(struct lwp *l, const struct netbsd32_writev_args *uap, register_t *retval) 215 { 216 /* { 217 syscallarg(int) fd; 218 syscallarg(const netbsd32_iovecp_t) iovp; 219 syscallarg(int) iovcnt; 220 } */ 221 int fd = SCARG(uap, fd); 222 file_t *fp; 223 224 if ((fp = fd_getfile(fd)) == NULL) 225 return (EBADF); 226 227 if ((fp->f_flag & FWRITE) == 0) { 228 fd_putfile(fd); 229 return (EBADF); 230 } 231 232 return (dofilewritev32(fd, fp, 233 (struct netbsd32_iovec *)SCARG_P32(uap, iovp), 234 SCARG(uap, iovcnt), &fp->f_offset, FOF_UPDATE_OFFSET, retval)); 235 } 236 237 int 238 dofilewritev32(int fd, struct file *fp, struct netbsd32_iovec *iovp, int iovcnt, off_t *offset, int flags, register_t *retval) 239 { 240 struct uio auio; 241 struct iovec *iov; 242 struct iovec *needfree; 243 struct iovec aiov[UIO_SMALLIOV]; 244 long i, cnt, error = 0; 245 u_int iovlen; 246 struct iovec *ktriov = NULL; 247 248 /* note: can't use iovlen until iovcnt is validated */ 249 iovlen = iovcnt * sizeof(struct iovec); 250 if ((u_int)iovcnt > UIO_SMALLIOV) { 251 if ((u_int)iovcnt > IOV_MAX) { 252 error = EINVAL; 253 goto out; 254 } 255 iov = kmem_alloc(iovlen, KM_SLEEP); 256 needfree = iov; 257 } else if ((u_int)iovcnt > 0) { 258 iov = aiov; 259 needfree = NULL; 260 } else { 261 error = EINVAL; 262 goto out; 263 } 264 265 auio.uio_iov = iov; 266 auio.uio_iovcnt = iovcnt; 267 auio.uio_rw = UIO_WRITE; 268 auio.uio_vmspace = curproc->p_vmspace; 269 error = netbsd32_to_iovecin(iovp, iov, iovcnt); 270 if (error) 271 goto done; 272 auio.uio_resid = 0; 273 for (i = 0; i < iovcnt; i++) { 274 auio.uio_resid += iov->iov_len; 275 /* 276 * Writes return ssize_t because -1 is returned on error. 277 * Therefore we must restrict the length to SSIZE_MAX to 278 * avoid garbage return values. 279 */ 280 if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) { 281 error = EINVAL; 282 goto done; 283 } 284 iov++; 285 } 286 287 /* 288 * if tracing, save a copy of iovec 289 */ 290 if (ktrpoint(KTR_GENIO)) { 291 ktriov = kmem_alloc(iovlen, KM_SLEEP); 292 memcpy((void *)ktriov, (void *)auio.uio_iov, iovlen); 293 } 294 295 cnt = auio.uio_resid; 296 error = (*fp->f_ops->fo_write)(fp, offset, &auio, fp->f_cred, flags); 297 if (error) { 298 if (auio.uio_resid != cnt && (error == ERESTART || 299 error == EINTR || error == EWOULDBLOCK)) 300 error = 0; 301 if (error == EPIPE && (fp->f_flag & FNOSIGPIPE) == 0) { 302 mutex_enter(proc_lock); 303 psignal(curproc, SIGPIPE); 304 mutex_exit(proc_lock); 305 } 306 } 307 cnt -= auio.uio_resid; 308 if (ktriov != NULL) { 309 ktrgenio(fd, UIO_WRITE, ktriov, cnt, error); 310 kmem_free(ktriov, iovlen); 311 } 312 *retval = cnt; 313 done: 314 if (needfree) 315 kmem_free(needfree, iovlen); 316 out: 317 fd_putfile(fd); 318 return (error); 319 } 320 321 /* 322 * Common routines to set access and modification times given a vnode. 323 */ 324 static int 325 get_utimes32(const netbsd32_timevalp_t *tptr, struct timeval *tv, 326 struct timeval **tvp) 327 { 328 int error; 329 struct netbsd32_timeval tv32[2]; 330 331 if (tptr == NULL) { 332 *tvp = NULL; 333 return 0; 334 } 335 336 error = copyin(tptr, tv32, sizeof(tv32)); 337 if (error) 338 return error; 339 netbsd32_to_timeval(&tv32[0], &tv[0]); 340 netbsd32_to_timeval(&tv32[1], &tv[1]); 341 342 *tvp = tv; 343 return 0; 344 } 345 346 static int 347 get_utimens32(const netbsd32_timespecp_t *tptr, struct timespec *ts, 348 struct timespec **tsp) 349 { 350 int error; 351 struct netbsd32_timespec ts32[2]; 352 353 if (tptr == NULL) { 354 *tsp = NULL; 355 return 0; 356 } 357 358 error = copyin(tptr, ts32, sizeof(ts32)); 359 if (error) 360 return error; 361 netbsd32_to_timespec(&ts32[0], &ts[0]); 362 netbsd32_to_timespec(&ts32[1], &ts[1]); 363 364 *tsp = ts; 365 return 0; 366 } 367 368 int 369 netbsd32___utimes50(struct lwp *l, const struct netbsd32___utimes50_args *uap, register_t *retval) 370 { 371 /* { 372 syscallarg(const netbsd32_charp) path; 373 syscallarg(const netbsd32_timevalp_t) tptr; 374 } */ 375 int error; 376 struct timeval tv[2], *tvp; 377 378 error = get_utimes32(SCARG_P32(uap, tptr), tv, &tvp); 379 if (error != 0) 380 return error; 381 382 return do_sys_utimes(l, NULL, SCARG_P32(uap, path), FOLLOW, 383 tvp, UIO_SYSSPACE); 384 } 385 386 static int 387 netbds32_copyout_statvfs(const void *kp, void *up, size_t len) 388 { 389 struct netbsd32_statvfs *sbuf_32; 390 int error; 391 392 sbuf_32 = kmem_alloc(sizeof(*sbuf_32), KM_SLEEP); 393 netbsd32_from_statvfs(kp, sbuf_32); 394 error = copyout(sbuf_32, up, sizeof(*sbuf_32)); 395 kmem_free(sbuf_32, sizeof(*sbuf_32)); 396 397 return error; 398 } 399 400 int 401 netbsd32_statvfs1(struct lwp *l, const struct netbsd32_statvfs1_args *uap, register_t *retval) 402 { 403 /* { 404 syscallarg(const netbsd32_charp) path; 405 syscallarg(netbsd32_statvfsp_t) buf; 406 syscallarg(int) flags; 407 } */ 408 struct statvfs *sb; 409 int error; 410 411 sb = STATVFSBUF_GET(); 412 error = do_sys_pstatvfs(l, SCARG_P32(uap, path), SCARG(uap, flags), sb); 413 if (error == 0) 414 error = netbds32_copyout_statvfs(sb, SCARG_P32(uap, buf), 0); 415 STATVFSBUF_PUT(sb); 416 return error; 417 } 418 419 int 420 netbsd32_fstatvfs1(struct lwp *l, const struct netbsd32_fstatvfs1_args *uap, register_t *retval) 421 { 422 /* { 423 syscallarg(int) fd; 424 syscallarg(netbsd32_statvfsp_t) buf; 425 syscallarg(int) flags; 426 } */ 427 struct statvfs *sb; 428 int error; 429 430 sb = STATVFSBUF_GET(); 431 error = do_sys_fstatvfs(l, SCARG(uap, fd), SCARG(uap, flags), sb); 432 if (error == 0) 433 error = netbds32_copyout_statvfs(sb, SCARG_P32(uap, buf), 0); 434 STATVFSBUF_PUT(sb); 435 return error; 436 } 437 438 int 439 netbsd32_getvfsstat(struct lwp *l, const struct netbsd32_getvfsstat_args *uap, register_t *retval) 440 { 441 /* { 442 syscallarg(netbsd32_statvfsp_t) buf; 443 syscallarg(netbsd32_size_t) bufsize; 444 syscallarg(int) flags; 445 } */ 446 447 return do_sys_getvfsstat(l, SCARG_P32(uap, buf), SCARG(uap, bufsize), 448 SCARG(uap, flags), netbds32_copyout_statvfs, 449 sizeof (struct netbsd32_statvfs), retval); 450 } 451 452 int 453 netbsd32___fhstatvfs140(struct lwp *l, const struct netbsd32___fhstatvfs140_args *uap, register_t *retval) 454 { 455 /* { 456 syscallarg(const netbsd32_pointer_t) fhp; 457 syscallarg(netbsd32_size_t) fh_size; 458 syscallarg(netbsd32_statvfsp_t) buf; 459 syscallarg(int) flags; 460 } */ 461 struct statvfs *sb; 462 int error; 463 464 sb = STATVFSBUF_GET(); 465 error = do_fhstatvfs(l, SCARG_P32(uap, fhp), SCARG(uap, fh_size), sb, 466 SCARG(uap, flags)); 467 468 if (error == 0) 469 error = netbds32_copyout_statvfs(sb, SCARG_P32(uap, buf), 0); 470 STATVFSBUF_PUT(sb); 471 472 return error; 473 } 474 475 int 476 netbsd32___futimes50(struct lwp *l, const struct netbsd32___futimes50_args *uap, register_t *retval) 477 { 478 /* { 479 syscallarg(int) fd; 480 syscallarg(const netbsd32_timevalp_t) tptr; 481 } */ 482 int error; 483 file_t *fp; 484 struct timeval tv[2], *tvp; 485 486 error = get_utimes32(SCARG_P32(uap, tptr), tv, &tvp); 487 if (error != 0) 488 return error; 489 490 /* fd_getvnode() will use the descriptor for us */ 491 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 492 return (error); 493 494 error = do_sys_utimes(l, fp->f_data, NULL, 0, tvp, UIO_SYSSPACE); 495 496 fd_putfile(SCARG(uap, fd)); 497 return (error); 498 } 499 500 int 501 netbsd32___getdents30(struct lwp *l, 502 const struct netbsd32___getdents30_args *uap, register_t *retval) 503 { 504 /* { 505 syscallarg(int) fd; 506 syscallarg(netbsd32_charp) buf; 507 syscallarg(netbsd32_size_t) count; 508 } */ 509 file_t *fp; 510 int error, done; 511 512 /* fd_getvnode() will use the descriptor for us */ 513 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 514 return (error); 515 if ((fp->f_flag & FREAD) == 0) { 516 error = EBADF; 517 goto out; 518 } 519 error = vn_readdir(fp, SCARG_P32(uap, buf), 520 UIO_USERSPACE, SCARG(uap, count), &done, l, 0, 0); 521 *retval = done; 522 out: 523 fd_putfile(SCARG(uap, fd)); 524 return (error); 525 } 526 527 int 528 netbsd32___lutimes50(struct lwp *l, 529 const struct netbsd32___lutimes50_args *uap, register_t *retval) 530 { 531 /* { 532 syscallarg(const netbsd32_charp) path; 533 syscallarg(const netbsd32_timevalp_t) tptr; 534 } */ 535 int error; 536 struct timeval tv[2], *tvp; 537 538 error = get_utimes32(SCARG_P32(uap, tptr), tv, &tvp); 539 if (error != 0) 540 return error; 541 542 return do_sys_utimes(l, NULL, SCARG_P32(uap, path), NOFOLLOW, 543 tvp, UIO_SYSSPACE); 544 } 545 546 int 547 netbsd32___stat50(struct lwp *l, const struct netbsd32___stat50_args *uap, register_t *retval) 548 { 549 /* { 550 syscallarg(const netbsd32_charp) path; 551 syscallarg(netbsd32_statp_t) ub; 552 } */ 553 struct netbsd32_stat sb32; 554 struct stat sb; 555 int error; 556 const char *path; 557 558 path = SCARG_P32(uap, path); 559 560 error = do_sys_stat(path, FOLLOW, &sb); 561 if (error) 562 return (error); 563 netbsd32_from_stat(&sb, &sb32); 564 error = copyout(&sb32, SCARG_P32(uap, ub), sizeof(sb32)); 565 return (error); 566 } 567 568 int 569 netbsd32___fstat50(struct lwp *l, const struct netbsd32___fstat50_args *uap, register_t *retval) 570 { 571 /* { 572 syscallarg(int) fd; 573 syscallarg(netbsd32_statp_t) sb; 574 } */ 575 struct netbsd32_stat sb32; 576 struct stat ub; 577 int error; 578 579 error = do_sys_fstat(SCARG(uap, fd), &ub); 580 if (error == 0) { 581 netbsd32_from_stat(&ub, &sb32); 582 error = copyout(&sb32, SCARG_P32(uap, sb), sizeof(sb32)); 583 } 584 return (error); 585 } 586 587 int 588 netbsd32___lstat50(struct lwp *l, const struct netbsd32___lstat50_args *uap, register_t *retval) 589 { 590 /* { 591 syscallarg(const netbsd32_charp) path; 592 syscallarg(netbsd32_statp_t) ub; 593 } */ 594 struct netbsd32_stat sb32; 595 struct stat sb; 596 int error; 597 const char *path; 598 599 path = SCARG_P32(uap, path); 600 601 error = do_sys_stat(path, NOFOLLOW, &sb); 602 if (error) 603 return (error); 604 netbsd32_from_stat(&sb, &sb32); 605 error = copyout(&sb32, SCARG_P32(uap, ub), sizeof(sb32)); 606 return (error); 607 } 608 609 int 610 netbsd32___fhstat50(struct lwp *l, const struct netbsd32___fhstat50_args *uap, register_t *retval) 611 { 612 /* { 613 syscallarg(const netbsd32_pointer_t) fhp; 614 syscallarg(netbsd32_size_t) fh_size; 615 syscallarg(netbsd32_statp_t) sb; 616 } */ 617 struct stat sb; 618 struct netbsd32_stat sb32; 619 int error; 620 621 error = do_fhstat(l, SCARG_P32(uap, fhp), SCARG(uap, fh_size), &sb); 622 if (error == 0) { 623 netbsd32_from_stat(&sb, &sb32); 624 error = copyout(&sb32, SCARG_P32(uap, sb), sizeof(sb)); 625 } 626 return error; 627 } 628 629 int 630 netbsd32_preadv(struct lwp *l, const struct netbsd32_preadv_args *uap, register_t *retval) 631 { 632 /* { 633 syscallarg(int) fd; 634 syscallarg(const netbsd32_iovecp_t) iovp; 635 syscallarg(int) iovcnt; 636 syscallarg(int) pad; 637 syscallarg(off_t) offset; 638 } */ 639 file_t *fp; 640 struct vnode *vp; 641 off_t offset; 642 int error, fd = SCARG(uap, fd); 643 644 if ((fp = fd_getfile(fd)) == NULL) 645 return (EBADF); 646 647 if ((fp->f_flag & FREAD) == 0) { 648 fd_putfile(fd); 649 return (EBADF); 650 } 651 652 vp = fp->f_data; 653 if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) { 654 error = ESPIPE; 655 goto out; 656 } 657 658 offset = SCARG(uap, offset); 659 660 /* 661 * XXX This works because no file systems actually 662 * XXX take any action on the seek operation. 663 */ 664 if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0) 665 goto out; 666 667 return (dofilereadv32(fd, fp, SCARG_P32(uap, iovp), 668 SCARG(uap, iovcnt), &offset, 0, retval)); 669 670 out: 671 fd_putfile(fd); 672 return (error); 673 } 674 675 int 676 netbsd32_pwritev(struct lwp *l, const struct netbsd32_pwritev_args *uap, register_t *retval) 677 { 678 /* { 679 syscallarg(int) fd; 680 syscallarg(const netbsd32_iovecp_t) iovp; 681 syscallarg(int) iovcnt; 682 syscallarg(int) pad; 683 syscallarg(off_t) offset; 684 } */ 685 file_t *fp; 686 struct vnode *vp; 687 off_t offset; 688 int error, fd = SCARG(uap, fd); 689 690 if ((fp = fd_getfile(fd)) == NULL) 691 return (EBADF); 692 693 if ((fp->f_flag & FWRITE) == 0) { 694 fd_putfile(fd); 695 return (EBADF); 696 } 697 698 vp = fp->f_data; 699 if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) { 700 error = ESPIPE; 701 goto out; 702 } 703 704 offset = SCARG(uap, offset); 705 706 /* 707 * XXX This works because no file systems actually 708 * XXX take any action on the seek operation. 709 */ 710 if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0) 711 goto out; 712 713 return (dofilewritev32(fd, fp, SCARG_P32(uap, iovp), 714 SCARG(uap, iovcnt), &offset, 0, retval)); 715 716 out: 717 fd_putfile(fd); 718 return (error); 719 } 720 721 /* 722 * Find pathname of process's current directory. 723 * 724 * Use vfs vnode-to-name reverse cache; if that fails, fall back 725 * to reading directory contents. 726 */ 727 /* XXX NH Why does this exist */ 728 int 729 getcwd_common(struct vnode *, struct vnode *, 730 char **, char *, int, int, struct lwp *); 731 732 int 733 netbsd32___getcwd(struct lwp *l, const struct netbsd32___getcwd_args *uap, register_t *retval) 734 { 735 /* { 736 syscallarg(char *) bufp; 737 syscallarg(size_t) length; 738 } */ 739 struct proc *p = l->l_proc; 740 int error; 741 char *path; 742 char *bp, *bend; 743 int len = (int)SCARG(uap, length); 744 int lenused; 745 struct cwdinfo *cwdi; 746 747 if (len > MAXPATHLEN*4) 748 len = MAXPATHLEN*4; 749 else if (len < 2) 750 return ERANGE; 751 752 path = kmem_alloc(len, KM_SLEEP); 753 if (!path) 754 return ENOMEM; 755 756 bp = &path[len]; 757 bend = bp; 758 *(--bp) = '\0'; 759 760 /* 761 * 5th argument here is "max number of vnodes to traverse". 762 * Since each entry takes up at least 2 bytes in the output buffer, 763 * limit it to N/2 vnodes for an N byte buffer. 764 */ 765 #define GETCWD_CHECK_ACCESS 0x0001 766 cwdi = p->p_cwdi; 767 rw_enter(&cwdi->cwdi_lock, RW_READER); 768 error = getcwd_common (cwdi->cwdi_cdir, NULL, &bp, path, len/2, 769 GETCWD_CHECK_ACCESS, l); 770 rw_exit(&cwdi->cwdi_lock); 771 772 if (error) 773 goto out; 774 lenused = bend - bp; 775 *retval = lenused; 776 /* put the result into user buffer */ 777 error = copyout(bp, SCARG_P32(uap, bufp), lenused); 778 779 out: 780 kmem_free(path, len); 781 return error; 782 } 783 784 int 785 netbsd32___mount50(struct lwp *l, const struct netbsd32___mount50_args *uap, 786 register_t *retval) 787 { 788 /* { 789 syscallarg(netbsd32_charp) type; 790 syscallarg(netbsd32_charp) path; 791 syscallarg(int) flags; 792 syscallarg(netbsd32_voidp) data; 793 syscallarg(netbsd32_size_t) data_len; 794 } */ 795 char mtype[MNAMELEN]; 796 union { 797 struct netbsd32_ufs_args ufs_args; 798 struct netbsd32_mfs_args mfs_args; 799 struct netbsd32_iso_args iso_args; 800 struct netbsd32_nfs_args nfs_args; 801 struct netbsd32_msdosfs_args msdosfs_args; 802 } fs_args32; 803 union { 804 struct ufs_args ufs_args; 805 struct mfs_args mfs_args; 806 struct iso_args iso_args; 807 struct nfs_args nfs_args; 808 struct msdosfs_args msdosfs_args; 809 } fs_args; 810 const char *type = SCARG_P32(uap, type); 811 const char *path = SCARG_P32(uap, path); 812 int flags = SCARG(uap, flags); 813 void *data = SCARG_P32(uap, data); 814 size_t data_len = SCARG(uap, data_len); 815 enum uio_seg data_seg; 816 size_t len; 817 int error; 818 819 error = copyinstr(type, mtype, sizeof(mtype), &len); 820 if (error) 821 return error; 822 if (strcmp(mtype, MOUNT_MFS) == 0) { 823 if (data_len != sizeof(fs_args32.mfs_args)) 824 return EINVAL; 825 if ((flags & MNT_GETARGS) == 0) { 826 error = copyin(data, &fs_args32.mfs_args, 827 sizeof(fs_args32.mfs_args)); 828 if (error) 829 return error; 830 fs_args.mfs_args.fspec = 831 NETBSD32PTR64(fs_args32.mfs_args.fspec); 832 memset(&fs_args.mfs_args._pad1, 0, 833 sizeof(fs_args.mfs_args._pad1)); 834 fs_args.mfs_args.base = 835 NETBSD32PTR64(fs_args32.mfs_args.base); 836 fs_args.mfs_args.size = fs_args32.mfs_args.size; 837 } 838 data_seg = UIO_SYSSPACE; 839 data = &fs_args.mfs_args; 840 data_len = sizeof(fs_args.mfs_args); 841 } else if ((strcmp(mtype, MOUNT_UFS) == 0) || 842 (strcmp(mtype, MOUNT_EXT2FS) == 0) || 843 (strcmp(mtype, MOUNT_LFS) == 0)) { 844 if (data_len > sizeof(fs_args32.ufs_args)) 845 return EINVAL; 846 if ((flags & MNT_GETARGS) == 0) { 847 error = copyin(data, &fs_args32.ufs_args, 848 sizeof(fs_args32.ufs_args)); 849 if (error) 850 return error; 851 fs_args.ufs_args.fspec = 852 NETBSD32PTR64(fs_args32.ufs_args.fspec); 853 } 854 data_seg = UIO_SYSSPACE; 855 data = &fs_args.ufs_args; 856 data_len = sizeof(fs_args.ufs_args); 857 } else if (strcmp(mtype, MOUNT_CD9660) == 0) { 858 if (data_len != sizeof(fs_args32.iso_args)) 859 return EINVAL; 860 if ((flags & MNT_GETARGS) == 0) { 861 error = copyin(data, &fs_args32.iso_args, 862 sizeof(fs_args32.iso_args)); 863 if (error) 864 return error; 865 fs_args.iso_args.fspec = 866 NETBSD32PTR64(fs_args32.iso_args.fspec); 867 memset(&fs_args.iso_args._pad1, 0, 868 sizeof(fs_args.iso_args._pad1)); 869 fs_args.iso_args.flags = fs_args32.iso_args.flags; 870 } 871 data_seg = UIO_SYSSPACE; 872 data = &fs_args.iso_args; 873 data_len = sizeof(fs_args.iso_args); 874 } else if (strcmp(mtype, MOUNT_MSDOS) == 0) { 875 if (data_len != sizeof(fs_args32.msdosfs_args)) 876 return EINVAL; 877 if ((flags & MNT_GETARGS) == 0) { 878 error = copyin(data, &fs_args32.msdosfs_args, 879 sizeof(fs_args32.msdosfs_args)); 880 if (error) 881 return error; 882 fs_args.msdosfs_args.fspec = 883 NETBSD32PTR64(fs_args32.msdosfs_args.fspec); 884 memset(&fs_args.msdosfs_args._pad1, 0, 885 sizeof(fs_args.msdosfs_args._pad1)); 886 fs_args.msdosfs_args.uid = 887 fs_args32.msdosfs_args.uid; 888 fs_args.msdosfs_args.gid = 889 fs_args32.msdosfs_args.gid; 890 fs_args.msdosfs_args.mask = 891 fs_args32.msdosfs_args.mask; 892 fs_args.msdosfs_args.flags = 893 fs_args32.msdosfs_args.flags; 894 fs_args.msdosfs_args.version = 895 fs_args32.msdosfs_args.version; 896 fs_args.msdosfs_args.dirmask = 897 fs_args32.msdosfs_args.dirmask; 898 fs_args.msdosfs_args.gmtoff = 899 fs_args32.msdosfs_args.gmtoff; 900 } 901 data_seg = UIO_SYSSPACE; 902 data = &fs_args.msdosfs_args; 903 data_len = sizeof(fs_args.msdosfs_args); 904 } else if (strcmp(mtype, MOUNT_NFS) == 0) { 905 if (data_len != sizeof(fs_args32.nfs_args)) 906 return EINVAL; 907 if ((flags & MNT_GETARGS) == 0) { 908 error = copyin(data, &fs_args32.nfs_args, 909 sizeof(fs_args32.nfs_args)); 910 if (error) 911 return error; 912 fs_args.nfs_args.version = fs_args32.nfs_args.version; 913 fs_args.nfs_args.addr = 914 NETBSD32PTR64(fs_args32.nfs_args.addr); 915 memcpy(&fs_args.nfs_args.addrlen, 916 &fs_args32.nfs_args.addrlen, 917 offsetof(struct nfs_args, fh) 918 - offsetof(struct nfs_args, addrlen)); 919 fs_args.nfs_args.fh = 920 NETBSD32PTR64(fs_args32.nfs_args.fh); 921 memcpy(&fs_args.nfs_args.fhsize, 922 &fs_args32.nfs_args.fhsize, 923 offsetof(struct nfs_args, hostname) 924 - offsetof(struct nfs_args, fhsize)); 925 fs_args.nfs_args.hostname = 926 NETBSD32PTR64(fs_args32.nfs_args.hostname); 927 } 928 data_seg = UIO_SYSSPACE; 929 data = &fs_args.nfs_args; 930 data_len = sizeof(fs_args.nfs_args); 931 } else { 932 data_seg = UIO_USERSPACE; 933 } 934 error = do_sys_mount(l, NULL, type, path, flags, data, data_seg, 935 data_len, retval); 936 if (error) 937 return error; 938 if (flags & MNT_GETARGS) { 939 data_len = *retval; 940 if (strcmp(mtype, MOUNT_MFS) == 0) { 941 if (data_len != sizeof(fs_args.mfs_args)) 942 return EINVAL; 943 NETBSD32PTR32(fs_args32.mfs_args.fspec, 944 fs_args.mfs_args.fspec); 945 memset(&fs_args32.mfs_args._pad1, 0, 946 sizeof(fs_args32.mfs_args._pad1)); 947 NETBSD32PTR32(fs_args32.mfs_args.base, 948 fs_args.mfs_args.base); 949 fs_args32.mfs_args.size = fs_args.mfs_args.size; 950 error = copyout(&fs_args32.mfs_args, data, 951 sizeof(fs_args32.mfs_args)); 952 } else if (strcmp(mtype, MOUNT_UFS) == 0) { 953 if (data_len != sizeof(fs_args.ufs_args)) 954 return EINVAL; 955 NETBSD32PTR32(fs_args32.ufs_args.fspec, 956 fs_args.ufs_args.fspec); 957 error = copyout(&fs_args32.ufs_args, data, 958 sizeof(fs_args32.ufs_args)); 959 } else if (strcmp(mtype, MOUNT_CD9660) == 0) { 960 if (data_len != sizeof(fs_args.iso_args)) 961 return EINVAL; 962 NETBSD32PTR32(fs_args32.iso_args.fspec, 963 fs_args.iso_args.fspec); 964 memset(&fs_args32.iso_args._pad1, 0, 965 sizeof(fs_args32.iso_args._pad1)); 966 fs_args32.iso_args.flags = fs_args.iso_args.flags; 967 error = copyout(&fs_args32.iso_args, data, 968 sizeof(fs_args32.iso_args)); 969 } else if (strcmp(mtype, MOUNT_NFS) == 0) { 970 if (data_len != sizeof(fs_args.nfs_args)) 971 return EINVAL; 972 error = copyin(data, &fs_args32.nfs_args, 973 sizeof(fs_args32.nfs_args)); 974 if (error) 975 return error; 976 fs_args.nfs_args.version = fs_args32.nfs_args.version; 977 NETBSD32PTR32(fs_args32.nfs_args.addr, 978 fs_args.nfs_args.addr); 979 memcpy(&fs_args32.nfs_args.addrlen, 980 &fs_args.nfs_args.addrlen, 981 offsetof(struct nfs_args, fh) 982 - offsetof(struct nfs_args, addrlen)); 983 NETBSD32PTR32(fs_args32.nfs_args.fh, 984 fs_args.nfs_args.fh); 985 memcpy(&fs_args32.nfs_args.fhsize, 986 &fs_args.nfs_args.fhsize, 987 offsetof(struct nfs_args, hostname) 988 - offsetof(struct nfs_args, fhsize)); 989 NETBSD32PTR32(fs_args32.nfs_args.hostname, 990 fs_args.nfs_args.hostname); 991 error = copyout(&fs_args32.nfs_args, data, 992 sizeof(fs_args32.nfs_args)); 993 } 994 } 995 return error; 996 } 997 998 int 999 netbsd32_linkat(struct lwp *l, const struct netbsd32_linkat_args *uap, 1000 register_t *retval) 1001 { 1002 /* { 1003 syscallarg(int) fd1; 1004 syscallarg(const netbsd32_charp) name1; 1005 syscallarg(int) fd2; 1006 syscallarg(const netbsd32_charp) name2; 1007 syscallarg(int) flags; 1008 } */ 1009 struct sys_linkat_args ua; 1010 1011 NETBSD32TO64_UAP(fd1); 1012 NETBSD32TOP_UAP(name1, const char); 1013 NETBSD32TO64_UAP(fd2); 1014 NETBSD32TOP_UAP(name2, const char); 1015 NETBSD32TO64_UAP(flags); 1016 1017 return sys_linkat(l, &ua, retval); 1018 } 1019 1020 int 1021 netbsd32_renameat(struct lwp *l, const struct netbsd32_renameat_args *uap, 1022 register_t *retval) 1023 { 1024 /* { 1025 syscallarg(int) fromfd; 1026 syscallarg(const netbsd32_charp) from; 1027 syscallarg(int) tofd; 1028 syscallarg(const netbsd32_charp) to; 1029 } */ 1030 struct sys_renameat_args ua; 1031 1032 NETBSD32TO64_UAP(fromfd); 1033 NETBSD32TOP_UAP(from, const char); 1034 NETBSD32TO64_UAP(tofd); 1035 NETBSD32TOP_UAP(to, const char); 1036 1037 return sys_renameat(l, &ua, retval); 1038 } 1039 1040 int 1041 netbsd32_mkfifoat(struct lwp *l, const struct netbsd32_mkfifoat_args *uap, 1042 register_t *retval) 1043 { 1044 /* { 1045 syscallarg(int) fd; 1046 syscallarg(const netbsd32_charp) path; 1047 syscallarg(mode_t) mode; 1048 } */ 1049 struct sys_mkfifoat_args ua; 1050 1051 NETBSD32TO64_UAP(fd); 1052 NETBSD32TOP_UAP(path, const char); 1053 NETBSD32TO64_UAP(mode); 1054 1055 return sys_mkfifoat(l, &ua, retval); 1056 } 1057 1058 int 1059 netbsd32_mknodat(struct lwp *l, const struct netbsd32_mknodat_args *uap, 1060 register_t *retval) 1061 { 1062 /* { 1063 syscallarg(int) fd; 1064 syscallarg(netbsd32_charp) path; 1065 syscallarg(mode_t) mode; 1066 syscallarg(uint32_t) dev; 1067 } */ 1068 struct sys_mknodat_args ua; 1069 1070 NETBSD32TO64_UAP(fd); 1071 NETBSD32TOP_UAP(path, const char); 1072 NETBSD32TO64_UAP(mode); 1073 NETBSD32TO64_UAP(dev); 1074 1075 return sys_mknodat(l, &ua, retval); 1076 } 1077 1078 int 1079 netbsd32_mkdirat(struct lwp *l, const struct netbsd32_mkdirat_args *uap, 1080 register_t *retval) 1081 { 1082 /* { 1083 syscallarg(int) fd; 1084 syscallarg(netbsd32_charp) path; 1085 syscallarg(mode_t) mode; 1086 } */ 1087 struct sys_mkdirat_args ua; 1088 1089 NETBSD32TO64_UAP(fd); 1090 NETBSD32TOP_UAP(path, const char); 1091 NETBSD32TO64_UAP(mode); 1092 1093 return sys_mkdirat(l, &ua, retval); 1094 } 1095 1096 int 1097 netbsd32_faccessat(struct lwp *l, const struct netbsd32_faccessat_args *uap, 1098 register_t *retval) 1099 { 1100 /* { 1101 syscallarg(int) fd; 1102 syscallarg(netbsd32_charp) path; 1103 syscallarg(int) amode; 1104 syscallarg(int) flag; 1105 } */ 1106 struct sys_faccessat_args ua; 1107 1108 NETBSD32TO64_UAP(fd); 1109 NETBSD32TOP_UAP(path, const char); 1110 NETBSD32TO64_UAP(amode); 1111 NETBSD32TO64_UAP(flag); 1112 1113 return sys_faccessat(l, &ua, retval); 1114 } 1115 1116 int 1117 netbsd32_fchmodat(struct lwp *l, const struct netbsd32_fchmodat_args *uap, 1118 register_t *retval) 1119 { 1120 /* { 1121 syscallarg(int) fd; 1122 syscallarg(netbsd32_charp) path; 1123 syscallarg(mode_t) mode; 1124 syscallarg(int) flag; 1125 } */ 1126 struct sys_fchmodat_args ua; 1127 1128 NETBSD32TO64_UAP(fd); 1129 NETBSD32TOP_UAP(path, const char); 1130 NETBSD32TO64_UAP(mode); 1131 NETBSD32TO64_UAP(flag); 1132 1133 return sys_fchmodat(l, &ua, retval); 1134 } 1135 1136 int 1137 netbsd32_fchownat(struct lwp *l, const struct netbsd32_fchownat_args *uap, 1138 register_t *retval) 1139 { 1140 /* { 1141 syscallarg(int) fd; 1142 syscallarg(netbsd32_charp) path; 1143 syscallarg(uid_t) owner; 1144 syscallarg(gid_t) group; 1145 syscallarg(int) flag; 1146 } */ 1147 struct sys_fchownat_args ua; 1148 1149 NETBSD32TO64_UAP(fd); 1150 NETBSD32TOP_UAP(path, const char); 1151 NETBSD32TO64_UAP(owner); 1152 NETBSD32TO64_UAP(group); 1153 NETBSD32TO64_UAP(flag); 1154 1155 return sys_fchownat(l, &ua, retval); 1156 } 1157 1158 int 1159 netbsd32_fstatat(struct lwp *l, const struct netbsd32_fstatat_args *uap, 1160 register_t *retval) 1161 { 1162 /* { 1163 syscallarg(int) fd; 1164 syscallarg(netbsd32_charp) path; 1165 syscallarg(netbsd32_statp_t) buf; 1166 syscallarg(int) flag; 1167 } */ 1168 struct netbsd32_stat sb32; 1169 struct stat sb; 1170 int follow; 1171 int error; 1172 1173 follow = (SCARG(uap, flag) & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW; 1174 1175 error = do_sys_statat(l, SCARG(uap, fd), SCARG_P32(uap, path), 1176 follow, &sb); 1177 if (error) 1178 return error; 1179 netbsd32_from_stat(&sb, &sb32); 1180 return copyout(&sb32, SCARG_P32(uap, buf), sizeof(sb32)); 1181 } 1182 1183 int 1184 netbsd32_utimensat(struct lwp *l, const struct netbsd32_utimensat_args *uap, 1185 register_t *retval) 1186 { 1187 /* { 1188 syscallarg(int) fd; 1189 syscallarg(netbsd32_charp) path; 1190 syscallarg(netbsd32_timespecp_t) tptr; 1191 syscallarg(int) flag; 1192 } */ 1193 struct timespec ts[2], *tsp; 1194 int follow; 1195 int error; 1196 1197 error = get_utimens32(SCARG_P32(uap, tptr), ts, &tsp); 1198 if (error != 0) 1199 return error; 1200 1201 follow = (SCARG(uap, flag) & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW; 1202 1203 return do_sys_utimensat(l, SCARG(uap, fd), NULL, 1204 SCARG_P32(uap, path), follow, tsp, UIO_SYSSPACE); 1205 } 1206 1207 int 1208 netbsd32_openat(struct lwp *l, const struct netbsd32_openat_args *uap, 1209 register_t *retval) 1210 { 1211 /* { 1212 syscallarg(int) fd; 1213 syscallarg(netbsd32_charp) path; 1214 syscallarg(int) oflags; 1215 syscallarg(mode_t) mode; 1216 } */ 1217 struct sys_openat_args ua; 1218 1219 NETBSD32TO64_UAP(fd); 1220 NETBSD32TOP_UAP(path, const char); 1221 NETBSD32TO64_UAP(oflags); 1222 NETBSD32TO64_UAP(mode); 1223 1224 return sys_openat(l, &ua, retval); 1225 } 1226 1227 int 1228 netbsd32_readlinkat(struct lwp *l, const struct netbsd32_readlinkat_args *uap, 1229 register_t *retval) 1230 { 1231 /* { 1232 syscallarg(int) fd; 1233 syscallarg(netbsd32_charp) path; 1234 syscallarg(netbsd32_charp) buf; 1235 syscallarg(netbsd32_size_t) bufsize; 1236 } */ 1237 struct sys_readlinkat_args ua; 1238 1239 NETBSD32TO64_UAP(fd); 1240 NETBSD32TOP_UAP(path, const char *); 1241 NETBSD32TOP_UAP(buf, char *); 1242 NETBSD32TOX_UAP(bufsize, size_t); 1243 1244 return sys_readlinkat(l, &ua, retval); 1245 } 1246 1247 int 1248 netbsd32_symlinkat(struct lwp *l, const struct netbsd32_symlinkat_args *uap, 1249 register_t *retval) 1250 { 1251 /* { 1252 syscallarg(netbsd32_charp) path1; 1253 syscallarg(int) fd; 1254 syscallarg(netbsd32_charp) path2; 1255 } */ 1256 struct sys_symlinkat_args ua; 1257 1258 NETBSD32TOP_UAP(path1, const char *); 1259 NETBSD32TO64_UAP(fd); 1260 NETBSD32TOP_UAP(path2, const char *); 1261 1262 return sys_symlinkat(l, &ua, retval); 1263 } 1264 1265 int 1266 netbsd32_unlinkat(struct lwp *l, const struct netbsd32_unlinkat_args *uap, 1267 register_t *retval) 1268 { 1269 /* { 1270 syscallarg(int) fd; 1271 syscallarg(netbsd32_charp) path; 1272 syscallarg(int) flag; 1273 } */ 1274 struct sys_unlinkat_args ua; 1275 1276 NETBSD32TO64_UAP(fd); 1277 NETBSD32TOP_UAP(path, const char *); 1278 NETBSD32TO64_UAP(flag); 1279 1280 return sys_unlinkat(l, &ua, retval); 1281 } 1282 1283 int 1284 netbsd32_futimens(struct lwp *l, const struct netbsd32_futimens_args *uap, 1285 register_t *retval) 1286 { 1287 /* { 1288 syscallarg(int) fd; 1289 syscallarg(netbsd32_timespecp_t) tptr; 1290 } */ 1291 struct timespec ts[2], *tsp; 1292 file_t *fp; 1293 int error; 1294 1295 error = get_utimens32(SCARG_P32(uap, tptr), ts, &tsp); 1296 if (error != 0) 1297 return error; 1298 1299 /* fd_getvnode() will use the descriptor for us */ 1300 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 1301 return (error); 1302 error = do_sys_utimensat(l, AT_FDCWD, fp->f_data, NULL, 0, 1303 tsp, UIO_SYSSPACE); 1304 fd_putfile(SCARG(uap, fd)); 1305 return (error); 1306 } 1307