1 /* $NetBSD: netbsd32_fs.c,v 1.87 2020/02/23 22:14:03 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.87 2020/02/23 22:14:03 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 int error; 744 char *path; 745 char *bp, *bend; 746 int len = (int)SCARG(uap, length); 747 int lenused; 748 struct vnode *dvp; 749 750 if (len > MAXPATHLEN*4) 751 len = MAXPATHLEN*4; 752 else if (len < 2) 753 return ERANGE; 754 755 path = kmem_alloc(len, KM_SLEEP); 756 bp = &path[len]; 757 bend = bp; 758 *(--bp) = '\0'; 759 760 /* 761 * 5th argument here is "max number of vnodes to traverse". 762 * Since each entry takes up at least 2 bytes in the output buffer, 763 * limit it to N/2 vnodes for an N byte buffer. 764 */ 765 #define GETCWD_CHECK_ACCESS 0x0001 766 dvp = cwdcdir(); 767 error = getcwd_common (dvp, NULL, &bp, path, len/2, 768 GETCWD_CHECK_ACCESS, l); 769 vrele(dvp); 770 771 if (error) 772 goto out; 773 lenused = bend - bp; 774 *retval = lenused; 775 /* put the result into user buffer */ 776 error = copyout(bp, SCARG_P32(uap, bufp), lenused); 777 778 out: 779 kmem_free(path, len); 780 return error; 781 } 782 783 int 784 netbsd32___mount50(struct lwp *l, const struct netbsd32___mount50_args *uap, 785 register_t *retval) 786 { 787 /* { 788 syscallarg(netbsd32_charp) type; 789 syscallarg(netbsd32_charp) path; 790 syscallarg(int) flags; 791 syscallarg(netbsd32_voidp) data; 792 syscallarg(netbsd32_size_t) data_len; 793 } */ 794 char mtype[MNAMELEN]; 795 union { 796 struct netbsd32_ufs_args ufs_args; 797 struct netbsd32_mfs_args mfs_args; 798 struct netbsd32_iso_args iso_args; 799 struct netbsd32_nfs_args nfs_args; 800 struct netbsd32_msdosfs_args msdosfs_args; 801 struct netbsd32_tmpfs_args tmpfs_args; 802 struct netbsd32_null_args null_args; 803 } fs_args32; 804 union { 805 struct ufs_args ufs_args; 806 struct mfs_args mfs_args; 807 struct iso_args iso_args; 808 struct nfs_args nfs_args; 809 struct msdosfs_args msdosfs_args; 810 struct tmpfs_args tmpfs_args; 811 struct null_args null_args; 812 } fs_args; 813 const char *type = SCARG_P32(uap, type); 814 const char *path = SCARG_P32(uap, path); 815 int flags = SCARG(uap, flags); 816 void *data, *udata; 817 size_t data_len = SCARG(uap, data_len); 818 enum uio_seg data_seg; 819 size_t len; 820 int error; 821 822 udata = data = SCARG_P32(uap, data); 823 memset(&fs_args32, 0, sizeof(fs_args32)); 824 825 error = copyinstr(type, mtype, sizeof(mtype), &len); 826 if (error) 827 return error; 828 829 if (strcmp(mtype, MOUNT_TMPFS) == 0) { 830 if (data_len < sizeof(fs_args32.tmpfs_args)) 831 return EINVAL; 832 if ((flags & MNT_GETARGS) == 0) { 833 error = copyin(data, &fs_args32.tmpfs_args, 834 sizeof(fs_args32.tmpfs_args)); 835 if (error) 836 return error; 837 fs_args.tmpfs_args.ta_version = 838 fs_args32.tmpfs_args.ta_version; 839 fs_args.tmpfs_args.ta_nodes_max = 840 fs_args32.tmpfs_args.ta_nodes_max; 841 fs_args.tmpfs_args.ta_size_max = 842 fs_args32.tmpfs_args.ta_size_max; 843 fs_args.tmpfs_args.ta_root_uid = 844 fs_args32.tmpfs_args.ta_root_uid; 845 fs_args.tmpfs_args.ta_root_gid = 846 fs_args32.tmpfs_args.ta_root_gid; 847 fs_args.tmpfs_args.ta_root_mode = 848 fs_args32.tmpfs_args.ta_root_mode; 849 } 850 data_seg = UIO_SYSSPACE; 851 data = &fs_args.tmpfs_args; 852 data_len = sizeof(fs_args.tmpfs_args); 853 } else if (strcmp(mtype, MOUNT_MFS) == 0) { 854 if (data_len < sizeof(fs_args32.mfs_args)) 855 return EINVAL; 856 if ((flags & MNT_GETARGS) == 0) { 857 error = copyin(data, &fs_args32.mfs_args, 858 sizeof(fs_args32.mfs_args)); 859 if (error) 860 return error; 861 fs_args.mfs_args.fspec = 862 NETBSD32PTR64(fs_args32.mfs_args.fspec); 863 memset(&fs_args.mfs_args._pad1, 0, 864 sizeof(fs_args.mfs_args._pad1)); 865 fs_args.mfs_args.base = 866 NETBSD32PTR64(fs_args32.mfs_args.base); 867 fs_args.mfs_args.size = fs_args32.mfs_args.size; 868 } 869 data_seg = UIO_SYSSPACE; 870 data = &fs_args.mfs_args; 871 data_len = sizeof(fs_args.mfs_args); 872 } else if ((strcmp(mtype, MOUNT_UFS) == 0) || 873 (strcmp(mtype, MOUNT_EXT2FS) == 0) || 874 (strcmp(mtype, MOUNT_LFS) == 0)) { 875 if (data_len < sizeof(fs_args32.ufs_args)) 876 return EINVAL; 877 if ((flags & MNT_GETARGS) == 0) { 878 error = copyin(data, &fs_args32.ufs_args, 879 sizeof(fs_args32.ufs_args)); 880 if (error) 881 return error; 882 fs_args.ufs_args.fspec = 883 NETBSD32PTR64(fs_args32.ufs_args.fspec); 884 } 885 data_seg = UIO_SYSSPACE; 886 data = &fs_args.ufs_args; 887 data_len = sizeof(fs_args.ufs_args); 888 } else if (strcmp(mtype, MOUNT_CD9660) == 0) { 889 if (data_len < sizeof(fs_args32.iso_args)) 890 return EINVAL; 891 if ((flags & MNT_GETARGS) == 0) { 892 error = copyin(data, &fs_args32.iso_args, 893 sizeof(fs_args32.iso_args)); 894 if (error) 895 return error; 896 fs_args.iso_args.fspec = 897 NETBSD32PTR64(fs_args32.iso_args.fspec); 898 memset(&fs_args.iso_args._pad1, 0, 899 sizeof(fs_args.iso_args._pad1)); 900 fs_args.iso_args.flags = fs_args32.iso_args.flags; 901 } 902 data_seg = UIO_SYSSPACE; 903 data = &fs_args.iso_args; 904 data_len = sizeof(fs_args.iso_args); 905 } else if (strcmp(mtype, MOUNT_MSDOS) == 0) { 906 if (data_len < sizeof(fs_args32.msdosfs_args)) 907 return EINVAL; 908 if ((flags & MNT_GETARGS) == 0) { 909 error = copyin(data, &fs_args32.msdosfs_args, 910 sizeof(fs_args32.msdosfs_args)); 911 if (error) 912 return error; 913 fs_args.msdosfs_args.fspec = 914 NETBSD32PTR64(fs_args32.msdosfs_args.fspec); 915 memset(&fs_args.msdosfs_args._pad1, 0, 916 sizeof(fs_args.msdosfs_args._pad1)); 917 fs_args.msdosfs_args.uid = 918 fs_args32.msdosfs_args.uid; 919 fs_args.msdosfs_args.gid = 920 fs_args32.msdosfs_args.gid; 921 fs_args.msdosfs_args.mask = 922 fs_args32.msdosfs_args.mask; 923 fs_args.msdosfs_args.flags = 924 fs_args32.msdosfs_args.flags; 925 fs_args.msdosfs_args.version = 926 fs_args32.msdosfs_args.version; 927 fs_args.msdosfs_args.dirmask = 928 fs_args32.msdosfs_args.dirmask; 929 fs_args.msdosfs_args.gmtoff = 930 fs_args32.msdosfs_args.gmtoff; 931 } 932 data_seg = UIO_SYSSPACE; 933 data = &fs_args.msdosfs_args; 934 data_len = sizeof(fs_args.msdosfs_args); 935 } else if (strcmp(mtype, MOUNT_NFS) == 0) { 936 if (data_len < sizeof(fs_args32.nfs_args)) 937 return EINVAL; 938 /* XXX: NFS requires copyin even with MNT_GETARGS */ 939 if ((flags & MNT_GETARGS) == 0) { 940 error = copyin(data, &fs_args32.nfs_args, 941 sizeof(fs_args32.nfs_args)); 942 if (error) 943 return error; 944 fs_args.nfs_args.version = fs_args32.nfs_args.version; 945 fs_args.nfs_args.addr = 946 NETBSD32PTR64(fs_args32.nfs_args.addr); 947 memcpy(&fs_args.nfs_args.addrlen, 948 &fs_args32.nfs_args.addrlen, 949 offsetof(struct nfs_args, fh) 950 - offsetof(struct nfs_args, addrlen)); 951 fs_args.nfs_args.fh = 952 NETBSD32PTR64(fs_args32.nfs_args.fh); 953 memcpy(&fs_args.nfs_args.fhsize, 954 &fs_args32.nfs_args.fhsize, 955 offsetof(struct nfs_args, hostname) 956 - offsetof(struct nfs_args, fhsize)); 957 fs_args.nfs_args.hostname = 958 NETBSD32PTR64(fs_args32.nfs_args.hostname); 959 } 960 data_seg = UIO_SYSSPACE; 961 data = &fs_args.nfs_args; 962 data_len = sizeof(fs_args.nfs_args); 963 } else if (strcmp(mtype, MOUNT_NULL) == 0) { 964 if (data_len < sizeof(fs_args32.null_args)) 965 return EINVAL; 966 if ((flags & MNT_GETARGS) == 0) { 967 error = copyin(data, &fs_args32.null_args, 968 sizeof(fs_args32.null_args)); 969 if (error) 970 return error; 971 fs_args.null_args.la.target = 972 NETBSD32PTR64(fs_args32.null_args.la.target); 973 } 974 data_seg = UIO_SYSSPACE; 975 data = &fs_args.null_args; 976 data_len = sizeof(fs_args.null_args); 977 } else { 978 data_seg = UIO_USERSPACE; 979 } 980 981 error = do_sys_mount(l, mtype, UIO_SYSSPACE, path, flags, data, data_seg, 982 data_len, retval); 983 if (error) 984 return error; 985 986 if (flags & MNT_GETARGS) { 987 data_len = *retval; 988 if (strcmp(mtype, MOUNT_TMPFS) == 0) { 989 if (data_len != sizeof(fs_args.tmpfs_args)) 990 return EINVAL; 991 fs_args32.tmpfs_args.ta_version = 992 fs_args.tmpfs_args.ta_version; 993 fs_args32.tmpfs_args.ta_nodes_max = 994 fs_args.tmpfs_args.ta_nodes_max; 995 fs_args32.tmpfs_args.ta_size_max = 996 fs_args.tmpfs_args.ta_size_max; 997 fs_args32.tmpfs_args.ta_root_uid = 998 fs_args.tmpfs_args.ta_root_uid; 999 fs_args32.tmpfs_args.ta_root_gid = 1000 fs_args.tmpfs_args.ta_root_gid; 1001 fs_args32.tmpfs_args.ta_root_mode = 1002 fs_args.tmpfs_args.ta_root_mode; 1003 error = copyout(&fs_args32.tmpfs_args, udata, 1004 sizeof(fs_args32.tmpfs_args)); 1005 *retval = sizeof(fs_args32.tmpfs_args); 1006 } else if (strcmp(mtype, MOUNT_MFS) == 0) { 1007 if (data_len != sizeof(fs_args.mfs_args)) 1008 return EINVAL; 1009 NETBSD32PTR32(fs_args32.mfs_args.fspec, 1010 fs_args.mfs_args.fspec); 1011 memset(&fs_args32.mfs_args._pad1, 0, 1012 sizeof(fs_args32.mfs_args._pad1)); 1013 NETBSD32PTR32(fs_args32.mfs_args.base, 1014 fs_args.mfs_args.base); 1015 fs_args32.mfs_args.size = fs_args.mfs_args.size; 1016 error = copyout(&fs_args32.mfs_args, udata, 1017 sizeof(fs_args32.mfs_args)); 1018 *retval = sizeof(fs_args32.mfs_args); 1019 } else if (strcmp(mtype, MOUNT_UFS) == 0) { 1020 if (data_len != sizeof(fs_args.ufs_args)) 1021 return EINVAL; 1022 NETBSD32PTR32(fs_args32.ufs_args.fspec, 1023 fs_args.ufs_args.fspec); 1024 error = copyout(&fs_args32.ufs_args, udata, 1025 sizeof(fs_args32.ufs_args)); 1026 *retval = sizeof(fs_args32.ufs_args); 1027 } else if (strcmp(mtype, MOUNT_CD9660) == 0) { 1028 if (data_len != sizeof(fs_args.iso_args)) 1029 return EINVAL; 1030 NETBSD32PTR32(fs_args32.iso_args.fspec, 1031 fs_args.iso_args.fspec); 1032 memset(&fs_args32.iso_args._pad1, 0, 1033 sizeof(fs_args32.iso_args._pad1)); 1034 fs_args32.iso_args.flags = fs_args.iso_args.flags; 1035 error = copyout(&fs_args32.iso_args, udata, 1036 sizeof(fs_args32.iso_args)); 1037 *retval = sizeof(fs_args32.iso_args); 1038 } else if (strcmp(mtype, MOUNT_NFS) == 0) { 1039 if (data_len != sizeof(fs_args.nfs_args)) 1040 return EINVAL; 1041 NETBSD32PTR32(fs_args32.nfs_args.addr, 1042 fs_args.nfs_args.addr); 1043 memcpy(&fs_args32.nfs_args.addrlen, 1044 &fs_args.nfs_args.addrlen, 1045 offsetof(struct nfs_args, fh) 1046 - offsetof(struct nfs_args, addrlen)); 1047 NETBSD32PTR32(fs_args32.nfs_args.fh, 1048 fs_args.nfs_args.fh); 1049 memcpy(&fs_args32.nfs_args.fhsize, 1050 &fs_args.nfs_args.fhsize, 1051 offsetof(struct nfs_args, hostname) 1052 - offsetof(struct nfs_args, fhsize)); 1053 NETBSD32PTR32(fs_args32.nfs_args.hostname, 1054 fs_args.nfs_args.hostname); 1055 error = copyout(&fs_args32.nfs_args, udata, 1056 sizeof(fs_args32.nfs_args)); 1057 *retval = sizeof(fs_args32.nfs_args); 1058 } else if (strcmp(mtype, MOUNT_NULL) == 0) { 1059 if (data_len != sizeof(fs_args.null_args)) 1060 return EINVAL; 1061 NETBSD32PTR32(fs_args32.null_args.la.target, 1062 fs_args.null_args.la.target); 1063 error = copyout(&fs_args32.null_args, udata, 1064 sizeof(fs_args32.null_args)); 1065 *retval = sizeof(fs_args32.null_args); 1066 } 1067 } 1068 return error; 1069 } 1070 1071 int 1072 netbsd32_linkat(struct lwp *l, const struct netbsd32_linkat_args *uap, 1073 register_t *retval) 1074 { 1075 /* { 1076 syscallarg(int) fd1; 1077 syscallarg(const netbsd32_charp) name1; 1078 syscallarg(int) fd2; 1079 syscallarg(const netbsd32_charp) name2; 1080 syscallarg(int) flags; 1081 } */ 1082 struct sys_linkat_args ua; 1083 1084 NETBSD32TO64_UAP(fd1); 1085 NETBSD32TOP_UAP(name1, const char); 1086 NETBSD32TO64_UAP(fd2); 1087 NETBSD32TOP_UAP(name2, const char); 1088 NETBSD32TO64_UAP(flags); 1089 1090 return sys_linkat(l, &ua, retval); 1091 } 1092 1093 int 1094 netbsd32_renameat(struct lwp *l, const struct netbsd32_renameat_args *uap, 1095 register_t *retval) 1096 { 1097 /* { 1098 syscallarg(int) fromfd; 1099 syscallarg(const netbsd32_charp) from; 1100 syscallarg(int) tofd; 1101 syscallarg(const netbsd32_charp) to; 1102 } */ 1103 struct sys_renameat_args ua; 1104 1105 NETBSD32TO64_UAP(fromfd); 1106 NETBSD32TOP_UAP(from, const char); 1107 NETBSD32TO64_UAP(tofd); 1108 NETBSD32TOP_UAP(to, const char); 1109 1110 return sys_renameat(l, &ua, retval); 1111 } 1112 1113 int 1114 netbsd32_mkfifoat(struct lwp *l, const struct netbsd32_mkfifoat_args *uap, 1115 register_t *retval) 1116 { 1117 /* { 1118 syscallarg(int) fd; 1119 syscallarg(const netbsd32_charp) path; 1120 syscallarg(mode_t) mode; 1121 } */ 1122 struct sys_mkfifoat_args ua; 1123 1124 NETBSD32TO64_UAP(fd); 1125 NETBSD32TOP_UAP(path, const char); 1126 NETBSD32TO64_UAP(mode); 1127 1128 return sys_mkfifoat(l, &ua, retval); 1129 } 1130 1131 int 1132 netbsd32_mknodat(struct lwp *l, const struct netbsd32_mknodat_args *uap, 1133 register_t *retval) 1134 { 1135 /* { 1136 syscallarg(int) fd; 1137 syscallarg(netbsd32_charp) path; 1138 syscallarg(mode_t) mode; 1139 syscallarg(int) pad; 1140 syscallarg(netbsd32_dev_t) dev; 1141 } */ 1142 struct sys_mknodat_args ua; 1143 1144 NETBSD32TO64_UAP(fd); 1145 NETBSD32TOP_UAP(path, const char); 1146 NETBSD32TO64_UAP(mode); 1147 NETBSD32TO64_UAP(PAD); 1148 NETBSD32TO64_UAP(dev); 1149 1150 return sys_mknodat(l, &ua, retval); 1151 } 1152 1153 int 1154 netbsd32_mkdirat(struct lwp *l, const struct netbsd32_mkdirat_args *uap, 1155 register_t *retval) 1156 { 1157 /* { 1158 syscallarg(int) fd; 1159 syscallarg(netbsd32_charp) path; 1160 syscallarg(mode_t) mode; 1161 } */ 1162 struct sys_mkdirat_args ua; 1163 1164 NETBSD32TO64_UAP(fd); 1165 NETBSD32TOP_UAP(path, const char); 1166 NETBSD32TO64_UAP(mode); 1167 1168 return sys_mkdirat(l, &ua, retval); 1169 } 1170 1171 int 1172 netbsd32_faccessat(struct lwp *l, const struct netbsd32_faccessat_args *uap, 1173 register_t *retval) 1174 { 1175 /* { 1176 syscallarg(int) fd; 1177 syscallarg(netbsd32_charp) path; 1178 syscallarg(int) amode; 1179 syscallarg(int) flag; 1180 } */ 1181 struct sys_faccessat_args ua; 1182 1183 NETBSD32TO64_UAP(fd); 1184 NETBSD32TOP_UAP(path, const char); 1185 NETBSD32TO64_UAP(amode); 1186 NETBSD32TO64_UAP(flag); 1187 1188 return sys_faccessat(l, &ua, retval); 1189 } 1190 1191 int 1192 netbsd32_fchmodat(struct lwp *l, const struct netbsd32_fchmodat_args *uap, 1193 register_t *retval) 1194 { 1195 /* { 1196 syscallarg(int) fd; 1197 syscallarg(netbsd32_charp) path; 1198 syscallarg(mode_t) mode; 1199 syscallarg(int) flag; 1200 } */ 1201 struct sys_fchmodat_args ua; 1202 1203 NETBSD32TO64_UAP(fd); 1204 NETBSD32TOP_UAP(path, const char); 1205 NETBSD32TO64_UAP(mode); 1206 NETBSD32TO64_UAP(flag); 1207 1208 return sys_fchmodat(l, &ua, retval); 1209 } 1210 1211 int 1212 netbsd32_fchownat(struct lwp *l, const struct netbsd32_fchownat_args *uap, 1213 register_t *retval) 1214 { 1215 /* { 1216 syscallarg(int) fd; 1217 syscallarg(netbsd32_charp) path; 1218 syscallarg(uid_t) owner; 1219 syscallarg(gid_t) group; 1220 syscallarg(int) flag; 1221 } */ 1222 struct sys_fchownat_args ua; 1223 1224 NETBSD32TO64_UAP(fd); 1225 NETBSD32TOP_UAP(path, const char); 1226 NETBSD32TO64_UAP(owner); 1227 NETBSD32TO64_UAP(group); 1228 NETBSD32TO64_UAP(flag); 1229 1230 return sys_fchownat(l, &ua, retval); 1231 } 1232 1233 int 1234 netbsd32_fstatat(struct lwp *l, const struct netbsd32_fstatat_args *uap, 1235 register_t *retval) 1236 { 1237 /* { 1238 syscallarg(int) fd; 1239 syscallarg(netbsd32_charp) path; 1240 syscallarg(netbsd32_statp_t) buf; 1241 syscallarg(int) flag; 1242 } */ 1243 struct netbsd32_stat sb32; 1244 struct stat sb; 1245 int follow; 1246 int error; 1247 1248 follow = (SCARG(uap, flag) & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW; 1249 1250 error = do_sys_statat(l, SCARG(uap, fd), SCARG_P32(uap, path), 1251 follow, &sb); 1252 if (error) 1253 return error; 1254 netbsd32_from_stat(&sb, &sb32); 1255 return copyout(&sb32, SCARG_P32(uap, buf), sizeof(sb32)); 1256 } 1257 1258 int 1259 netbsd32_utimensat(struct lwp *l, const struct netbsd32_utimensat_args *uap, 1260 register_t *retval) 1261 { 1262 /* { 1263 syscallarg(int) fd; 1264 syscallarg(netbsd32_charp) path; 1265 syscallarg(netbsd32_timespecp_t) tptr; 1266 syscallarg(int) flag; 1267 } */ 1268 struct timespec ts[2], *tsp; 1269 int follow; 1270 int error; 1271 1272 error = get_utimens32(SCARG_P32(uap, tptr), ts, &tsp); 1273 if (error != 0) 1274 return error; 1275 1276 follow = (SCARG(uap, flag) & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW; 1277 1278 return do_sys_utimensat(l, SCARG(uap, fd), NULL, 1279 SCARG_P32(uap, path), follow, tsp, UIO_SYSSPACE); 1280 } 1281 1282 int 1283 netbsd32_openat(struct lwp *l, const struct netbsd32_openat_args *uap, 1284 register_t *retval) 1285 { 1286 /* { 1287 syscallarg(int) fd; 1288 syscallarg(netbsd32_charp) path; 1289 syscallarg(int) oflags; 1290 syscallarg(mode_t) mode; 1291 } */ 1292 struct sys_openat_args ua; 1293 1294 NETBSD32TO64_UAP(fd); 1295 NETBSD32TOP_UAP(path, const char); 1296 NETBSD32TO64_UAP(oflags); 1297 NETBSD32TO64_UAP(mode); 1298 1299 return sys_openat(l, &ua, retval); 1300 } 1301 1302 int 1303 netbsd32_readlinkat(struct lwp *l, const struct netbsd32_readlinkat_args *uap, 1304 register_t *retval) 1305 { 1306 /* { 1307 syscallarg(int) fd; 1308 syscallarg(netbsd32_charp) path; 1309 syscallarg(netbsd32_charp) buf; 1310 syscallarg(netbsd32_size_t) bufsize; 1311 } */ 1312 struct sys_readlinkat_args ua; 1313 1314 NETBSD32TO64_UAP(fd); 1315 NETBSD32TOP_UAP(path, const char *); 1316 NETBSD32TOP_UAP(buf, char *); 1317 NETBSD32TOX_UAP(bufsize, size_t); 1318 1319 return sys_readlinkat(l, &ua, retval); 1320 } 1321 1322 int 1323 netbsd32_symlinkat(struct lwp *l, const struct netbsd32_symlinkat_args *uap, 1324 register_t *retval) 1325 { 1326 /* { 1327 syscallarg(netbsd32_charp) path1; 1328 syscallarg(int) fd; 1329 syscallarg(netbsd32_charp) path2; 1330 } */ 1331 struct sys_symlinkat_args ua; 1332 1333 NETBSD32TOP_UAP(path1, const char *); 1334 NETBSD32TO64_UAP(fd); 1335 NETBSD32TOP_UAP(path2, const char *); 1336 1337 return sys_symlinkat(l, &ua, retval); 1338 } 1339 1340 int 1341 netbsd32_unlinkat(struct lwp *l, const struct netbsd32_unlinkat_args *uap, 1342 register_t *retval) 1343 { 1344 /* { 1345 syscallarg(int) fd; 1346 syscallarg(netbsd32_charp) path; 1347 syscallarg(int) flag; 1348 } */ 1349 struct sys_unlinkat_args ua; 1350 1351 NETBSD32TO64_UAP(fd); 1352 NETBSD32TOP_UAP(path, const char *); 1353 NETBSD32TO64_UAP(flag); 1354 1355 return sys_unlinkat(l, &ua, retval); 1356 } 1357 1358 int 1359 netbsd32_futimens(struct lwp *l, const struct netbsd32_futimens_args *uap, 1360 register_t *retval) 1361 { 1362 /* { 1363 syscallarg(int) fd; 1364 syscallarg(netbsd32_timespecp_t) tptr; 1365 } */ 1366 struct timespec ts[2], *tsp; 1367 file_t *fp; 1368 int error; 1369 1370 error = get_utimens32(SCARG_P32(uap, tptr), ts, &tsp); 1371 if (error != 0) 1372 return error; 1373 1374 /* fd_getvnode() will use the descriptor for us */ 1375 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 1376 return (error); 1377 error = do_sys_utimensat(l, AT_FDCWD, fp->f_vnode, NULL, 0, 1378 tsp, UIO_SYSSPACE); 1379 fd_putfile(SCARG(uap, fd)); 1380 return (error); 1381 } 1382