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