1 /* $NetBSD: netbsd32_fs.c,v 1.85 2019/09/26 01:32:09 christos 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.85 2019/09/26 01:32:09 christos 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(sb)); 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 < 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 < 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 < 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 < 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 < 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 < 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 != sizeof(fs_args.tmpfs_args)) 992 return EINVAL; 993 fs_args32.tmpfs_args.ta_version = 994 fs_args.tmpfs_args.ta_version; 995 fs_args32.tmpfs_args.ta_nodes_max = 996 fs_args.tmpfs_args.ta_nodes_max; 997 fs_args32.tmpfs_args.ta_size_max = 998 fs_args.tmpfs_args.ta_size_max; 999 fs_args32.tmpfs_args.ta_root_uid = 1000 fs_args.tmpfs_args.ta_root_uid; 1001 fs_args32.tmpfs_args.ta_root_gid = 1002 fs_args.tmpfs_args.ta_root_gid; 1003 fs_args32.tmpfs_args.ta_root_mode = 1004 fs_args.tmpfs_args.ta_root_mode; 1005 error = copyout(&fs_args32.tmpfs_args, udata, 1006 sizeof(fs_args32.tmpfs_args)); 1007 *retval = sizeof(fs_args32.tmpfs_args); 1008 } else if (strcmp(mtype, MOUNT_MFS) == 0) { 1009 if (data_len != sizeof(fs_args.mfs_args)) 1010 return EINVAL; 1011 NETBSD32PTR32(fs_args32.mfs_args.fspec, 1012 fs_args.mfs_args.fspec); 1013 memset(&fs_args32.mfs_args._pad1, 0, 1014 sizeof(fs_args32.mfs_args._pad1)); 1015 NETBSD32PTR32(fs_args32.mfs_args.base, 1016 fs_args.mfs_args.base); 1017 fs_args32.mfs_args.size = fs_args.mfs_args.size; 1018 error = copyout(&fs_args32.mfs_args, udata, 1019 sizeof(fs_args32.mfs_args)); 1020 *retval = sizeof(fs_args32.mfs_args); 1021 } else if (strcmp(mtype, MOUNT_UFS) == 0) { 1022 if (data_len != sizeof(fs_args.ufs_args)) 1023 return EINVAL; 1024 NETBSD32PTR32(fs_args32.ufs_args.fspec, 1025 fs_args.ufs_args.fspec); 1026 error = copyout(&fs_args32.ufs_args, udata, 1027 sizeof(fs_args32.ufs_args)); 1028 *retval = sizeof(fs_args32.ufs_args); 1029 } else if (strcmp(mtype, MOUNT_CD9660) == 0) { 1030 if (data_len != sizeof(fs_args.iso_args)) 1031 return EINVAL; 1032 NETBSD32PTR32(fs_args32.iso_args.fspec, 1033 fs_args.iso_args.fspec); 1034 memset(&fs_args32.iso_args._pad1, 0, 1035 sizeof(fs_args32.iso_args._pad1)); 1036 fs_args32.iso_args.flags = fs_args.iso_args.flags; 1037 error = copyout(&fs_args32.iso_args, udata, 1038 sizeof(fs_args32.iso_args)); 1039 *retval = sizeof(fs_args32.iso_args); 1040 } else if (strcmp(mtype, MOUNT_NFS) == 0) { 1041 if (data_len != sizeof(fs_args.nfs_args)) 1042 return EINVAL; 1043 NETBSD32PTR32(fs_args32.nfs_args.addr, 1044 fs_args.nfs_args.addr); 1045 memcpy(&fs_args32.nfs_args.addrlen, 1046 &fs_args.nfs_args.addrlen, 1047 offsetof(struct nfs_args, fh) 1048 - offsetof(struct nfs_args, addrlen)); 1049 NETBSD32PTR32(fs_args32.nfs_args.fh, 1050 fs_args.nfs_args.fh); 1051 memcpy(&fs_args32.nfs_args.fhsize, 1052 &fs_args.nfs_args.fhsize, 1053 offsetof(struct nfs_args, hostname) 1054 - offsetof(struct nfs_args, fhsize)); 1055 NETBSD32PTR32(fs_args32.nfs_args.hostname, 1056 fs_args.nfs_args.hostname); 1057 error = copyout(&fs_args32.nfs_args, udata, 1058 sizeof(fs_args32.nfs_args)); 1059 *retval = sizeof(fs_args32.nfs_args); 1060 } else if (strcmp(mtype, MOUNT_NULL) == 0) { 1061 if (data_len != sizeof(fs_args.null_args)) 1062 return EINVAL; 1063 NETBSD32PTR32(fs_args32.null_args.la.target, 1064 fs_args.null_args.la.target); 1065 error = copyout(&fs_args32.null_args, udata, 1066 sizeof(fs_args32.null_args)); 1067 *retval = sizeof(fs_args32.null_args); 1068 } 1069 } 1070 return error; 1071 } 1072 1073 int 1074 netbsd32_linkat(struct lwp *l, const struct netbsd32_linkat_args *uap, 1075 register_t *retval) 1076 { 1077 /* { 1078 syscallarg(int) fd1; 1079 syscallarg(const netbsd32_charp) name1; 1080 syscallarg(int) fd2; 1081 syscallarg(const netbsd32_charp) name2; 1082 syscallarg(int) flags; 1083 } */ 1084 struct sys_linkat_args ua; 1085 1086 NETBSD32TO64_UAP(fd1); 1087 NETBSD32TOP_UAP(name1, const char); 1088 NETBSD32TO64_UAP(fd2); 1089 NETBSD32TOP_UAP(name2, const char); 1090 NETBSD32TO64_UAP(flags); 1091 1092 return sys_linkat(l, &ua, retval); 1093 } 1094 1095 int 1096 netbsd32_renameat(struct lwp *l, const struct netbsd32_renameat_args *uap, 1097 register_t *retval) 1098 { 1099 /* { 1100 syscallarg(int) fromfd; 1101 syscallarg(const netbsd32_charp) from; 1102 syscallarg(int) tofd; 1103 syscallarg(const netbsd32_charp) to; 1104 } */ 1105 struct sys_renameat_args ua; 1106 1107 NETBSD32TO64_UAP(fromfd); 1108 NETBSD32TOP_UAP(from, const char); 1109 NETBSD32TO64_UAP(tofd); 1110 NETBSD32TOP_UAP(to, const char); 1111 1112 return sys_renameat(l, &ua, retval); 1113 } 1114 1115 int 1116 netbsd32_mkfifoat(struct lwp *l, const struct netbsd32_mkfifoat_args *uap, 1117 register_t *retval) 1118 { 1119 /* { 1120 syscallarg(int) fd; 1121 syscallarg(const netbsd32_charp) path; 1122 syscallarg(mode_t) mode; 1123 } */ 1124 struct sys_mkfifoat_args ua; 1125 1126 NETBSD32TO64_UAP(fd); 1127 NETBSD32TOP_UAP(path, const char); 1128 NETBSD32TO64_UAP(mode); 1129 1130 return sys_mkfifoat(l, &ua, retval); 1131 } 1132 1133 int 1134 netbsd32_mknodat(struct lwp *l, const struct netbsd32_mknodat_args *uap, 1135 register_t *retval) 1136 { 1137 /* { 1138 syscallarg(int) fd; 1139 syscallarg(netbsd32_charp) path; 1140 syscallarg(mode_t) mode; 1141 syscallarg(int) pad; 1142 syscallarg(netbsd32_dev_t) dev; 1143 } */ 1144 struct sys_mknodat_args ua; 1145 1146 NETBSD32TO64_UAP(fd); 1147 NETBSD32TOP_UAP(path, const char); 1148 NETBSD32TO64_UAP(mode); 1149 NETBSD32TO64_UAP(PAD); 1150 NETBSD32TO64_UAP(dev); 1151 1152 return sys_mknodat(l, &ua, retval); 1153 } 1154 1155 int 1156 netbsd32_mkdirat(struct lwp *l, const struct netbsd32_mkdirat_args *uap, 1157 register_t *retval) 1158 { 1159 /* { 1160 syscallarg(int) fd; 1161 syscallarg(netbsd32_charp) path; 1162 syscallarg(mode_t) mode; 1163 } */ 1164 struct sys_mkdirat_args ua; 1165 1166 NETBSD32TO64_UAP(fd); 1167 NETBSD32TOP_UAP(path, const char); 1168 NETBSD32TO64_UAP(mode); 1169 1170 return sys_mkdirat(l, &ua, retval); 1171 } 1172 1173 int 1174 netbsd32_faccessat(struct lwp *l, const struct netbsd32_faccessat_args *uap, 1175 register_t *retval) 1176 { 1177 /* { 1178 syscallarg(int) fd; 1179 syscallarg(netbsd32_charp) path; 1180 syscallarg(int) amode; 1181 syscallarg(int) flag; 1182 } */ 1183 struct sys_faccessat_args ua; 1184 1185 NETBSD32TO64_UAP(fd); 1186 NETBSD32TOP_UAP(path, const char); 1187 NETBSD32TO64_UAP(amode); 1188 NETBSD32TO64_UAP(flag); 1189 1190 return sys_faccessat(l, &ua, retval); 1191 } 1192 1193 int 1194 netbsd32_fchmodat(struct lwp *l, const struct netbsd32_fchmodat_args *uap, 1195 register_t *retval) 1196 { 1197 /* { 1198 syscallarg(int) fd; 1199 syscallarg(netbsd32_charp) path; 1200 syscallarg(mode_t) mode; 1201 syscallarg(int) flag; 1202 } */ 1203 struct sys_fchmodat_args ua; 1204 1205 NETBSD32TO64_UAP(fd); 1206 NETBSD32TOP_UAP(path, const char); 1207 NETBSD32TO64_UAP(mode); 1208 NETBSD32TO64_UAP(flag); 1209 1210 return sys_fchmodat(l, &ua, retval); 1211 } 1212 1213 int 1214 netbsd32_fchownat(struct lwp *l, const struct netbsd32_fchownat_args *uap, 1215 register_t *retval) 1216 { 1217 /* { 1218 syscallarg(int) fd; 1219 syscallarg(netbsd32_charp) path; 1220 syscallarg(uid_t) owner; 1221 syscallarg(gid_t) group; 1222 syscallarg(int) flag; 1223 } */ 1224 struct sys_fchownat_args ua; 1225 1226 NETBSD32TO64_UAP(fd); 1227 NETBSD32TOP_UAP(path, const char); 1228 NETBSD32TO64_UAP(owner); 1229 NETBSD32TO64_UAP(group); 1230 NETBSD32TO64_UAP(flag); 1231 1232 return sys_fchownat(l, &ua, retval); 1233 } 1234 1235 int 1236 netbsd32_fstatat(struct lwp *l, const struct netbsd32_fstatat_args *uap, 1237 register_t *retval) 1238 { 1239 /* { 1240 syscallarg(int) fd; 1241 syscallarg(netbsd32_charp) path; 1242 syscallarg(netbsd32_statp_t) buf; 1243 syscallarg(int) flag; 1244 } */ 1245 struct netbsd32_stat sb32; 1246 struct stat sb; 1247 int follow; 1248 int error; 1249 1250 follow = (SCARG(uap, flag) & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW; 1251 1252 error = do_sys_statat(l, SCARG(uap, fd), SCARG_P32(uap, path), 1253 follow, &sb); 1254 if (error) 1255 return error; 1256 netbsd32_from_stat(&sb, &sb32); 1257 return copyout(&sb32, SCARG_P32(uap, buf), sizeof(sb32)); 1258 } 1259 1260 int 1261 netbsd32_utimensat(struct lwp *l, const struct netbsd32_utimensat_args *uap, 1262 register_t *retval) 1263 { 1264 /* { 1265 syscallarg(int) fd; 1266 syscallarg(netbsd32_charp) path; 1267 syscallarg(netbsd32_timespecp_t) tptr; 1268 syscallarg(int) flag; 1269 } */ 1270 struct timespec ts[2], *tsp; 1271 int follow; 1272 int error; 1273 1274 error = get_utimens32(SCARG_P32(uap, tptr), ts, &tsp); 1275 if (error != 0) 1276 return error; 1277 1278 follow = (SCARG(uap, flag) & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW; 1279 1280 return do_sys_utimensat(l, SCARG(uap, fd), NULL, 1281 SCARG_P32(uap, path), follow, tsp, UIO_SYSSPACE); 1282 } 1283 1284 int 1285 netbsd32_openat(struct lwp *l, const struct netbsd32_openat_args *uap, 1286 register_t *retval) 1287 { 1288 /* { 1289 syscallarg(int) fd; 1290 syscallarg(netbsd32_charp) path; 1291 syscallarg(int) oflags; 1292 syscallarg(mode_t) mode; 1293 } */ 1294 struct sys_openat_args ua; 1295 1296 NETBSD32TO64_UAP(fd); 1297 NETBSD32TOP_UAP(path, const char); 1298 NETBSD32TO64_UAP(oflags); 1299 NETBSD32TO64_UAP(mode); 1300 1301 return sys_openat(l, &ua, retval); 1302 } 1303 1304 int 1305 netbsd32_readlinkat(struct lwp *l, const struct netbsd32_readlinkat_args *uap, 1306 register_t *retval) 1307 { 1308 /* { 1309 syscallarg(int) fd; 1310 syscallarg(netbsd32_charp) path; 1311 syscallarg(netbsd32_charp) buf; 1312 syscallarg(netbsd32_size_t) bufsize; 1313 } */ 1314 struct sys_readlinkat_args ua; 1315 1316 NETBSD32TO64_UAP(fd); 1317 NETBSD32TOP_UAP(path, const char *); 1318 NETBSD32TOP_UAP(buf, char *); 1319 NETBSD32TOX_UAP(bufsize, size_t); 1320 1321 return sys_readlinkat(l, &ua, retval); 1322 } 1323 1324 int 1325 netbsd32_symlinkat(struct lwp *l, const struct netbsd32_symlinkat_args *uap, 1326 register_t *retval) 1327 { 1328 /* { 1329 syscallarg(netbsd32_charp) path1; 1330 syscallarg(int) fd; 1331 syscallarg(netbsd32_charp) path2; 1332 } */ 1333 struct sys_symlinkat_args ua; 1334 1335 NETBSD32TOP_UAP(path1, const char *); 1336 NETBSD32TO64_UAP(fd); 1337 NETBSD32TOP_UAP(path2, const char *); 1338 1339 return sys_symlinkat(l, &ua, retval); 1340 } 1341 1342 int 1343 netbsd32_unlinkat(struct lwp *l, const struct netbsd32_unlinkat_args *uap, 1344 register_t *retval) 1345 { 1346 /* { 1347 syscallarg(int) fd; 1348 syscallarg(netbsd32_charp) path; 1349 syscallarg(int) flag; 1350 } */ 1351 struct sys_unlinkat_args ua; 1352 1353 NETBSD32TO64_UAP(fd); 1354 NETBSD32TOP_UAP(path, const char *); 1355 NETBSD32TO64_UAP(flag); 1356 1357 return sys_unlinkat(l, &ua, retval); 1358 } 1359 1360 int 1361 netbsd32_futimens(struct lwp *l, const struct netbsd32_futimens_args *uap, 1362 register_t *retval) 1363 { 1364 /* { 1365 syscallarg(int) fd; 1366 syscallarg(netbsd32_timespecp_t) tptr; 1367 } */ 1368 struct timespec ts[2], *tsp; 1369 file_t *fp; 1370 int error; 1371 1372 error = get_utimens32(SCARG_P32(uap, tptr), ts, &tsp); 1373 if (error != 0) 1374 return error; 1375 1376 /* fd_getvnode() will use the descriptor for us */ 1377 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 1378 return (error); 1379 error = do_sys_utimensat(l, AT_FDCWD, fp->f_vnode, NULL, 0, 1380 tsp, UIO_SYSSPACE); 1381 fd_putfile(SCARG(uap, fd)); 1382 return (error); 1383 } 1384