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