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