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