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