1 /* $NetBSD: netbsd32_fs.c,v 1.64 2012/12/13 15:16:57 matt 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.64 2012/12/13 15:16:57 matt 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 routine 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 int 347 netbsd32___utimes50(struct lwp *l, const struct netbsd32___utimes50_args *uap, register_t *retval) 348 { 349 /* { 350 syscallarg(const netbsd32_charp) path; 351 syscallarg(const netbsd32_timevalp_t) tptr; 352 } */ 353 int error; 354 struct timeval tv[2], *tvp; 355 356 error = get_utimes32(SCARG_P32(uap, tptr), tv, &tvp); 357 if (error != 0) 358 return error; 359 360 return do_sys_utimes(l, NULL, SCARG_P32(uap, path), FOLLOW, 361 tvp, UIO_SYSSPACE); 362 } 363 364 static int 365 netbds32_copyout_statvfs(const void *kp, void *up, size_t len) 366 { 367 struct netbsd32_statvfs *sbuf_32; 368 int error; 369 370 sbuf_32 = kmem_alloc(sizeof(*sbuf_32), KM_SLEEP); 371 netbsd32_from_statvfs(kp, sbuf_32); 372 error = copyout(sbuf_32, up, sizeof(*sbuf_32)); 373 kmem_free(sbuf_32, sizeof(*sbuf_32)); 374 375 return error; 376 } 377 378 int 379 netbsd32_statvfs1(struct lwp *l, const struct netbsd32_statvfs1_args *uap, register_t *retval) 380 { 381 /* { 382 syscallarg(const netbsd32_charp) path; 383 syscallarg(netbsd32_statvfsp_t) buf; 384 syscallarg(int) flags; 385 } */ 386 struct statvfs *sb; 387 int error; 388 389 sb = STATVFSBUF_GET(); 390 error = do_sys_pstatvfs(l, SCARG_P32(uap, path), SCARG(uap, flags), sb); 391 if (error == 0) 392 error = netbds32_copyout_statvfs(sb, SCARG_P32(uap, buf), 0); 393 STATVFSBUF_PUT(sb); 394 return error; 395 } 396 397 int 398 netbsd32_fstatvfs1(struct lwp *l, const struct netbsd32_fstatvfs1_args *uap, register_t *retval) 399 { 400 /* { 401 syscallarg(int) fd; 402 syscallarg(netbsd32_statvfsp_t) buf; 403 syscallarg(int) flags; 404 } */ 405 struct statvfs *sb; 406 int error; 407 408 sb = STATVFSBUF_GET(); 409 error = do_sys_fstatvfs(l, SCARG(uap, fd), SCARG(uap, flags), sb); 410 if (error == 0) 411 error = netbds32_copyout_statvfs(sb, SCARG_P32(uap, buf), 0); 412 STATVFSBUF_PUT(sb); 413 return error; 414 } 415 416 int 417 netbsd32_getvfsstat(struct lwp *l, const struct netbsd32_getvfsstat_args *uap, register_t *retval) 418 { 419 /* { 420 syscallarg(netbsd32_statvfsp_t) buf; 421 syscallarg(netbsd32_size_t) bufsize; 422 syscallarg(int) flags; 423 } */ 424 425 return do_sys_getvfsstat(l, SCARG_P32(uap, buf), SCARG(uap, bufsize), 426 SCARG(uap, flags), netbds32_copyout_statvfs, 427 sizeof (struct netbsd32_statvfs), retval); 428 } 429 430 int 431 netbsd32___fhstatvfs140(struct lwp *l, const struct netbsd32___fhstatvfs140_args *uap, register_t *retval) 432 { 433 /* { 434 syscallarg(const netbsd32_pointer_t) fhp; 435 syscallarg(netbsd32_size_t) fh_size; 436 syscallarg(netbsd32_statvfsp_t) buf; 437 syscallarg(int) flags; 438 } */ 439 struct statvfs *sb; 440 int error; 441 442 sb = STATVFSBUF_GET(); 443 error = do_fhstatvfs(l, SCARG_P32(uap, fhp), SCARG(uap, fh_size), sb, 444 SCARG(uap, flags)); 445 446 if (error == 0) 447 error = netbds32_copyout_statvfs(sb, SCARG_P32(uap, buf), 0); 448 STATVFSBUF_PUT(sb); 449 450 return error; 451 } 452 453 int 454 netbsd32___futimes50(struct lwp *l, const struct netbsd32___futimes50_args *uap, register_t *retval) 455 { 456 /* { 457 syscallarg(int) fd; 458 syscallarg(const netbsd32_timevalp_t) tptr; 459 } */ 460 int error; 461 file_t *fp; 462 struct timeval tv[2], *tvp; 463 464 error = get_utimes32(SCARG_P32(uap, tptr), tv, &tvp); 465 if (error != 0) 466 return error; 467 468 /* fd_getvnode() will use the descriptor for us */ 469 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 470 return (error); 471 472 error = do_sys_utimes(l, fp->f_data, NULL, 0, tvp, UIO_SYSSPACE); 473 474 fd_putfile(SCARG(uap, fd)); 475 return (error); 476 } 477 478 int 479 netbsd32___getdents30(struct lwp *l, 480 const struct netbsd32___getdents30_args *uap, register_t *retval) 481 { 482 /* { 483 syscallarg(int) fd; 484 syscallarg(netbsd32_charp) buf; 485 syscallarg(netbsd32_size_t) count; 486 } */ 487 file_t *fp; 488 int error, done; 489 490 /* fd_getvnode() will use the descriptor for us */ 491 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 492 return (error); 493 if ((fp->f_flag & FREAD) == 0) { 494 error = EBADF; 495 goto out; 496 } 497 error = vn_readdir(fp, SCARG_P32(uap, buf), 498 UIO_USERSPACE, SCARG(uap, count), &done, l, 0, 0); 499 *retval = done; 500 out: 501 fd_putfile(SCARG(uap, fd)); 502 return (error); 503 } 504 505 int 506 netbsd32___lutimes50(struct lwp *l, 507 const struct netbsd32___lutimes50_args *uap, register_t *retval) 508 { 509 /* { 510 syscallarg(const netbsd32_charp) path; 511 syscallarg(const netbsd32_timevalp_t) tptr; 512 } */ 513 int error; 514 struct timeval tv[2], *tvp; 515 516 error = get_utimes32(SCARG_P32(uap, tptr), tv, &tvp); 517 if (error != 0) 518 return error; 519 520 return do_sys_utimes(l, NULL, SCARG_P32(uap, path), NOFOLLOW, 521 tvp, UIO_SYSSPACE); 522 } 523 524 int 525 netbsd32___stat50(struct lwp *l, const struct netbsd32___stat50_args *uap, register_t *retval) 526 { 527 /* { 528 syscallarg(const netbsd32_charp) path; 529 syscallarg(netbsd32_statp_t) ub; 530 } */ 531 struct netbsd32_stat sb32; 532 struct stat sb; 533 int error; 534 const char *path; 535 536 path = SCARG_P32(uap, path); 537 538 error = do_sys_stat(path, FOLLOW, &sb); 539 if (error) 540 return (error); 541 netbsd32_from_stat(&sb, &sb32); 542 error = copyout(&sb32, SCARG_P32(uap, ub), sizeof(sb32)); 543 return (error); 544 } 545 546 int 547 netbsd32___fstat50(struct lwp *l, const struct netbsd32___fstat50_args *uap, register_t *retval) 548 { 549 /* { 550 syscallarg(int) fd; 551 syscallarg(netbsd32_statp_t) sb; 552 } */ 553 struct netbsd32_stat sb32; 554 struct stat ub; 555 int error; 556 557 error = do_sys_fstat(SCARG(uap, fd), &ub); 558 if (error == 0) { 559 netbsd32_from_stat(&ub, &sb32); 560 error = copyout(&sb32, SCARG_P32(uap, sb), sizeof(sb32)); 561 } 562 return (error); 563 } 564 565 int 566 netbsd32___lstat50(struct lwp *l, const struct netbsd32___lstat50_args *uap, register_t *retval) 567 { 568 /* { 569 syscallarg(const netbsd32_charp) path; 570 syscallarg(netbsd32_statp_t) ub; 571 } */ 572 struct netbsd32_stat sb32; 573 struct stat sb; 574 int error; 575 const char *path; 576 577 path = SCARG_P32(uap, path); 578 579 error = do_sys_stat(path, NOFOLLOW, &sb); 580 if (error) 581 return (error); 582 netbsd32_from_stat(&sb, &sb32); 583 error = copyout(&sb32, SCARG_P32(uap, ub), sizeof(sb32)); 584 return (error); 585 } 586 587 int 588 netbsd32___fhstat50(struct lwp *l, const struct netbsd32___fhstat50_args *uap, register_t *retval) 589 { 590 /* { 591 syscallarg(const netbsd32_pointer_t) fhp; 592 syscallarg(netbsd32_size_t) fh_size; 593 syscallarg(netbsd32_statp_t) sb; 594 } */ 595 struct stat sb; 596 struct netbsd32_stat sb32; 597 int error; 598 599 error = do_fhstat(l, SCARG_P32(uap, fhp), SCARG(uap, fh_size), &sb); 600 if (error == 0) { 601 netbsd32_from_stat(&sb, &sb32); 602 error = copyout(&sb32, SCARG_P32(uap, sb), sizeof(sb)); 603 } 604 return error; 605 } 606 607 int 608 netbsd32_preadv(struct lwp *l, const struct netbsd32_preadv_args *uap, register_t *retval) 609 { 610 /* { 611 syscallarg(int) fd; 612 syscallarg(const netbsd32_iovecp_t) iovp; 613 syscallarg(int) iovcnt; 614 syscallarg(int) pad; 615 syscallarg(off_t) offset; 616 } */ 617 file_t *fp; 618 struct vnode *vp; 619 off_t offset; 620 int error, fd = SCARG(uap, fd); 621 622 if ((fp = fd_getfile(fd)) == NULL) 623 return (EBADF); 624 625 if ((fp->f_flag & FREAD) == 0) { 626 fd_putfile(fd); 627 return (EBADF); 628 } 629 630 vp = fp->f_data; 631 if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) { 632 error = ESPIPE; 633 goto out; 634 } 635 636 offset = SCARG(uap, offset); 637 638 /* 639 * XXX This works because no file systems actually 640 * XXX take any action on the seek operation. 641 */ 642 if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0) 643 goto out; 644 645 return (dofilereadv32(fd, fp, SCARG_P32(uap, iovp), 646 SCARG(uap, iovcnt), &offset, 0, retval)); 647 648 out: 649 fd_putfile(fd); 650 return (error); 651 } 652 653 int 654 netbsd32_pwritev(struct lwp *l, const struct netbsd32_pwritev_args *uap, register_t *retval) 655 { 656 /* { 657 syscallarg(int) fd; 658 syscallarg(const netbsd32_iovecp_t) iovp; 659 syscallarg(int) iovcnt; 660 syscallarg(int) pad; 661 syscallarg(off_t) offset; 662 } */ 663 file_t *fp; 664 struct vnode *vp; 665 off_t offset; 666 int error, fd = SCARG(uap, fd); 667 668 if ((fp = fd_getfile(fd)) == NULL) 669 return (EBADF); 670 671 if ((fp->f_flag & FWRITE) == 0) { 672 fd_putfile(fd); 673 return (EBADF); 674 } 675 676 vp = fp->f_data; 677 if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) { 678 error = ESPIPE; 679 goto out; 680 } 681 682 offset = SCARG(uap, offset); 683 684 /* 685 * XXX This works because no file systems actually 686 * XXX take any action on the seek operation. 687 */ 688 if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0) 689 goto out; 690 691 return (dofilewritev32(fd, fp, SCARG_P32(uap, iovp), 692 SCARG(uap, iovcnt), &offset, 0, retval)); 693 694 out: 695 fd_putfile(fd); 696 return (error); 697 } 698 699 /* 700 * Find pathname of process's current directory. 701 * 702 * Use vfs vnode-to-name reverse cache; if that fails, fall back 703 * to reading directory contents. 704 */ 705 /* XXX NH Why does this exist */ 706 int 707 getcwd_common(struct vnode *, struct vnode *, 708 char **, char *, int, int, struct lwp *); 709 710 int 711 netbsd32___getcwd(struct lwp *l, const struct netbsd32___getcwd_args *uap, register_t *retval) 712 { 713 /* { 714 syscallarg(char *) bufp; 715 syscallarg(size_t) length; 716 } */ 717 struct proc *p = l->l_proc; 718 int error; 719 char *path; 720 char *bp, *bend; 721 int len = (int)SCARG(uap, length); 722 int lenused; 723 struct cwdinfo *cwdi; 724 725 if (len > MAXPATHLEN*4) 726 len = MAXPATHLEN*4; 727 else if (len < 2) 728 return ERANGE; 729 730 path = kmem_alloc(len, KM_SLEEP); 731 if (!path) 732 return ENOMEM; 733 734 bp = &path[len]; 735 bend = bp; 736 *(--bp) = '\0'; 737 738 /* 739 * 5th argument here is "max number of vnodes to traverse". 740 * Since each entry takes up at least 2 bytes in the output buffer, 741 * limit it to N/2 vnodes for an N byte buffer. 742 */ 743 #define GETCWD_CHECK_ACCESS 0x0001 744 cwdi = p->p_cwdi; 745 rw_enter(&cwdi->cwdi_lock, RW_READER); 746 error = getcwd_common (cwdi->cwdi_cdir, NULL, &bp, path, len/2, 747 GETCWD_CHECK_ACCESS, l); 748 rw_exit(&cwdi->cwdi_lock); 749 750 if (error) 751 goto out; 752 lenused = bend - bp; 753 *retval = lenused; 754 /* put the result into user buffer */ 755 error = copyout(bp, SCARG_P32(uap, bufp), lenused); 756 757 out: 758 kmem_free(path, len); 759 return error; 760 } 761 762 int 763 netbsd32___mount50(struct lwp *l, const struct netbsd32___mount50_args *uap, 764 register_t *retval) 765 { 766 /* { 767 syscallarg(netbsd32_charp) type; 768 syscallarg(netbsd32_charp) path; 769 syscallarg(int) flags; 770 syscallarg(netbsd32_voidp) data; 771 syscallarg(netbsd32_size_t) data_len; 772 } */ 773 char mtype[MNAMELEN]; 774 union { 775 struct netbsd32_ufs_args ufs_args; 776 struct netbsd32_mfs_args mfs_args; 777 struct netbsd32_iso_args iso_args; 778 struct netbsd32_nfs_args nfs_args; 779 struct netbsd32_msdosfs_args msdosfs_args; 780 } fs_args32; 781 union { 782 struct ufs_args ufs_args; 783 struct mfs_args mfs_args; 784 struct iso_args iso_args; 785 struct nfs_args nfs_args; 786 struct msdosfs_args msdosfs_args; 787 } fs_args; 788 const char *type = SCARG_P32(uap, type); 789 const char *path = SCARG_P32(uap, path); 790 int flags = SCARG(uap, flags); 791 void *data = SCARG_P32(uap, data); 792 size_t data_len = SCARG(uap, data_len); 793 enum uio_seg data_seg; 794 size_t len; 795 int error; 796 797 error = copyinstr(type, mtype, sizeof(mtype), &len); 798 if (error) 799 return error; 800 if (strcmp(mtype, MOUNT_MFS) == 0) { 801 if (data_len != sizeof(fs_args32.mfs_args)) 802 return EINVAL; 803 if ((flags & MNT_GETARGS) == 0) { 804 error = copyin(data, &fs_args32.mfs_args, 805 sizeof(fs_args32.mfs_args)); 806 if (error) 807 return error; 808 fs_args.mfs_args.fspec = 809 NETBSD32PTR64(fs_args32.mfs_args.fspec); 810 memset(&fs_args.mfs_args._pad1, 0, 811 sizeof(fs_args.mfs_args._pad1)); 812 fs_args.mfs_args.base = 813 NETBSD32PTR64(fs_args32.mfs_args.base); 814 fs_args.mfs_args.size = fs_args32.mfs_args.size; 815 } 816 data_seg = UIO_SYSSPACE; 817 data = &fs_args.mfs_args; 818 data_len = sizeof(fs_args.mfs_args); 819 } else if ((strcmp(mtype, MOUNT_UFS) == 0) || 820 (strcmp(mtype, MOUNT_EXT2FS) == 0) || 821 (strcmp(mtype, MOUNT_LFS) == 0)) { 822 if (data_len > sizeof(fs_args32.ufs_args)) 823 return EINVAL; 824 if ((flags & MNT_GETARGS) == 0) { 825 error = copyin(data, &fs_args32.ufs_args, 826 sizeof(fs_args32.ufs_args)); 827 if (error) 828 return error; 829 fs_args.ufs_args.fspec = 830 NETBSD32PTR64(fs_args32.ufs_args.fspec); 831 } 832 data_seg = UIO_SYSSPACE; 833 data = &fs_args.ufs_args; 834 data_len = sizeof(fs_args.ufs_args); 835 } else if (strcmp(mtype, MOUNT_CD9660) == 0) { 836 if (data_len != sizeof(fs_args32.iso_args)) 837 return EINVAL; 838 if ((flags & MNT_GETARGS) == 0) { 839 error = copyin(data, &fs_args32.iso_args, 840 sizeof(fs_args32.iso_args)); 841 if (error) 842 return error; 843 fs_args.iso_args.fspec = 844 NETBSD32PTR64(fs_args32.iso_args.fspec); 845 memset(&fs_args.iso_args._pad1, 0, 846 sizeof(fs_args.iso_args._pad1)); 847 fs_args.iso_args.flags = fs_args32.iso_args.flags; 848 } 849 data_seg = UIO_SYSSPACE; 850 data = &fs_args.iso_args; 851 data_len = sizeof(fs_args.iso_args); 852 } else if (strcmp(mtype, MOUNT_MSDOS) == 0) { 853 if (data_len != sizeof(fs_args32.msdosfs_args)) 854 return EINVAL; 855 if ((flags & MNT_GETARGS) == 0) { 856 error = copyin(data, &fs_args32.msdosfs_args, 857 sizeof(fs_args32.msdosfs_args)); 858 if (error) 859 return error; 860 fs_args.msdosfs_args.fspec = 861 NETBSD32PTR64(fs_args32.msdosfs_args.fspec); 862 memset(&fs_args.msdosfs_args._pad1, 0, 863 sizeof(fs_args.msdosfs_args._pad1)); 864 fs_args.msdosfs_args.uid = 865 fs_args32.msdosfs_args.uid; 866 fs_args.msdosfs_args.gid = 867 fs_args32.msdosfs_args.gid; 868 fs_args.msdosfs_args.mask = 869 fs_args32.msdosfs_args.mask; 870 fs_args.msdosfs_args.flags = 871 fs_args32.msdosfs_args.flags; 872 fs_args.msdosfs_args.version = 873 fs_args32.msdosfs_args.version; 874 fs_args.msdosfs_args.dirmask = 875 fs_args32.msdosfs_args.dirmask; 876 fs_args.msdosfs_args.gmtoff = 877 fs_args32.msdosfs_args.gmtoff; 878 } 879 data_seg = UIO_SYSSPACE; 880 data = &fs_args.msdosfs_args; 881 data_len = sizeof(fs_args.msdosfs_args); 882 } else if (strcmp(mtype, MOUNT_NFS) == 0) { 883 if (data_len != sizeof(fs_args32.nfs_args)) 884 return EINVAL; 885 if ((flags & MNT_GETARGS) == 0) { 886 error = copyin(data, &fs_args32.nfs_args, 887 sizeof(fs_args32.nfs_args)); 888 if (error) 889 return error; 890 fs_args.nfs_args.version = fs_args32.nfs_args.version; 891 fs_args.nfs_args.addr = 892 NETBSD32PTR64(fs_args32.nfs_args.addr); 893 memcpy(&fs_args.nfs_args.addrlen, 894 &fs_args32.nfs_args.addrlen, 895 offsetof(struct nfs_args, fh) 896 - offsetof(struct nfs_args, addrlen)); 897 fs_args.nfs_args.fh = 898 NETBSD32PTR64(fs_args32.nfs_args.fh); 899 memcpy(&fs_args.nfs_args.fhsize, 900 &fs_args32.nfs_args.fhsize, 901 offsetof(struct nfs_args, hostname) 902 - offsetof(struct nfs_args, fhsize)); 903 fs_args.nfs_args.hostname = 904 NETBSD32PTR64(fs_args32.nfs_args.hostname); 905 } 906 data_seg = UIO_SYSSPACE; 907 data = &fs_args.nfs_args; 908 data_len = sizeof(fs_args.nfs_args); 909 } else { 910 data_seg = UIO_USERSPACE; 911 } 912 error = do_sys_mount(l, NULL, type, path, flags, data, data_seg, 913 data_len, retval); 914 if (error) 915 return error; 916 if (flags & MNT_GETARGS) { 917 data_len = *retval; 918 if (strcmp(mtype, MOUNT_MFS) == 0) { 919 if (data_len != sizeof(fs_args.mfs_args)) 920 return EINVAL; 921 NETBSD32PTR32(fs_args32.mfs_args.fspec, 922 fs_args.mfs_args.fspec); 923 memset(&fs_args32.mfs_args._pad1, 0, 924 sizeof(fs_args32.mfs_args._pad1)); 925 NETBSD32PTR32(fs_args32.mfs_args.base, 926 fs_args.mfs_args.base); 927 fs_args32.mfs_args.size = fs_args.mfs_args.size; 928 error = copyout(&fs_args32.mfs_args, data, 929 sizeof(fs_args32.mfs_args)); 930 } else if (strcmp(mtype, MOUNT_UFS) == 0) { 931 if (data_len != sizeof(fs_args.ufs_args)) 932 return EINVAL; 933 NETBSD32PTR32(fs_args32.ufs_args.fspec, 934 fs_args.ufs_args.fspec); 935 error = copyout(&fs_args32.ufs_args, data, 936 sizeof(fs_args32.ufs_args)); 937 } else if (strcmp(mtype, MOUNT_CD9660) == 0) { 938 if (data_len != sizeof(fs_args.iso_args)) 939 return EINVAL; 940 NETBSD32PTR32(fs_args32.iso_args.fspec, 941 fs_args.iso_args.fspec); 942 memset(&fs_args32.iso_args._pad1, 0, 943 sizeof(fs_args32.iso_args._pad1)); 944 fs_args32.iso_args.flags = fs_args.iso_args.flags; 945 error = copyout(&fs_args32.iso_args, data, 946 sizeof(fs_args32.iso_args)); 947 } else if (strcmp(mtype, MOUNT_NFS) == 0) { 948 if (data_len != sizeof(fs_args.nfs_args)) 949 return EINVAL; 950 error = copyin(data, &fs_args32.nfs_args, 951 sizeof(fs_args32.nfs_args)); 952 if (error) 953 return error; 954 fs_args.nfs_args.version = fs_args32.nfs_args.version; 955 NETBSD32PTR32(fs_args32.nfs_args.addr, 956 fs_args.nfs_args.addr); 957 memcpy(&fs_args32.nfs_args.addrlen, 958 &fs_args.nfs_args.addrlen, 959 offsetof(struct nfs_args, fh) 960 - offsetof(struct nfs_args, addrlen)); 961 NETBSD32PTR32(fs_args32.nfs_args.fh, 962 fs_args.nfs_args.fh); 963 memcpy(&fs_args32.nfs_args.fhsize, 964 &fs_args.nfs_args.fhsize, 965 offsetof(struct nfs_args, hostname) 966 - offsetof(struct nfs_args, fhsize)); 967 NETBSD32PTR32(fs_args32.nfs_args.hostname, 968 fs_args.nfs_args.hostname); 969 error = copyout(&fs_args32.nfs_args, data, 970 sizeof(fs_args32.nfs_args)); 971 } 972 } 973 return error; 974 } 975