1 /* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94 39 * $FreeBSD$ 40 */ 41 42 /* For 4.3 integer FS ID compatibility */ 43 #include "opt_compat.h" 44 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/bio.h> 48 #include <sys/buf.h> 49 #include <sys/sysent.h> 50 #include <sys/malloc.h> 51 #include <sys/mount.h> 52 #include <sys/mutex.h> 53 #include <sys/sysproto.h> 54 #include <sys/namei.h> 55 #include <sys/filedesc.h> 56 #include <sys/kernel.h> 57 #include <sys/fcntl.h> 58 #include <sys/file.h> 59 #include <sys/linker.h> 60 #include <sys/stat.h> 61 #include <sys/sx.h> 62 #include <sys/unistd.h> 63 #include <sys/vnode.h> 64 #include <sys/proc.h> 65 #include <sys/dirent.h> 66 #include <sys/extattr.h> 67 #include <sys/jail.h> 68 #include <sys/sysctl.h> 69 70 #include <machine/limits.h> 71 #include <machine/stdarg.h> 72 73 #include <vm/vm.h> 74 #include <vm/vm_object.h> 75 #include <vm/vm_page.h> 76 #include <vm/uma.h> 77 78 static int change_dir(struct nameidata *ndp, struct thread *td); 79 static int chroot_refuse_vdir_fds(struct filedesc *fdp); 80 static int getutimes(const struct timeval *, struct timespec *); 81 static int setfown(struct thread *td, struct vnode *, uid_t, gid_t); 82 static int setfmode(struct thread *td, struct vnode *, int); 83 static int setfflags(struct thread *td, struct vnode *, int); 84 static int setutimes(struct thread *td, struct vnode *, 85 const struct timespec *, int); 86 static int vn_access(struct vnode *vp, int user_flags, struct ucred *cred, 87 struct thread *td); 88 89 int (*union_dircheckp)(struct thread *td, struct vnode **, struct file *); 90 int (*softdep_fsync_hook)(struct vnode *); 91 92 /* 93 * Sync each mounted filesystem. 94 */ 95 #ifndef _SYS_SYSPROTO_H_ 96 struct sync_args { 97 int dummy; 98 }; 99 #endif 100 101 #ifdef DEBUG 102 static int syncprt = 0; 103 SYSCTL_INT(_debug, OID_AUTO, syncprt, CTLFLAG_RW, &syncprt, 0, ""); 104 #endif 105 106 /* ARGSUSED */ 107 int 108 sync(td, uap) 109 struct thread *td; 110 struct sync_args *uap; 111 { 112 struct mount *mp, *nmp; 113 int asyncflag; 114 115 mtx_lock(&mountlist_mtx); 116 for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) { 117 if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) { 118 nmp = TAILQ_NEXT(mp, mnt_list); 119 continue; 120 } 121 if ((mp->mnt_flag & MNT_RDONLY) == 0 && 122 vn_start_write(NULL, &mp, V_NOWAIT) == 0) { 123 asyncflag = mp->mnt_flag & MNT_ASYNC; 124 mp->mnt_flag &= ~MNT_ASYNC; 125 vfs_msync(mp, MNT_NOWAIT); 126 VFS_SYNC(mp, MNT_NOWAIT, 127 ((td != NULL) ? td->td_ucred : NOCRED), td); 128 mp->mnt_flag |= asyncflag; 129 vn_finished_write(mp); 130 } 131 mtx_lock(&mountlist_mtx); 132 nmp = TAILQ_NEXT(mp, mnt_list); 133 vfs_unbusy(mp, td); 134 } 135 mtx_unlock(&mountlist_mtx); 136 #if 0 137 /* 138 * XXX don't call vfs_bufstats() yet because that routine 139 * was not imported in the Lite2 merge. 140 */ 141 #ifdef DIAGNOSTIC 142 if (syncprt) 143 vfs_bufstats(); 144 #endif /* DIAGNOSTIC */ 145 #endif 146 return (0); 147 } 148 149 /* XXX PRISON: could be per prison flag */ 150 static int prison_quotas; 151 #if 0 152 SYSCTL_INT(_kern_prison, OID_AUTO, quotas, CTLFLAG_RW, &prison_quotas, 0, ""); 153 #endif 154 155 /* 156 * Change filesystem quotas. 157 */ 158 #ifndef _SYS_SYSPROTO_H_ 159 struct quotactl_args { 160 char *path; 161 int cmd; 162 int uid; 163 caddr_t arg; 164 }; 165 #endif 166 /* ARGSUSED */ 167 int 168 quotactl(td, uap) 169 struct thread *td; 170 register struct quotactl_args /* { 171 syscallarg(char *) path; 172 syscallarg(int) cmd; 173 syscallarg(int) uid; 174 syscallarg(caddr_t) arg; 175 } */ *uap; 176 { 177 struct mount *mp; 178 int error; 179 struct nameidata nd; 180 181 if (jailed(td->td_ucred) && !prison_quotas) 182 return (EPERM); 183 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 184 if ((error = namei(&nd)) != 0) 185 return (error); 186 NDFREE(&nd, NDF_ONLY_PNBUF); 187 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 188 vrele(nd.ni_vp); 189 if (error) 190 return (error); 191 error = VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid), 192 SCARG(uap, arg), td); 193 vn_finished_write(mp); 194 return (error); 195 } 196 197 /* 198 * Get filesystem statistics. 199 */ 200 #ifndef _SYS_SYSPROTO_H_ 201 struct statfs_args { 202 char *path; 203 struct statfs *buf; 204 }; 205 #endif 206 /* ARGSUSED */ 207 int 208 statfs(td, uap) 209 struct thread *td; 210 register struct statfs_args /* { 211 syscallarg(char *) path; 212 syscallarg(struct statfs *) buf; 213 } */ *uap; 214 { 215 register struct mount *mp; 216 register struct statfs *sp; 217 int error; 218 struct nameidata nd; 219 struct statfs sb; 220 221 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 222 if ((error = namei(&nd)) != 0) 223 return (error); 224 mp = nd.ni_vp->v_mount; 225 sp = &mp->mnt_stat; 226 NDFREE(&nd, NDF_ONLY_PNBUF); 227 vrele(nd.ni_vp); 228 error = VFS_STATFS(mp, sp, td); 229 if (error) 230 return (error); 231 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 232 if (suser(td)) { 233 bcopy(sp, &sb, sizeof(sb)); 234 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; 235 sp = &sb; 236 } 237 return (copyout(sp, SCARG(uap, buf), sizeof(*sp))); 238 } 239 240 /* 241 * Get filesystem statistics. 242 */ 243 #ifndef _SYS_SYSPROTO_H_ 244 struct fstatfs_args { 245 int fd; 246 struct statfs *buf; 247 }; 248 #endif 249 /* ARGSUSED */ 250 int 251 fstatfs(td, uap) 252 struct thread *td; 253 register struct fstatfs_args /* { 254 syscallarg(int) fd; 255 syscallarg(struct statfs *) buf; 256 } */ *uap; 257 { 258 struct file *fp; 259 struct mount *mp; 260 register struct statfs *sp; 261 int error; 262 struct statfs sb; 263 264 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 265 return (error); 266 mp = ((struct vnode *)fp->f_data)->v_mount; 267 fdrop(fp, td); 268 if (mp == NULL) 269 return (EBADF); 270 sp = &mp->mnt_stat; 271 error = VFS_STATFS(mp, sp, td); 272 if (error) 273 return (error); 274 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 275 if (suser(td)) { 276 bcopy(sp, &sb, sizeof(sb)); 277 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; 278 sp = &sb; 279 } 280 return (copyout(sp, SCARG(uap, buf), sizeof(*sp))); 281 } 282 283 /* 284 * Get statistics on all filesystems. 285 */ 286 #ifndef _SYS_SYSPROTO_H_ 287 struct getfsstat_args { 288 struct statfs *buf; 289 long bufsize; 290 int flags; 291 }; 292 #endif 293 int 294 getfsstat(td, uap) 295 struct thread *td; 296 register struct getfsstat_args /* { 297 syscallarg(struct statfs *) buf; 298 syscallarg(long) bufsize; 299 syscallarg(int) flags; 300 } */ *uap; 301 { 302 register struct mount *mp, *nmp; 303 register struct statfs *sp; 304 caddr_t sfsp; 305 long count, maxcount, error; 306 307 maxcount = SCARG(uap, bufsize) / sizeof(struct statfs); 308 sfsp = (caddr_t)SCARG(uap, buf); 309 count = 0; 310 mtx_lock(&mountlist_mtx); 311 for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) { 312 if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) { 313 nmp = TAILQ_NEXT(mp, mnt_list); 314 continue; 315 } 316 if (sfsp && count < maxcount) { 317 sp = &mp->mnt_stat; 318 /* 319 * If MNT_NOWAIT or MNT_LAZY is specified, do not 320 * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY 321 * overrides MNT_WAIT. 322 */ 323 if (((SCARG(uap, flags) & (MNT_LAZY|MNT_NOWAIT)) == 0 || 324 (SCARG(uap, flags) & MNT_WAIT)) && 325 (error = VFS_STATFS(mp, sp, td))) { 326 mtx_lock(&mountlist_mtx); 327 nmp = TAILQ_NEXT(mp, mnt_list); 328 vfs_unbusy(mp, td); 329 continue; 330 } 331 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 332 error = copyout(sp, sfsp, sizeof(*sp)); 333 if (error) { 334 vfs_unbusy(mp, td); 335 return (error); 336 } 337 sfsp += sizeof(*sp); 338 } 339 count++; 340 mtx_lock(&mountlist_mtx); 341 nmp = TAILQ_NEXT(mp, mnt_list); 342 vfs_unbusy(mp, td); 343 } 344 mtx_unlock(&mountlist_mtx); 345 if (sfsp && count > maxcount) 346 td->td_retval[0] = maxcount; 347 else 348 td->td_retval[0] = count; 349 return (0); 350 } 351 352 /* 353 * Change current working directory to a given file descriptor. 354 */ 355 #ifndef _SYS_SYSPROTO_H_ 356 struct fchdir_args { 357 int fd; 358 }; 359 #endif 360 /* ARGSUSED */ 361 int 362 fchdir(td, uap) 363 struct thread *td; 364 struct fchdir_args /* { 365 syscallarg(int) fd; 366 } */ *uap; 367 { 368 register struct filedesc *fdp = td->td_proc->p_fd; 369 struct vnode *vp, *tdp, *vpold; 370 struct mount *mp; 371 struct file *fp; 372 int error; 373 374 if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0) 375 return (error); 376 vp = (struct vnode *)fp->f_data; 377 VREF(vp); 378 fdrop(fp, td); 379 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 380 if (vp->v_type != VDIR) 381 error = ENOTDIR; 382 else 383 error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td); 384 while (!error && (mp = vp->v_mountedhere) != NULL) { 385 if (vfs_busy(mp, 0, 0, td)) 386 continue; 387 error = VFS_ROOT(mp, &tdp); 388 vfs_unbusy(mp, td); 389 if (error) 390 break; 391 vput(vp); 392 vp = tdp; 393 } 394 if (error) { 395 vput(vp); 396 return (error); 397 } 398 VOP_UNLOCK(vp, 0, td); 399 FILEDESC_LOCK(fdp); 400 vpold = fdp->fd_cdir; 401 fdp->fd_cdir = vp; 402 FILEDESC_UNLOCK(fdp); 403 vrele(vpold); 404 return (0); 405 } 406 407 /* 408 * Change current working directory (``.''). 409 */ 410 #ifndef _SYS_SYSPROTO_H_ 411 struct chdir_args { 412 char *path; 413 }; 414 #endif 415 /* ARGSUSED */ 416 int 417 chdir(td, uap) 418 struct thread *td; 419 struct chdir_args /* { 420 syscallarg(char *) path; 421 } */ *uap; 422 { 423 register struct filedesc *fdp = td->td_proc->p_fd; 424 int error; 425 struct nameidata nd; 426 struct vnode *vp; 427 428 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 429 SCARG(uap, path), td); 430 if ((error = change_dir(&nd, td)) != 0) 431 return (error); 432 NDFREE(&nd, NDF_ONLY_PNBUF); 433 FILEDESC_LOCK(fdp); 434 vp = fdp->fd_cdir; 435 fdp->fd_cdir = nd.ni_vp; 436 FILEDESC_UNLOCK(fdp); 437 vrele(vp); 438 return (0); 439 } 440 441 /* 442 * Helper function for raised chroot(2) security function: Refuse if 443 * any filedescriptors are open directories. 444 */ 445 static int 446 chroot_refuse_vdir_fds(fdp) 447 struct filedesc *fdp; 448 { 449 struct vnode *vp; 450 struct file *fp; 451 int fd; 452 453 FILEDESC_LOCK(fdp); 454 for (fd = 0; fd < fdp->fd_nfiles ; fd++) { 455 fp = fget_locked(fdp, fd); 456 if (fp == NULL) 457 continue; 458 if (fp->f_type == DTYPE_VNODE) { 459 vp = (struct vnode *)fp->f_data; 460 if (vp->v_type == VDIR) { 461 FILEDESC_UNLOCK(fdp); 462 return (EPERM); 463 } 464 } 465 } 466 FILEDESC_UNLOCK(fdp); 467 return (0); 468 } 469 470 /* 471 * This sysctl determines if we will allow a process to chroot(2) if it 472 * has a directory open: 473 * 0: disallowed for all processes. 474 * 1: allowed for processes that were not already chroot(2)'ed. 475 * 2: allowed for all processes. 476 */ 477 478 static int chroot_allow_open_directories = 1; 479 480 SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW, 481 &chroot_allow_open_directories, 0, ""); 482 483 /* 484 * Change notion of root (``/'') directory. 485 */ 486 #ifndef _SYS_SYSPROTO_H_ 487 struct chroot_args { 488 char *path; 489 }; 490 #endif 491 /* ARGSUSED */ 492 int 493 chroot(td, uap) 494 struct thread *td; 495 struct chroot_args /* { 496 syscallarg(char *) path; 497 } */ *uap; 498 { 499 register struct filedesc *fdp = td->td_proc->p_fd; 500 int error; 501 struct nameidata nd; 502 struct vnode *vp; 503 504 error = suser_cred(td->td_ucred, PRISON_ROOT); 505 if (error) 506 return (error); 507 FILEDESC_LOCK(fdp); 508 if (chroot_allow_open_directories == 0 || 509 (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) { 510 FILEDESC_UNLOCK(fdp); 511 error = chroot_refuse_vdir_fds(fdp); 512 } else 513 FILEDESC_UNLOCK(fdp); 514 if (error) 515 return (error); 516 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 517 SCARG(uap, path), td); 518 if ((error = change_dir(&nd, td)) != 0) 519 return (error); 520 NDFREE(&nd, NDF_ONLY_PNBUF); 521 FILEDESC_LOCK(fdp); 522 vp = fdp->fd_rdir; 523 fdp->fd_rdir = nd.ni_vp; 524 if (!fdp->fd_jdir) { 525 fdp->fd_jdir = nd.ni_vp; 526 VREF(fdp->fd_jdir); 527 } 528 FILEDESC_UNLOCK(fdp); 529 vrele(vp); 530 return (0); 531 } 532 533 /* 534 * Common routine for chroot and chdir. 535 */ 536 static int 537 change_dir(ndp, td) 538 register struct nameidata *ndp; 539 struct thread *td; 540 { 541 struct vnode *vp; 542 int error; 543 544 error = namei(ndp); 545 if (error) 546 return (error); 547 vp = ndp->ni_vp; 548 if (vp->v_type != VDIR) 549 error = ENOTDIR; 550 else 551 error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td); 552 if (error) 553 vput(vp); 554 else 555 VOP_UNLOCK(vp, 0, td); 556 return (error); 557 } 558 559 /* 560 * Check permissions, allocate an open file structure, 561 * and call the device open routine if any. 562 */ 563 #ifndef _SYS_SYSPROTO_H_ 564 struct open_args { 565 char *path; 566 int flags; 567 int mode; 568 }; 569 #endif 570 int 571 open(td, uap) 572 struct thread *td; 573 register struct open_args /* { 574 syscallarg(char *) path; 575 syscallarg(int) flags; 576 syscallarg(int) mode; 577 } */ *uap; 578 { 579 struct proc *p = td->td_proc; 580 struct filedesc *fdp = p->p_fd; 581 struct file *fp; 582 struct vnode *vp; 583 struct vattr vat; 584 struct mount *mp; 585 int cmode, flags, oflags; 586 struct file *nfp; 587 int type, indx, error; 588 struct flock lf; 589 struct nameidata nd; 590 591 oflags = SCARG(uap, flags); 592 if ((oflags & O_ACCMODE) == O_ACCMODE) 593 return (EINVAL); 594 flags = FFLAGS(oflags); 595 error = falloc(td, &nfp, &indx); 596 if (error) 597 return (error); 598 fp = nfp; 599 FILEDESC_LOCK(fdp); 600 cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; 601 FILEDESC_UNLOCK(fdp); 602 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 603 td->td_dupfd = -indx - 1; /* XXX check for fdopen */ 604 /* 605 * Bump the ref count to prevent another process from closing 606 * the descriptor while we are blocked in vn_open() 607 */ 608 fhold(fp); 609 error = vn_open(&nd, &flags, cmode); 610 if (error) { 611 /* 612 * release our own reference 613 */ 614 fdrop(fp, td); 615 616 /* 617 * handle special fdopen() case. bleh. dupfdopen() is 618 * responsible for dropping the old contents of ofiles[indx] 619 * if it succeeds. 620 */ 621 if ((error == ENODEV || error == ENXIO) && 622 td->td_dupfd >= 0 && /* XXX from fdopen */ 623 (error = 624 dupfdopen(td, fdp, indx, td->td_dupfd, flags, error)) == 0) { 625 td->td_retval[0] = indx; 626 return (0); 627 } 628 /* 629 * Clean up the descriptor, but only if another thread hadn't 630 * replaced or closed it. 631 */ 632 FILEDESC_LOCK(fdp); 633 if (fdp->fd_ofiles[indx] == fp) { 634 fdp->fd_ofiles[indx] = NULL; 635 FILEDESC_UNLOCK(fdp); 636 fdrop(fp, td); 637 } else 638 FILEDESC_UNLOCK(fdp); 639 640 if (error == ERESTART) 641 error = EINTR; 642 return (error); 643 } 644 td->td_dupfd = 0; 645 NDFREE(&nd, NDF_ONLY_PNBUF); 646 vp = nd.ni_vp; 647 648 /* 649 * There should be 2 references on the file, one from the descriptor 650 * table, and one for us. 651 * 652 * Handle the case where someone closed the file (via its file 653 * descriptor) while we were blocked. The end result should look 654 * like opening the file succeeded but it was immediately closed. 655 */ 656 FILEDESC_LOCK(fdp); 657 FILE_LOCK(fp); 658 if (fp->f_count == 1) { 659 KASSERT(fdp->fd_ofiles[indx] != fp, 660 ("Open file descriptor lost all refs")); 661 FILEDESC_UNLOCK(fdp); 662 FILE_UNLOCK(fp); 663 VOP_UNLOCK(vp, 0, td); 664 vn_close(vp, flags & FMASK, fp->f_cred, td); 665 fdrop(fp, td); 666 td->td_retval[0] = indx; 667 return 0; 668 } 669 670 /* assert that vn_open created a backing object if one is needed */ 671 KASSERT(!vn_canvmio(vp) || VOP_GETVOBJECT(vp, NULL) == 0, 672 ("open: vmio vnode has no backing object after vn_open")); 673 674 fp->f_data = vp; 675 fp->f_flag = flags & FMASK; 676 fp->f_ops = &vnops; 677 fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE); 678 FILEDESC_UNLOCK(fdp); 679 FILE_UNLOCK(fp); 680 VOP_UNLOCK(vp, 0, td); 681 if (flags & (O_EXLOCK | O_SHLOCK)) { 682 lf.l_whence = SEEK_SET; 683 lf.l_start = 0; 684 lf.l_len = 0; 685 if (flags & O_EXLOCK) 686 lf.l_type = F_WRLCK; 687 else 688 lf.l_type = F_RDLCK; 689 type = F_FLOCK; 690 if ((flags & FNONBLOCK) == 0) 691 type |= F_WAIT; 692 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, 693 type)) != 0) 694 goto bad; 695 fp->f_flag |= FHASLOCK; 696 } 697 if (flags & O_TRUNC) { 698 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 699 goto bad; 700 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 701 VATTR_NULL(&vat); 702 vat.va_size = 0; 703 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 704 error = VOP_SETATTR(vp, &vat, td->td_ucred, td); 705 VOP_UNLOCK(vp, 0, td); 706 vn_finished_write(mp); 707 if (error) 708 goto bad; 709 } 710 /* 711 * Release our private reference, leaving the one associated with 712 * the descriptor table intact. 713 */ 714 fdrop(fp, td); 715 td->td_retval[0] = indx; 716 return (0); 717 bad: 718 FILEDESC_LOCK(fdp); 719 if (fdp->fd_ofiles[indx] == fp) { 720 fdp->fd_ofiles[indx] = NULL; 721 FILEDESC_UNLOCK(fdp); 722 fdrop(fp, td); 723 } else 724 FILEDESC_UNLOCK(fdp); 725 return (error); 726 } 727 728 #ifdef COMPAT_43 729 /* 730 * Create a file. 731 */ 732 #ifndef _SYS_SYSPROTO_H_ 733 struct ocreat_args { 734 char *path; 735 int mode; 736 }; 737 #endif 738 int 739 ocreat(td, uap) 740 struct thread *td; 741 register struct ocreat_args /* { 742 syscallarg(char *) path; 743 syscallarg(int) mode; 744 } */ *uap; 745 { 746 struct open_args /* { 747 syscallarg(char *) path; 748 syscallarg(int) flags; 749 syscallarg(int) mode; 750 } */ nuap; 751 752 SCARG(&nuap, path) = SCARG(uap, path); 753 SCARG(&nuap, mode) = SCARG(uap, mode); 754 SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC; 755 return (open(td, &nuap)); 756 } 757 #endif /* COMPAT_43 */ 758 759 /* 760 * Create a special file. 761 */ 762 #ifndef _SYS_SYSPROTO_H_ 763 struct mknod_args { 764 char *path; 765 int mode; 766 int dev; 767 }; 768 #endif 769 /* ARGSUSED */ 770 int 771 mknod(td, uap) 772 struct thread *td; 773 register struct mknod_args /* { 774 syscallarg(char *) path; 775 syscallarg(int) mode; 776 syscallarg(int) dev; 777 } */ *uap; 778 { 779 struct vnode *vp; 780 struct mount *mp; 781 struct vattr vattr; 782 int error; 783 int whiteout = 0; 784 struct nameidata nd; 785 786 switch (SCARG(uap, mode) & S_IFMT) { 787 case S_IFCHR: 788 case S_IFBLK: 789 error = suser(td); 790 break; 791 default: 792 error = suser_cred(td->td_ucred, PRISON_ROOT); 793 break; 794 } 795 if (error) 796 return (error); 797 restart: 798 bwillwrite(); 799 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), td); 800 if ((error = namei(&nd)) != 0) 801 return (error); 802 vp = nd.ni_vp; 803 if (vp != NULL) { 804 vrele(vp); 805 error = EEXIST; 806 } else { 807 VATTR_NULL(&vattr); 808 FILEDESC_LOCK(td->td_proc->p_fd); 809 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ td->td_proc->p_fd->fd_cmask; 810 FILEDESC_UNLOCK(td->td_proc->p_fd); 811 vattr.va_rdev = SCARG(uap, dev); 812 whiteout = 0; 813 814 switch (SCARG(uap, mode) & S_IFMT) { 815 case S_IFMT: /* used by badsect to flag bad sectors */ 816 vattr.va_type = VBAD; 817 break; 818 case S_IFCHR: 819 vattr.va_type = VCHR; 820 break; 821 case S_IFBLK: 822 vattr.va_type = VBLK; 823 break; 824 case S_IFWHT: 825 whiteout = 1; 826 break; 827 default: 828 error = EINVAL; 829 break; 830 } 831 } 832 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 833 NDFREE(&nd, NDF_ONLY_PNBUF); 834 vput(nd.ni_dvp); 835 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 836 return (error); 837 goto restart; 838 } 839 if (!error) { 840 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); 841 if (whiteout) 842 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE); 843 else { 844 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, 845 &nd.ni_cnd, &vattr); 846 if (error == 0) 847 vput(nd.ni_vp); 848 } 849 } 850 NDFREE(&nd, NDF_ONLY_PNBUF); 851 vput(nd.ni_dvp); 852 vn_finished_write(mp); 853 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mknod"); 854 ASSERT_VOP_UNLOCKED(nd.ni_vp, "mknod"); 855 return (error); 856 } 857 858 /* 859 * Create a named pipe. 860 */ 861 #ifndef _SYS_SYSPROTO_H_ 862 struct mkfifo_args { 863 char *path; 864 int mode; 865 }; 866 #endif 867 /* ARGSUSED */ 868 int 869 mkfifo(td, uap) 870 struct thread *td; 871 register struct mkfifo_args /* { 872 syscallarg(char *) path; 873 syscallarg(int) mode; 874 } */ *uap; 875 { 876 struct mount *mp; 877 struct vattr vattr; 878 int error; 879 struct nameidata nd; 880 881 restart: 882 bwillwrite(); 883 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), td); 884 if ((error = namei(&nd)) != 0) 885 return (error); 886 if (nd.ni_vp != NULL) { 887 NDFREE(&nd, NDF_ONLY_PNBUF); 888 vrele(nd.ni_vp); 889 vput(nd.ni_dvp); 890 return (EEXIST); 891 } 892 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 893 NDFREE(&nd, NDF_ONLY_PNBUF); 894 vput(nd.ni_dvp); 895 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 896 return (error); 897 goto restart; 898 } 899 VATTR_NULL(&vattr); 900 vattr.va_type = VFIFO; 901 FILEDESC_LOCK(td->td_proc->p_fd); 902 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ td->td_proc->p_fd->fd_cmask; 903 FILEDESC_UNLOCK(td->td_proc->p_fd); 904 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); 905 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 906 if (error == 0) 907 vput(nd.ni_vp); 908 NDFREE(&nd, NDF_ONLY_PNBUF); 909 vput(nd.ni_dvp); 910 vn_finished_write(mp); 911 return (error); 912 } 913 914 /* 915 * Make a hard file link. 916 */ 917 #ifndef _SYS_SYSPROTO_H_ 918 struct link_args { 919 char *path; 920 char *link; 921 }; 922 #endif 923 /* ARGSUSED */ 924 int 925 link(td, uap) 926 struct thread *td; 927 register struct link_args /* { 928 syscallarg(char *) path; 929 syscallarg(char *) link; 930 } */ *uap; 931 { 932 struct vnode *vp; 933 struct mount *mp; 934 struct nameidata nd; 935 int error; 936 937 bwillwrite(); 938 NDINIT(&nd, LOOKUP, FOLLOW|NOOBJ, UIO_USERSPACE, SCARG(uap, path), td); 939 if ((error = namei(&nd)) != 0) 940 return (error); 941 NDFREE(&nd, NDF_ONLY_PNBUF); 942 vp = nd.ni_vp; 943 if (vp->v_type == VDIR) { 944 vrele(vp); 945 return (EPERM); /* POSIX */ 946 } 947 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) { 948 vrele(vp); 949 return (error); 950 } 951 NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), td); 952 if ((error = namei(&nd)) == 0) { 953 if (nd.ni_vp != NULL) { 954 vrele(nd.ni_vp); 955 error = EEXIST; 956 } else { 957 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); 958 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 959 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); 960 } 961 NDFREE(&nd, NDF_ONLY_PNBUF); 962 vput(nd.ni_dvp); 963 } 964 vrele(vp); 965 vn_finished_write(mp); 966 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "link"); 967 ASSERT_VOP_UNLOCKED(nd.ni_vp, "link"); 968 return (error); 969 } 970 971 /* 972 * Make a symbolic link. 973 */ 974 #ifndef _SYS_SYSPROTO_H_ 975 struct symlink_args { 976 char *path; 977 char *link; 978 }; 979 #endif 980 /* ARGSUSED */ 981 int 982 symlink(td, uap) 983 struct thread *td; 984 register struct symlink_args /* { 985 syscallarg(char *) path; 986 syscallarg(char *) link; 987 } */ *uap; 988 { 989 struct mount *mp; 990 struct vattr vattr; 991 char *path; 992 int error; 993 struct nameidata nd; 994 995 path = uma_zalloc(namei_zone, M_WAITOK); 996 if ((error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL)) != 0) 997 goto out; 998 restart: 999 bwillwrite(); 1000 NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), td); 1001 if ((error = namei(&nd)) != 0) 1002 goto out; 1003 if (nd.ni_vp) { 1004 NDFREE(&nd, NDF_ONLY_PNBUF); 1005 vrele(nd.ni_vp); 1006 vput(nd.ni_dvp); 1007 error = EEXIST; 1008 goto out; 1009 } 1010 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1011 NDFREE(&nd, NDF_ONLY_PNBUF); 1012 vput(nd.ni_dvp); 1013 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 1014 return (error); 1015 goto restart; 1016 } 1017 VATTR_NULL(&vattr); 1018 FILEDESC_LOCK(td->td_proc->p_fd); 1019 vattr.va_mode = ACCESSPERMS &~ td->td_proc->p_fd->fd_cmask; 1020 FILEDESC_UNLOCK(td->td_proc->p_fd); 1021 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); 1022 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path); 1023 NDFREE(&nd, NDF_ONLY_PNBUF); 1024 if (error == 0) 1025 vput(nd.ni_vp); 1026 vput(nd.ni_dvp); 1027 vn_finished_write(mp); 1028 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "symlink"); 1029 ASSERT_VOP_UNLOCKED(nd.ni_vp, "symlink"); 1030 out: 1031 uma_zfree(namei_zone, path); 1032 return (error); 1033 } 1034 1035 /* 1036 * Delete a whiteout from the filesystem. 1037 */ 1038 /* ARGSUSED */ 1039 int 1040 undelete(td, uap) 1041 struct thread *td; 1042 register struct undelete_args /* { 1043 syscallarg(char *) path; 1044 } */ *uap; 1045 { 1046 int error; 1047 struct mount *mp; 1048 struct nameidata nd; 1049 1050 restart: 1051 bwillwrite(); 1052 NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE, 1053 SCARG(uap, path), td); 1054 error = namei(&nd); 1055 if (error) 1056 return (error); 1057 1058 if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) { 1059 NDFREE(&nd, NDF_ONLY_PNBUF); 1060 if (nd.ni_vp) 1061 vrele(nd.ni_vp); 1062 vput(nd.ni_dvp); 1063 return (EEXIST); 1064 } 1065 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1066 NDFREE(&nd, NDF_ONLY_PNBUF); 1067 vput(nd.ni_dvp); 1068 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 1069 return (error); 1070 goto restart; 1071 } 1072 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); 1073 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE); 1074 NDFREE(&nd, NDF_ONLY_PNBUF); 1075 vput(nd.ni_dvp); 1076 vn_finished_write(mp); 1077 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "undelete"); 1078 ASSERT_VOP_UNLOCKED(nd.ni_vp, "undelete"); 1079 return (error); 1080 } 1081 1082 /* 1083 * Delete a name from the filesystem. 1084 */ 1085 #ifndef _SYS_SYSPROTO_H_ 1086 struct unlink_args { 1087 char *path; 1088 }; 1089 #endif 1090 /* ARGSUSED */ 1091 int 1092 unlink(td, uap) 1093 struct thread *td; 1094 struct unlink_args /* { 1095 syscallarg(char *) path; 1096 } */ *uap; 1097 { 1098 struct mount *mp; 1099 struct vnode *vp; 1100 int error; 1101 struct nameidata nd; 1102 1103 restart: 1104 bwillwrite(); 1105 NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), td); 1106 if ((error = namei(&nd)) != 0) 1107 return (error); 1108 vp = nd.ni_vp; 1109 if (vp->v_type == VDIR) 1110 error = EPERM; /* POSIX */ 1111 else { 1112 /* 1113 * The root of a mounted filesystem cannot be deleted. 1114 * 1115 * XXX: can this only be a VDIR case? 1116 */ 1117 if (vp->v_flag & VROOT) 1118 error = EBUSY; 1119 } 1120 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1121 NDFREE(&nd, NDF_ONLY_PNBUF); 1122 vrele(vp); 1123 vput(nd.ni_dvp); 1124 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 1125 return (error); 1126 goto restart; 1127 } 1128 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 1129 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 1130 if (!error) { 1131 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); 1132 error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd); 1133 } 1134 NDFREE(&nd, NDF_ONLY_PNBUF); 1135 vput(nd.ni_dvp); 1136 vput(vp); 1137 vn_finished_write(mp); 1138 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "unlink"); 1139 ASSERT_VOP_UNLOCKED(nd.ni_vp, "unlink"); 1140 return (error); 1141 } 1142 1143 /* 1144 * Reposition read/write file offset. 1145 */ 1146 #ifndef _SYS_SYSPROTO_H_ 1147 struct lseek_args { 1148 int fd; 1149 int pad; 1150 off_t offset; 1151 int whence; 1152 }; 1153 #endif 1154 int 1155 lseek(td, uap) 1156 struct thread *td; 1157 register struct lseek_args /* { 1158 syscallarg(int) fd; 1159 syscallarg(int) pad; 1160 syscallarg(off_t) offset; 1161 syscallarg(int) whence; 1162 } */ *uap; 1163 { 1164 struct ucred *cred = td->td_ucred; 1165 struct file *fp; 1166 struct vnode *vp; 1167 struct vattr vattr; 1168 off_t offset; 1169 int error, noneg; 1170 1171 if ((error = fget(td, uap->fd, &fp)) != 0) 1172 return (error); 1173 if (fp->f_type != DTYPE_VNODE) { 1174 fdrop(fp, td); 1175 return (ESPIPE); 1176 } 1177 vp = (struct vnode *)fp->f_data; 1178 noneg = (vp->v_type != VCHR); 1179 offset = SCARG(uap, offset); 1180 switch (SCARG(uap, whence)) { 1181 case L_INCR: 1182 if (noneg && 1183 (fp->f_offset < 0 || 1184 (offset > 0 && fp->f_offset > OFF_MAX - offset))) 1185 return (EOVERFLOW); 1186 offset += fp->f_offset; 1187 break; 1188 case L_XTND: 1189 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 1190 error = VOP_GETATTR(vp, &vattr, cred, td); 1191 VOP_UNLOCK(vp, 0, td); 1192 if (error) 1193 return (error); 1194 if (noneg && 1195 (vattr.va_size > OFF_MAX || 1196 (offset > 0 && vattr.va_size > OFF_MAX - offset))) 1197 return (EOVERFLOW); 1198 offset += vattr.va_size; 1199 break; 1200 case L_SET: 1201 break; 1202 default: 1203 fdrop(fp, td); 1204 return (EINVAL); 1205 } 1206 if (noneg && offset < 0) 1207 return (EINVAL); 1208 fp->f_offset = offset; 1209 *(off_t *)(td->td_retval) = fp->f_offset; 1210 fdrop(fp, td); 1211 return (0); 1212 } 1213 1214 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1215 /* 1216 * Reposition read/write file offset. 1217 */ 1218 #ifndef _SYS_SYSPROTO_H_ 1219 struct olseek_args { 1220 int fd; 1221 long offset; 1222 int whence; 1223 }; 1224 #endif 1225 int 1226 olseek(td, uap) 1227 struct thread *td; 1228 register struct olseek_args /* { 1229 syscallarg(int) fd; 1230 syscallarg(long) offset; 1231 syscallarg(int) whence; 1232 } */ *uap; 1233 { 1234 struct lseek_args /* { 1235 syscallarg(int) fd; 1236 syscallarg(int) pad; 1237 syscallarg(off_t) offset; 1238 syscallarg(int) whence; 1239 } */ nuap; 1240 int error; 1241 1242 SCARG(&nuap, fd) = SCARG(uap, fd); 1243 SCARG(&nuap, offset) = SCARG(uap, offset); 1244 SCARG(&nuap, whence) = SCARG(uap, whence); 1245 error = lseek(td, &nuap); 1246 return (error); 1247 } 1248 #endif /* COMPAT_43 */ 1249 1250 /* 1251 * Check access permissions using passed credentials. 1252 */ 1253 static int 1254 vn_access(vp, user_flags, cred, td) 1255 struct vnode *vp; 1256 int user_flags; 1257 struct ucred *cred; 1258 struct thread *td; 1259 { 1260 int error, flags; 1261 1262 /* Flags == 0 means only check for existence. */ 1263 error = 0; 1264 if (user_flags) { 1265 flags = 0; 1266 if (user_flags & R_OK) 1267 flags |= VREAD; 1268 if (user_flags & W_OK) 1269 flags |= VWRITE; 1270 if (user_flags & X_OK) 1271 flags |= VEXEC; 1272 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0) 1273 error = VOP_ACCESS(vp, flags, cred, td); 1274 } 1275 return (error); 1276 } 1277 1278 /* 1279 * Check access permissions using "real" credentials. 1280 */ 1281 #ifndef _SYS_SYSPROTO_H_ 1282 struct access_args { 1283 char *path; 1284 int flags; 1285 }; 1286 #endif 1287 int 1288 access(td, uap) 1289 struct thread *td; 1290 register struct access_args /* { 1291 syscallarg(char *) path; 1292 syscallarg(int) flags; 1293 } */ *uap; 1294 { 1295 struct ucred *cred, *tmpcred; 1296 register struct vnode *vp; 1297 int error; 1298 struct nameidata nd; 1299 1300 /* 1301 * Create and modify a temporary credential instead of one that 1302 * is potentially shared. This could also mess up socket 1303 * buffer accounting which can run in an interrupt context. 1304 * 1305 * XXX - Depending on how "threads" are finally implemented, it 1306 * may be better to explicitly pass the credential to namei() 1307 * rather than to modify the potentially shared process structure. 1308 */ 1309 cred = td->td_ucred; 1310 tmpcred = crdup(cred); 1311 tmpcred->cr_uid = cred->cr_ruid; 1312 tmpcred->cr_groups[0] = cred->cr_rgid; 1313 td->td_ucred = tmpcred; 1314 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1315 SCARG(uap, path), td); 1316 if ((error = namei(&nd)) != 0) 1317 goto out1; 1318 vp = nd.ni_vp; 1319 1320 error = vn_access(vp, SCARG(uap, flags), tmpcred, td); 1321 NDFREE(&nd, NDF_ONLY_PNBUF); 1322 vput(vp); 1323 out1: 1324 td->td_ucred = cred; 1325 crfree(tmpcred); 1326 return (error); 1327 } 1328 1329 /* 1330 * Check access permissions using "effective" credentials. 1331 */ 1332 #ifndef _SYS_SYSPROTO_H_ 1333 struct eaccess_args { 1334 char *path; 1335 int flags; 1336 }; 1337 #endif 1338 int 1339 eaccess(td, uap) 1340 struct thread *td; 1341 register struct eaccess_args /* { 1342 syscallarg(char *) path; 1343 syscallarg(int) flags; 1344 } */ *uap; 1345 { 1346 struct nameidata nd; 1347 struct vnode *vp; 1348 int error; 1349 1350 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1351 SCARG(uap, path), td); 1352 if ((error = namei(&nd)) != 0) 1353 return (error); 1354 vp = nd.ni_vp; 1355 1356 error = vn_access(vp, SCARG(uap, flags), td->td_ucred, td); 1357 NDFREE(&nd, NDF_ONLY_PNBUF); 1358 vput(vp); 1359 return (error); 1360 } 1361 1362 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1363 /* 1364 * Get file status; this version follows links. 1365 */ 1366 #ifndef _SYS_SYSPROTO_H_ 1367 struct ostat_args { 1368 char *path; 1369 struct ostat *ub; 1370 }; 1371 #endif 1372 /* ARGSUSED */ 1373 int 1374 ostat(td, uap) 1375 struct thread *td; 1376 register struct ostat_args /* { 1377 syscallarg(char *) path; 1378 syscallarg(struct ostat *) ub; 1379 } */ *uap; 1380 { 1381 struct stat sb; 1382 struct ostat osb; 1383 int error; 1384 struct nameidata nd; 1385 1386 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1387 SCARG(uap, path), td); 1388 if ((error = namei(&nd)) != 0) 1389 return (error); 1390 NDFREE(&nd, NDF_ONLY_PNBUF); 1391 error = vn_stat(nd.ni_vp, &sb, td); 1392 vput(nd.ni_vp); 1393 if (error) 1394 return (error); 1395 cvtstat(&sb, &osb); 1396 error = copyout(&osb, SCARG(uap, ub), sizeof (osb)); 1397 return (error); 1398 } 1399 1400 /* 1401 * Get file status; this version does not follow links. 1402 */ 1403 #ifndef _SYS_SYSPROTO_H_ 1404 struct olstat_args { 1405 char *path; 1406 struct ostat *ub; 1407 }; 1408 #endif 1409 /* ARGSUSED */ 1410 int 1411 olstat(td, uap) 1412 struct thread *td; 1413 register struct olstat_args /* { 1414 syscallarg(char *) path; 1415 syscallarg(struct ostat *) ub; 1416 } */ *uap; 1417 { 1418 struct vnode *vp; 1419 struct stat sb; 1420 struct ostat osb; 1421 int error; 1422 struct nameidata nd; 1423 1424 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1425 SCARG(uap, path), td); 1426 if ((error = namei(&nd)) != 0) 1427 return (error); 1428 vp = nd.ni_vp; 1429 error = vn_stat(vp, &sb, td); 1430 NDFREE(&nd, NDF_ONLY_PNBUF); 1431 vput(vp); 1432 if (error) 1433 return (error); 1434 cvtstat(&sb, &osb); 1435 error = copyout(&osb, SCARG(uap, ub), sizeof (osb)); 1436 return (error); 1437 } 1438 1439 /* 1440 * Convert from an old to a new stat structure. 1441 */ 1442 void 1443 cvtstat(st, ost) 1444 struct stat *st; 1445 struct ostat *ost; 1446 { 1447 1448 ost->st_dev = st->st_dev; 1449 ost->st_ino = st->st_ino; 1450 ost->st_mode = st->st_mode; 1451 ost->st_nlink = st->st_nlink; 1452 ost->st_uid = st->st_uid; 1453 ost->st_gid = st->st_gid; 1454 ost->st_rdev = st->st_rdev; 1455 if (st->st_size < (quad_t)1 << 32) 1456 ost->st_size = st->st_size; 1457 else 1458 ost->st_size = -2; 1459 ost->st_atime = st->st_atime; 1460 ost->st_mtime = st->st_mtime; 1461 ost->st_ctime = st->st_ctime; 1462 ost->st_blksize = st->st_blksize; 1463 ost->st_blocks = st->st_blocks; 1464 ost->st_flags = st->st_flags; 1465 ost->st_gen = st->st_gen; 1466 } 1467 #endif /* COMPAT_43 || COMPAT_SUNOS */ 1468 1469 /* 1470 * Get file status; this version follows links. 1471 */ 1472 #ifndef _SYS_SYSPROTO_H_ 1473 struct stat_args { 1474 char *path; 1475 struct stat *ub; 1476 }; 1477 #endif 1478 /* ARGSUSED */ 1479 int 1480 stat(td, uap) 1481 struct thread *td; 1482 register struct stat_args /* { 1483 syscallarg(char *) path; 1484 syscallarg(struct stat *) ub; 1485 } */ *uap; 1486 { 1487 struct stat sb; 1488 int error; 1489 struct nameidata nd; 1490 1491 #ifdef LOOKUP_SHARED 1492 NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | NOOBJ, 1493 UIO_USERSPACE, SCARG(uap, path), td); 1494 #else 1495 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1496 SCARG(uap, path), td); 1497 #endif 1498 if ((error = namei(&nd)) != 0) 1499 return (error); 1500 error = vn_stat(nd.ni_vp, &sb, td); 1501 NDFREE(&nd, NDF_ONLY_PNBUF); 1502 vput(nd.ni_vp); 1503 if (error) 1504 return (error); 1505 error = copyout(&sb, SCARG(uap, ub), sizeof (sb)); 1506 return (error); 1507 } 1508 1509 /* 1510 * Get file status; this version does not follow links. 1511 */ 1512 #ifndef _SYS_SYSPROTO_H_ 1513 struct lstat_args { 1514 char *path; 1515 struct stat *ub; 1516 }; 1517 #endif 1518 /* ARGSUSED */ 1519 int 1520 lstat(td, uap) 1521 struct thread *td; 1522 register struct lstat_args /* { 1523 syscallarg(char *) path; 1524 syscallarg(struct stat *) ub; 1525 } */ *uap; 1526 { 1527 int error; 1528 struct vnode *vp; 1529 struct stat sb; 1530 struct nameidata nd; 1531 1532 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1533 SCARG(uap, path), td); 1534 if ((error = namei(&nd)) != 0) 1535 return (error); 1536 vp = nd.ni_vp; 1537 error = vn_stat(vp, &sb, td); 1538 NDFREE(&nd, NDF_ONLY_PNBUF); 1539 vput(vp); 1540 if (error) 1541 return (error); 1542 error = copyout(&sb, SCARG(uap, ub), sizeof (sb)); 1543 return (error); 1544 } 1545 1546 /* 1547 * Implementation of the NetBSD stat() function. 1548 * XXX This should probably be collapsed with the FreeBSD version, 1549 * as the differences are only due to vn_stat() clearing spares at 1550 * the end of the structures. vn_stat could be split to avoid this, 1551 * and thus collapse the following to close to zero code. 1552 */ 1553 void 1554 cvtnstat(sb, nsb) 1555 struct stat *sb; 1556 struct nstat *nsb; 1557 { 1558 bzero(nsb, sizeof *nsb); 1559 nsb->st_dev = sb->st_dev; 1560 nsb->st_ino = sb->st_ino; 1561 nsb->st_mode = sb->st_mode; 1562 nsb->st_nlink = sb->st_nlink; 1563 nsb->st_uid = sb->st_uid; 1564 nsb->st_gid = sb->st_gid; 1565 nsb->st_rdev = sb->st_rdev; 1566 nsb->st_atimespec = sb->st_atimespec; 1567 nsb->st_mtimespec = sb->st_mtimespec; 1568 nsb->st_ctimespec = sb->st_ctimespec; 1569 nsb->st_size = sb->st_size; 1570 nsb->st_blocks = sb->st_blocks; 1571 nsb->st_blksize = sb->st_blksize; 1572 nsb->st_flags = sb->st_flags; 1573 nsb->st_gen = sb->st_gen; 1574 nsb->st_createtimespec = sb->st_createtimespec; 1575 } 1576 1577 #ifndef _SYS_SYSPROTO_H_ 1578 struct nstat_args { 1579 char *path; 1580 struct nstat *ub; 1581 }; 1582 #endif 1583 /* ARGSUSED */ 1584 int 1585 nstat(td, uap) 1586 struct thread *td; 1587 register struct nstat_args /* { 1588 syscallarg(char *) path; 1589 syscallarg(struct nstat *) ub; 1590 } */ *uap; 1591 { 1592 struct stat sb; 1593 struct nstat nsb; 1594 int error; 1595 struct nameidata nd; 1596 1597 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1598 SCARG(uap, path), td); 1599 if ((error = namei(&nd)) != 0) 1600 return (error); 1601 NDFREE(&nd, NDF_ONLY_PNBUF); 1602 error = vn_stat(nd.ni_vp, &sb, td); 1603 vput(nd.ni_vp); 1604 if (error) 1605 return (error); 1606 cvtnstat(&sb, &nsb); 1607 error = copyout(&nsb, SCARG(uap, ub), sizeof (nsb)); 1608 return (error); 1609 } 1610 1611 /* 1612 * NetBSD lstat. Get file status; this version does not follow links. 1613 */ 1614 #ifndef _SYS_SYSPROTO_H_ 1615 struct lstat_args { 1616 char *path; 1617 struct stat *ub; 1618 }; 1619 #endif 1620 /* ARGSUSED */ 1621 int 1622 nlstat(td, uap) 1623 struct thread *td; 1624 register struct nlstat_args /* { 1625 syscallarg(char *) path; 1626 syscallarg(struct nstat *) ub; 1627 } */ *uap; 1628 { 1629 int error; 1630 struct vnode *vp; 1631 struct stat sb; 1632 struct nstat nsb; 1633 struct nameidata nd; 1634 1635 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1636 SCARG(uap, path), td); 1637 if ((error = namei(&nd)) != 0) 1638 return (error); 1639 vp = nd.ni_vp; 1640 NDFREE(&nd, NDF_ONLY_PNBUF); 1641 error = vn_stat(vp, &sb, td); 1642 vput(vp); 1643 if (error) 1644 return (error); 1645 cvtnstat(&sb, &nsb); 1646 error = copyout(&nsb, SCARG(uap, ub), sizeof (nsb)); 1647 return (error); 1648 } 1649 1650 /* 1651 * Get configurable pathname variables. 1652 */ 1653 #ifndef _SYS_SYSPROTO_H_ 1654 struct pathconf_args { 1655 char *path; 1656 int name; 1657 }; 1658 #endif 1659 /* ARGSUSED */ 1660 int 1661 pathconf(td, uap) 1662 struct thread *td; 1663 register struct pathconf_args /* { 1664 syscallarg(char *) path; 1665 syscallarg(int) name; 1666 } */ *uap; 1667 { 1668 int error; 1669 struct nameidata nd; 1670 1671 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1672 SCARG(uap, path), td); 1673 if ((error = namei(&nd)) != 0) 1674 return (error); 1675 NDFREE(&nd, NDF_ONLY_PNBUF); 1676 error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), td->td_retval); 1677 vput(nd.ni_vp); 1678 return (error); 1679 } 1680 1681 /* 1682 * Return target name of a symbolic link. 1683 */ 1684 #ifndef _SYS_SYSPROTO_H_ 1685 struct readlink_args { 1686 char *path; 1687 char *buf; 1688 int count; 1689 }; 1690 #endif 1691 /* ARGSUSED */ 1692 int 1693 readlink(td, uap) 1694 struct thread *td; 1695 register struct readlink_args /* { 1696 syscallarg(char *) path; 1697 syscallarg(char *) buf; 1698 syscallarg(int) count; 1699 } */ *uap; 1700 { 1701 register struct vnode *vp; 1702 struct iovec aiov; 1703 struct uio auio; 1704 int error; 1705 struct nameidata nd; 1706 1707 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1708 SCARG(uap, path), td); 1709 if ((error = namei(&nd)) != 0) 1710 return (error); 1711 NDFREE(&nd, NDF_ONLY_PNBUF); 1712 vp = nd.ni_vp; 1713 if (vp->v_type != VLNK) 1714 error = EINVAL; 1715 else { 1716 aiov.iov_base = SCARG(uap, buf); 1717 aiov.iov_len = SCARG(uap, count); 1718 auio.uio_iov = &aiov; 1719 auio.uio_iovcnt = 1; 1720 auio.uio_offset = 0; 1721 auio.uio_rw = UIO_READ; 1722 auio.uio_segflg = UIO_USERSPACE; 1723 auio.uio_td = td; 1724 auio.uio_resid = SCARG(uap, count); 1725 error = VOP_READLINK(vp, &auio, td->td_ucred); 1726 } 1727 vput(vp); 1728 td->td_retval[0] = SCARG(uap, count) - auio.uio_resid; 1729 return (error); 1730 } 1731 1732 /* 1733 * Common implementation code for chflags() and fchflags(). 1734 */ 1735 static int 1736 setfflags(td, vp, flags) 1737 struct thread *td; 1738 struct vnode *vp; 1739 int flags; 1740 { 1741 int error; 1742 struct mount *mp; 1743 struct vattr vattr; 1744 1745 /* 1746 * Prevent non-root users from setting flags on devices. When 1747 * a device is reused, users can retain ownership of the device 1748 * if they are allowed to set flags and programs assume that 1749 * chown can't fail when done as root. 1750 */ 1751 if (vp->v_type == VCHR || vp->v_type == VBLK) { 1752 error = suser_cred(td->td_ucred, PRISON_ROOT); 1753 if (error) 1754 return (error); 1755 } 1756 1757 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 1758 return (error); 1759 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 1760 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 1761 VATTR_NULL(&vattr); 1762 vattr.va_flags = flags; 1763 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); 1764 VOP_UNLOCK(vp, 0, td); 1765 vn_finished_write(mp); 1766 return (error); 1767 } 1768 1769 /* 1770 * Change flags of a file given a path name. 1771 */ 1772 #ifndef _SYS_SYSPROTO_H_ 1773 struct chflags_args { 1774 char *path; 1775 int flags; 1776 }; 1777 #endif 1778 /* ARGSUSED */ 1779 int 1780 chflags(td, uap) 1781 struct thread *td; 1782 register struct chflags_args /* { 1783 syscallarg(char *) path; 1784 syscallarg(int) flags; 1785 } */ *uap; 1786 { 1787 int error; 1788 struct nameidata nd; 1789 1790 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 1791 if ((error = namei(&nd)) != 0) 1792 return (error); 1793 NDFREE(&nd, NDF_ONLY_PNBUF); 1794 error = setfflags(td, nd.ni_vp, SCARG(uap, flags)); 1795 vrele(nd.ni_vp); 1796 return error; 1797 } 1798 1799 /* 1800 * Same as chflags() but doesn't follow symlinks. 1801 */ 1802 int 1803 lchflags(td, uap) 1804 struct thread *td; 1805 register struct lchflags_args /* { 1806 syscallarg(char *) path; 1807 syscallarg(int) flags; 1808 } */ *uap; 1809 { 1810 int error; 1811 struct nameidata nd; 1812 1813 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 1814 if ((error = namei(&nd)) != 0) 1815 return (error); 1816 NDFREE(&nd, NDF_ONLY_PNBUF); 1817 error = setfflags(td, nd.ni_vp, SCARG(uap, flags)); 1818 vrele(nd.ni_vp); 1819 return error; 1820 } 1821 1822 /* 1823 * Change flags of a file given a file descriptor. 1824 */ 1825 #ifndef _SYS_SYSPROTO_H_ 1826 struct fchflags_args { 1827 int fd; 1828 int flags; 1829 }; 1830 #endif 1831 /* ARGSUSED */ 1832 int 1833 fchflags(td, uap) 1834 struct thread *td; 1835 register struct fchflags_args /* { 1836 syscallarg(int) fd; 1837 syscallarg(int) flags; 1838 } */ *uap; 1839 { 1840 struct file *fp; 1841 int error; 1842 1843 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 1844 return (error); 1845 error = setfflags(td, (struct vnode *) fp->f_data, SCARG(uap, flags)); 1846 fdrop(fp, td); 1847 return (error); 1848 } 1849 1850 /* 1851 * Common implementation code for chmod(), lchmod() and fchmod(). 1852 */ 1853 static int 1854 setfmode(td, vp, mode) 1855 struct thread *td; 1856 struct vnode *vp; 1857 int mode; 1858 { 1859 int error; 1860 struct mount *mp; 1861 struct vattr vattr; 1862 1863 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 1864 return (error); 1865 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 1866 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 1867 VATTR_NULL(&vattr); 1868 vattr.va_mode = mode & ALLPERMS; 1869 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); 1870 VOP_UNLOCK(vp, 0, td); 1871 vn_finished_write(mp); 1872 return error; 1873 } 1874 1875 /* 1876 * Change mode of a file given path name. 1877 */ 1878 #ifndef _SYS_SYSPROTO_H_ 1879 struct chmod_args { 1880 char *path; 1881 int mode; 1882 }; 1883 #endif 1884 /* ARGSUSED */ 1885 int 1886 chmod(td, uap) 1887 struct thread *td; 1888 register struct chmod_args /* { 1889 syscallarg(char *) path; 1890 syscallarg(int) mode; 1891 } */ *uap; 1892 { 1893 int error; 1894 struct nameidata nd; 1895 1896 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 1897 if ((error = namei(&nd)) != 0) 1898 return (error); 1899 NDFREE(&nd, NDF_ONLY_PNBUF); 1900 error = setfmode(td, nd.ni_vp, SCARG(uap, mode)); 1901 vrele(nd.ni_vp); 1902 return error; 1903 } 1904 1905 /* 1906 * Change mode of a file given path name (don't follow links.) 1907 */ 1908 #ifndef _SYS_SYSPROTO_H_ 1909 struct lchmod_args { 1910 char *path; 1911 int mode; 1912 }; 1913 #endif 1914 /* ARGSUSED */ 1915 int 1916 lchmod(td, uap) 1917 struct thread *td; 1918 register struct lchmod_args /* { 1919 syscallarg(char *) path; 1920 syscallarg(int) mode; 1921 } */ *uap; 1922 { 1923 int error; 1924 struct nameidata nd; 1925 1926 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 1927 if ((error = namei(&nd)) != 0) 1928 return (error); 1929 NDFREE(&nd, NDF_ONLY_PNBUF); 1930 error = setfmode(td, nd.ni_vp, SCARG(uap, mode)); 1931 vrele(nd.ni_vp); 1932 return error; 1933 } 1934 1935 /* 1936 * Change mode of a file given a file descriptor. 1937 */ 1938 #ifndef _SYS_SYSPROTO_H_ 1939 struct fchmod_args { 1940 int fd; 1941 int mode; 1942 }; 1943 #endif 1944 /* ARGSUSED */ 1945 int 1946 fchmod(td, uap) 1947 struct thread *td; 1948 register struct fchmod_args /* { 1949 syscallarg(int) fd; 1950 syscallarg(int) mode; 1951 } */ *uap; 1952 { 1953 struct file *fp; 1954 struct vnode *vp; 1955 int error; 1956 1957 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 1958 return (error); 1959 vp = (struct vnode *)fp->f_data; 1960 error = setfmode(td, (struct vnode *)fp->f_data, SCARG(uap, mode)); 1961 fdrop(fp, td); 1962 return (error); 1963 } 1964 1965 /* 1966 * Common implementation for chown(), lchown(), and fchown() 1967 */ 1968 static int 1969 setfown(td, vp, uid, gid) 1970 struct thread *td; 1971 struct vnode *vp; 1972 uid_t uid; 1973 gid_t gid; 1974 { 1975 int error; 1976 struct mount *mp; 1977 struct vattr vattr; 1978 1979 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 1980 return (error); 1981 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 1982 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 1983 VATTR_NULL(&vattr); 1984 vattr.va_uid = uid; 1985 vattr.va_gid = gid; 1986 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); 1987 VOP_UNLOCK(vp, 0, td); 1988 vn_finished_write(mp); 1989 return error; 1990 } 1991 1992 /* 1993 * Set ownership given a path name. 1994 */ 1995 #ifndef _SYS_SYSPROTO_H_ 1996 struct chown_args { 1997 char *path; 1998 int uid; 1999 int gid; 2000 }; 2001 #endif 2002 /* ARGSUSED */ 2003 int 2004 chown(td, uap) 2005 struct thread *td; 2006 register struct chown_args /* { 2007 syscallarg(char *) path; 2008 syscallarg(int) uid; 2009 syscallarg(int) gid; 2010 } */ *uap; 2011 { 2012 int error; 2013 struct nameidata nd; 2014 2015 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 2016 if ((error = namei(&nd)) != 0) 2017 return (error); 2018 NDFREE(&nd, NDF_ONLY_PNBUF); 2019 error = setfown(td, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid)); 2020 vrele(nd.ni_vp); 2021 return (error); 2022 } 2023 2024 /* 2025 * Set ownership given a path name, do not cross symlinks. 2026 */ 2027 #ifndef _SYS_SYSPROTO_H_ 2028 struct lchown_args { 2029 char *path; 2030 int uid; 2031 int gid; 2032 }; 2033 #endif 2034 /* ARGSUSED */ 2035 int 2036 lchown(td, uap) 2037 struct thread *td; 2038 register struct lchown_args /* { 2039 syscallarg(char *) path; 2040 syscallarg(int) uid; 2041 syscallarg(int) gid; 2042 } */ *uap; 2043 { 2044 int error; 2045 struct nameidata nd; 2046 2047 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 2048 if ((error = namei(&nd)) != 0) 2049 return (error); 2050 NDFREE(&nd, NDF_ONLY_PNBUF); 2051 error = setfown(td, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid)); 2052 vrele(nd.ni_vp); 2053 return (error); 2054 } 2055 2056 /* 2057 * Set ownership given a file descriptor. 2058 */ 2059 #ifndef _SYS_SYSPROTO_H_ 2060 struct fchown_args { 2061 int fd; 2062 int uid; 2063 int gid; 2064 }; 2065 #endif 2066 /* ARGSUSED */ 2067 int 2068 fchown(td, uap) 2069 struct thread *td; 2070 register struct fchown_args /* { 2071 syscallarg(int) fd; 2072 syscallarg(int) uid; 2073 syscallarg(int) gid; 2074 } */ *uap; 2075 { 2076 struct file *fp; 2077 struct vnode *vp; 2078 int error; 2079 2080 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 2081 return (error); 2082 vp = (struct vnode *)fp->f_data; 2083 error = setfown(td, (struct vnode *)fp->f_data, 2084 SCARG(uap, uid), SCARG(uap, gid)); 2085 fdrop(fp, td); 2086 return (error); 2087 } 2088 2089 /* 2090 * Common implementation code for utimes(), lutimes(), and futimes(). 2091 */ 2092 static int 2093 getutimes(usrtvp, tsp) 2094 const struct timeval *usrtvp; 2095 struct timespec *tsp; 2096 { 2097 struct timeval tv[2]; 2098 int error; 2099 2100 if (usrtvp == NULL) { 2101 microtime(&tv[0]); 2102 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]); 2103 tsp[1] = tsp[0]; 2104 } else { 2105 if ((error = copyin(usrtvp, tv, sizeof (tv))) != 0) 2106 return (error); 2107 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]); 2108 TIMEVAL_TO_TIMESPEC(&tv[1], &tsp[1]); 2109 } 2110 return 0; 2111 } 2112 2113 /* 2114 * Common implementation code for utimes(), lutimes(), and futimes(). 2115 */ 2116 static int 2117 setutimes(td, vp, ts, nullflag) 2118 struct thread *td; 2119 struct vnode *vp; 2120 const struct timespec *ts; 2121 int nullflag; 2122 { 2123 int error; 2124 struct mount *mp; 2125 struct vattr vattr; 2126 2127 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 2128 return (error); 2129 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 2130 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2131 VATTR_NULL(&vattr); 2132 vattr.va_atime = ts[0]; 2133 vattr.va_mtime = ts[1]; 2134 if (nullflag) 2135 vattr.va_vaflags |= VA_UTIMES_NULL; 2136 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); 2137 VOP_UNLOCK(vp, 0, td); 2138 vn_finished_write(mp); 2139 return error; 2140 } 2141 2142 /* 2143 * Set the access and modification times of a file. 2144 */ 2145 #ifndef _SYS_SYSPROTO_H_ 2146 struct utimes_args { 2147 char *path; 2148 struct timeval *tptr; 2149 }; 2150 #endif 2151 /* ARGSUSED */ 2152 int 2153 utimes(td, uap) 2154 struct thread *td; 2155 register struct utimes_args /* { 2156 syscallarg(char *) path; 2157 syscallarg(struct timeval *) tptr; 2158 } */ *uap; 2159 { 2160 struct timespec ts[2]; 2161 struct timeval *usrtvp; 2162 int error; 2163 struct nameidata nd; 2164 2165 usrtvp = SCARG(uap, tptr); 2166 if ((error = getutimes(usrtvp, ts)) != 0) 2167 return (error); 2168 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 2169 if ((error = namei(&nd)) != 0) 2170 return (error); 2171 NDFREE(&nd, NDF_ONLY_PNBUF); 2172 error = setutimes(td, nd.ni_vp, ts, usrtvp == NULL); 2173 vrele(nd.ni_vp); 2174 return (error); 2175 } 2176 2177 /* 2178 * Set the access and modification times of a file. 2179 */ 2180 #ifndef _SYS_SYSPROTO_H_ 2181 struct lutimes_args { 2182 char *path; 2183 struct timeval *tptr; 2184 }; 2185 #endif 2186 /* ARGSUSED */ 2187 int 2188 lutimes(td, uap) 2189 struct thread *td; 2190 register struct lutimes_args /* { 2191 syscallarg(char *) path; 2192 syscallarg(struct timeval *) tptr; 2193 } */ *uap; 2194 { 2195 struct timespec ts[2]; 2196 struct timeval *usrtvp; 2197 int error; 2198 struct nameidata nd; 2199 2200 usrtvp = SCARG(uap, tptr); 2201 if ((error = getutimes(usrtvp, ts)) != 0) 2202 return (error); 2203 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 2204 if ((error = namei(&nd)) != 0) 2205 return (error); 2206 NDFREE(&nd, NDF_ONLY_PNBUF); 2207 error = setutimes(td, nd.ni_vp, ts, usrtvp == NULL); 2208 vrele(nd.ni_vp); 2209 return (error); 2210 } 2211 2212 /* 2213 * Set the access and modification times of a file. 2214 */ 2215 #ifndef _SYS_SYSPROTO_H_ 2216 struct futimes_args { 2217 int fd; 2218 struct timeval *tptr; 2219 }; 2220 #endif 2221 /* ARGSUSED */ 2222 int 2223 futimes(td, uap) 2224 struct thread *td; 2225 register struct futimes_args /* { 2226 syscallarg(int ) fd; 2227 syscallarg(struct timeval *) tptr; 2228 } */ *uap; 2229 { 2230 struct timespec ts[2]; 2231 struct file *fp; 2232 struct timeval *usrtvp; 2233 int error; 2234 2235 usrtvp = SCARG(uap, tptr); 2236 if ((error = getutimes(usrtvp, ts)) != 0) 2237 return (error); 2238 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 2239 return (error); 2240 error = setutimes(td, (struct vnode *)fp->f_data, ts, usrtvp == NULL); 2241 fdrop(fp, td); 2242 return (error); 2243 } 2244 2245 /* 2246 * Truncate a file given its path name. 2247 */ 2248 #ifndef _SYS_SYSPROTO_H_ 2249 struct truncate_args { 2250 char *path; 2251 int pad; 2252 off_t length; 2253 }; 2254 #endif 2255 /* ARGSUSED */ 2256 int 2257 truncate(td, uap) 2258 struct thread *td; 2259 register struct truncate_args /* { 2260 syscallarg(char *) path; 2261 syscallarg(int) pad; 2262 syscallarg(off_t) length; 2263 } */ *uap; 2264 { 2265 struct mount *mp; 2266 struct vnode *vp; 2267 struct vattr vattr; 2268 int error; 2269 struct nameidata nd; 2270 2271 if (uap->length < 0) 2272 return(EINVAL); 2273 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 2274 if ((error = namei(&nd)) != 0) 2275 return (error); 2276 vp = nd.ni_vp; 2277 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) { 2278 vrele(vp); 2279 return (error); 2280 } 2281 NDFREE(&nd, NDF_ONLY_PNBUF); 2282 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 2283 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2284 if (vp->v_type == VDIR) 2285 error = EISDIR; 2286 else if ((error = vn_writechk(vp)) == 0 && 2287 (error = VOP_ACCESS(vp, VWRITE, td->td_ucred, td)) == 0) { 2288 VATTR_NULL(&vattr); 2289 vattr.va_size = SCARG(uap, length); 2290 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); 2291 } 2292 vput(vp); 2293 vn_finished_write(mp); 2294 return (error); 2295 } 2296 2297 /* 2298 * Truncate a file given a file descriptor. 2299 */ 2300 #ifndef _SYS_SYSPROTO_H_ 2301 struct ftruncate_args { 2302 int fd; 2303 int pad; 2304 off_t length; 2305 }; 2306 #endif 2307 /* ARGSUSED */ 2308 int 2309 ftruncate(td, uap) 2310 struct thread *td; 2311 register struct ftruncate_args /* { 2312 syscallarg(int) fd; 2313 syscallarg(int) pad; 2314 syscallarg(off_t) length; 2315 } */ *uap; 2316 { 2317 struct mount *mp; 2318 struct vattr vattr; 2319 struct vnode *vp; 2320 struct file *fp; 2321 int error; 2322 2323 if (uap->length < 0) 2324 return(EINVAL); 2325 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 2326 return (error); 2327 if ((fp->f_flag & FWRITE) == 0) { 2328 fdrop(fp, td); 2329 return (EINVAL); 2330 } 2331 vp = (struct vnode *)fp->f_data; 2332 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) { 2333 fdrop(fp, td); 2334 return (error); 2335 } 2336 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 2337 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2338 if (vp->v_type == VDIR) 2339 error = EISDIR; 2340 else if ((error = vn_writechk(vp)) == 0) { 2341 VATTR_NULL(&vattr); 2342 vattr.va_size = SCARG(uap, length); 2343 error = VOP_SETATTR(vp, &vattr, fp->f_cred, td); 2344 } 2345 VOP_UNLOCK(vp, 0, td); 2346 vn_finished_write(mp); 2347 fdrop(fp, td); 2348 return (error); 2349 } 2350 2351 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 2352 /* 2353 * Truncate a file given its path name. 2354 */ 2355 #ifndef _SYS_SYSPROTO_H_ 2356 struct otruncate_args { 2357 char *path; 2358 long length; 2359 }; 2360 #endif 2361 /* ARGSUSED */ 2362 int 2363 otruncate(td, uap) 2364 struct thread *td; 2365 register struct otruncate_args /* { 2366 syscallarg(char *) path; 2367 syscallarg(long) length; 2368 } */ *uap; 2369 { 2370 struct truncate_args /* { 2371 syscallarg(char *) path; 2372 syscallarg(int) pad; 2373 syscallarg(off_t) length; 2374 } */ nuap; 2375 2376 SCARG(&nuap, path) = SCARG(uap, path); 2377 SCARG(&nuap, length) = SCARG(uap, length); 2378 return (truncate(td, &nuap)); 2379 } 2380 2381 /* 2382 * Truncate a file given a file descriptor. 2383 */ 2384 #ifndef _SYS_SYSPROTO_H_ 2385 struct oftruncate_args { 2386 int fd; 2387 long length; 2388 }; 2389 #endif 2390 /* ARGSUSED */ 2391 int 2392 oftruncate(td, uap) 2393 struct thread *td; 2394 register struct oftruncate_args /* { 2395 syscallarg(int) fd; 2396 syscallarg(long) length; 2397 } */ *uap; 2398 { 2399 struct ftruncate_args /* { 2400 syscallarg(int) fd; 2401 syscallarg(int) pad; 2402 syscallarg(off_t) length; 2403 } */ nuap; 2404 2405 SCARG(&nuap, fd) = SCARG(uap, fd); 2406 SCARG(&nuap, length) = SCARG(uap, length); 2407 return (ftruncate(td, &nuap)); 2408 } 2409 #endif /* COMPAT_43 || COMPAT_SUNOS */ 2410 2411 /* 2412 * Sync an open file. 2413 */ 2414 #ifndef _SYS_SYSPROTO_H_ 2415 struct fsync_args { 2416 int fd; 2417 }; 2418 #endif 2419 /* ARGSUSED */ 2420 int 2421 fsync(td, uap) 2422 struct thread *td; 2423 struct fsync_args /* { 2424 syscallarg(int) fd; 2425 } */ *uap; 2426 { 2427 struct vnode *vp; 2428 struct mount *mp; 2429 struct file *fp; 2430 vm_object_t obj; 2431 int error; 2432 2433 GIANT_REQUIRED; 2434 2435 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 2436 return (error); 2437 vp = (struct vnode *)fp->f_data; 2438 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) { 2439 fdrop(fp, td); 2440 return (error); 2441 } 2442 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2443 if (VOP_GETVOBJECT(vp, &obj) == 0) { 2444 vm_object_page_clean(obj, 0, 0, 0); 2445 } 2446 error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, td); 2447 if (error == 0 && vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP) 2448 && softdep_fsync_hook != NULL) 2449 error = (*softdep_fsync_hook)(vp); 2450 2451 VOP_UNLOCK(vp, 0, td); 2452 vn_finished_write(mp); 2453 fdrop(fp, td); 2454 return (error); 2455 } 2456 2457 /* 2458 * Rename files. Source and destination must either both be directories, 2459 * or both not be directories. If target is a directory, it must be empty. 2460 */ 2461 #ifndef _SYS_SYSPROTO_H_ 2462 struct rename_args { 2463 char *from; 2464 char *to; 2465 }; 2466 #endif 2467 /* ARGSUSED */ 2468 int 2469 rename(td, uap) 2470 struct thread *td; 2471 register struct rename_args /* { 2472 syscallarg(char *) from; 2473 syscallarg(char *) to; 2474 } */ *uap; 2475 { 2476 struct mount *mp; 2477 struct vnode *tvp, *fvp, *tdvp; 2478 struct nameidata fromnd, tond; 2479 int error; 2480 2481 bwillwrite(); 2482 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE, 2483 SCARG(uap, from), td); 2484 if ((error = namei(&fromnd)) != 0) 2485 return (error); 2486 fvp = fromnd.ni_vp; 2487 if ((error = vn_start_write(fvp, &mp, V_WAIT | PCATCH)) != 0) { 2488 NDFREE(&fromnd, NDF_ONLY_PNBUF); 2489 vrele(fromnd.ni_dvp); 2490 vrele(fvp); 2491 goto out1; 2492 } 2493 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | NOOBJ, 2494 UIO_USERSPACE, SCARG(uap, to), td); 2495 if (fromnd.ni_vp->v_type == VDIR) 2496 tond.ni_cnd.cn_flags |= WILLBEDIR; 2497 if ((error = namei(&tond)) != 0) { 2498 /* Translate error code for rename("dir1", "dir2/."). */ 2499 if (error == EISDIR && fvp->v_type == VDIR) 2500 error = EINVAL; 2501 NDFREE(&fromnd, NDF_ONLY_PNBUF); 2502 vrele(fromnd.ni_dvp); 2503 vrele(fvp); 2504 goto out1; 2505 } 2506 tdvp = tond.ni_dvp; 2507 tvp = tond.ni_vp; 2508 if (tvp != NULL) { 2509 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 2510 error = ENOTDIR; 2511 goto out; 2512 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 2513 error = EISDIR; 2514 goto out; 2515 } 2516 } 2517 if (fvp == tdvp) 2518 error = EINVAL; 2519 /* 2520 * If source is the same as the destination (that is the 2521 * same inode number with the same name in the same directory), 2522 * then there is nothing to do. 2523 */ 2524 if (fvp == tvp && fromnd.ni_dvp == tdvp && 2525 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen && 2526 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr, 2527 fromnd.ni_cnd.cn_namelen)) 2528 error = -1; 2529 out: 2530 if (!error) { 2531 VOP_LEASE(tdvp, td, td->td_ucred, LEASE_WRITE); 2532 if (fromnd.ni_dvp != tdvp) { 2533 VOP_LEASE(fromnd.ni_dvp, td, td->td_ucred, LEASE_WRITE); 2534 } 2535 if (tvp) { 2536 VOP_LEASE(tvp, td, td->td_ucred, LEASE_WRITE); 2537 } 2538 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, 2539 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); 2540 NDFREE(&fromnd, NDF_ONLY_PNBUF); 2541 NDFREE(&tond, NDF_ONLY_PNBUF); 2542 } else { 2543 NDFREE(&fromnd, NDF_ONLY_PNBUF); 2544 NDFREE(&tond, NDF_ONLY_PNBUF); 2545 if (tdvp == tvp) 2546 vrele(tdvp); 2547 else 2548 vput(tdvp); 2549 if (tvp) 2550 vput(tvp); 2551 vrele(fromnd.ni_dvp); 2552 vrele(fvp); 2553 } 2554 vrele(tond.ni_startdir); 2555 vn_finished_write(mp); 2556 ASSERT_VOP_UNLOCKED(fromnd.ni_dvp, "rename"); 2557 ASSERT_VOP_UNLOCKED(fromnd.ni_vp, "rename"); 2558 ASSERT_VOP_UNLOCKED(tond.ni_dvp, "rename"); 2559 ASSERT_VOP_UNLOCKED(tond.ni_vp, "rename"); 2560 out1: 2561 if (fromnd.ni_startdir) 2562 vrele(fromnd.ni_startdir); 2563 if (error == -1) 2564 return (0); 2565 return (error); 2566 } 2567 2568 /* 2569 * Make a directory file. 2570 */ 2571 #ifndef _SYS_SYSPROTO_H_ 2572 struct mkdir_args { 2573 char *path; 2574 int mode; 2575 }; 2576 #endif 2577 /* ARGSUSED */ 2578 int 2579 mkdir(td, uap) 2580 struct thread *td; 2581 register struct mkdir_args /* { 2582 syscallarg(char *) path; 2583 syscallarg(int) mode; 2584 } */ *uap; 2585 { 2586 2587 return vn_mkdir(uap->path, uap->mode, UIO_USERSPACE, td); 2588 } 2589 2590 int 2591 vn_mkdir(path, mode, segflg, td) 2592 char *path; 2593 int mode; 2594 enum uio_seg segflg; 2595 struct thread *td; 2596 { 2597 struct mount *mp; 2598 struct vnode *vp; 2599 struct vattr vattr; 2600 int error; 2601 struct nameidata nd; 2602 2603 restart: 2604 bwillwrite(); 2605 NDINIT(&nd, CREATE, LOCKPARENT, segflg, path, td); 2606 nd.ni_cnd.cn_flags |= WILLBEDIR; 2607 if ((error = namei(&nd)) != 0) 2608 return (error); 2609 vp = nd.ni_vp; 2610 if (vp != NULL) { 2611 NDFREE(&nd, NDF_ONLY_PNBUF); 2612 vrele(vp); 2613 /* 2614 * XXX namei called with LOCKPARENT but not LOCKLEAF has 2615 * the strange behaviour of leaving the vnode unlocked 2616 * if the target is the same vnode as the parent. 2617 */ 2618 if (vp == nd.ni_dvp) 2619 vrele(nd.ni_dvp); 2620 else 2621 vput(nd.ni_dvp); 2622 return (EEXIST); 2623 } 2624 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 2625 NDFREE(&nd, NDF_ONLY_PNBUF); 2626 vput(nd.ni_dvp); 2627 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 2628 return (error); 2629 goto restart; 2630 } 2631 VATTR_NULL(&vattr); 2632 vattr.va_type = VDIR; 2633 FILEDESC_LOCK(td->td_proc->p_fd); 2634 vattr.va_mode = (mode & ACCESSPERMS) &~ td->td_proc->p_fd->fd_cmask; 2635 FILEDESC_UNLOCK(td->td_proc->p_fd); 2636 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); 2637 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 2638 NDFREE(&nd, NDF_ONLY_PNBUF); 2639 vput(nd.ni_dvp); 2640 if (!error) 2641 vput(nd.ni_vp); 2642 vn_finished_write(mp); 2643 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mkdir"); 2644 ASSERT_VOP_UNLOCKED(nd.ni_vp, "mkdir"); 2645 return (error); 2646 } 2647 2648 /* 2649 * Remove a directory file. 2650 */ 2651 #ifndef _SYS_SYSPROTO_H_ 2652 struct rmdir_args { 2653 char *path; 2654 }; 2655 #endif 2656 /* ARGSUSED */ 2657 int 2658 rmdir(td, uap) 2659 struct thread *td; 2660 struct rmdir_args /* { 2661 syscallarg(char *) path; 2662 } */ *uap; 2663 { 2664 struct mount *mp; 2665 struct vnode *vp; 2666 int error; 2667 struct nameidata nd; 2668 2669 restart: 2670 bwillwrite(); 2671 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, 2672 SCARG(uap, path), td); 2673 if ((error = namei(&nd)) != 0) 2674 return (error); 2675 vp = nd.ni_vp; 2676 if (vp->v_type != VDIR) { 2677 error = ENOTDIR; 2678 goto out; 2679 } 2680 /* 2681 * No rmdir "." please. 2682 */ 2683 if (nd.ni_dvp == vp) { 2684 error = EINVAL; 2685 goto out; 2686 } 2687 /* 2688 * The root of a mounted filesystem cannot be deleted. 2689 */ 2690 if (vp->v_flag & VROOT) { 2691 error = EBUSY; 2692 goto out; 2693 } 2694 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 2695 NDFREE(&nd, NDF_ONLY_PNBUF); 2696 if (nd.ni_dvp == vp) 2697 vrele(nd.ni_dvp); 2698 else 2699 vput(nd.ni_dvp); 2700 vput(vp); 2701 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 2702 return (error); 2703 goto restart; 2704 } 2705 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); 2706 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 2707 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 2708 vn_finished_write(mp); 2709 out: 2710 NDFREE(&nd, NDF_ONLY_PNBUF); 2711 if (nd.ni_dvp == vp) 2712 vrele(nd.ni_dvp); 2713 else 2714 vput(nd.ni_dvp); 2715 vput(vp); 2716 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "rmdir"); 2717 ASSERT_VOP_UNLOCKED(nd.ni_vp, "rmdir"); 2718 return (error); 2719 } 2720 2721 #ifdef COMPAT_43 2722 /* 2723 * Read a block of directory entries in a filesystem independent format. 2724 */ 2725 #ifndef _SYS_SYSPROTO_H_ 2726 struct ogetdirentries_args { 2727 int fd; 2728 char *buf; 2729 u_int count; 2730 long *basep; 2731 }; 2732 #endif 2733 int 2734 ogetdirentries(td, uap) 2735 struct thread *td; 2736 register struct ogetdirentries_args /* { 2737 syscallarg(int) fd; 2738 syscallarg(char *) buf; 2739 syscallarg(u_int) count; 2740 syscallarg(long *) basep; 2741 } */ *uap; 2742 { 2743 struct vnode *vp; 2744 struct file *fp; 2745 struct uio auio, kuio; 2746 struct iovec aiov, kiov; 2747 struct dirent *dp, *edp; 2748 caddr_t dirbuf; 2749 int error, eofflag, readcnt; 2750 long loff; 2751 2752 /* XXX arbitrary sanity limit on `count'. */ 2753 if (SCARG(uap, count) > 64 * 1024) 2754 return (EINVAL); 2755 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 2756 return (error); 2757 if ((fp->f_flag & FREAD) == 0) { 2758 fdrop(fp, td); 2759 return (EBADF); 2760 } 2761 vp = (struct vnode *)fp->f_data; 2762 unionread: 2763 if (vp->v_type != VDIR) { 2764 fdrop(fp, td); 2765 return (EINVAL); 2766 } 2767 aiov.iov_base = SCARG(uap, buf); 2768 aiov.iov_len = SCARG(uap, count); 2769 auio.uio_iov = &aiov; 2770 auio.uio_iovcnt = 1; 2771 auio.uio_rw = UIO_READ; 2772 auio.uio_segflg = UIO_USERSPACE; 2773 auio.uio_td = td; 2774 auio.uio_resid = SCARG(uap, count); 2775 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2776 loff = auio.uio_offset = fp->f_offset; 2777 # if (BYTE_ORDER != LITTLE_ENDIAN) 2778 if (vp->v_mount->mnt_maxsymlinklen <= 0) { 2779 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, 2780 NULL, NULL); 2781 fp->f_offset = auio.uio_offset; 2782 } else 2783 # endif 2784 { 2785 kuio = auio; 2786 kuio.uio_iov = &kiov; 2787 kuio.uio_segflg = UIO_SYSSPACE; 2788 kiov.iov_len = SCARG(uap, count); 2789 MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK); 2790 kiov.iov_base = dirbuf; 2791 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag, 2792 NULL, NULL); 2793 fp->f_offset = kuio.uio_offset; 2794 if (error == 0) { 2795 readcnt = SCARG(uap, count) - kuio.uio_resid; 2796 edp = (struct dirent *)&dirbuf[readcnt]; 2797 for (dp = (struct dirent *)dirbuf; dp < edp; ) { 2798 # if (BYTE_ORDER == LITTLE_ENDIAN) 2799 /* 2800 * The expected low byte of 2801 * dp->d_namlen is our dp->d_type. 2802 * The high MBZ byte of dp->d_namlen 2803 * is our dp->d_namlen. 2804 */ 2805 dp->d_type = dp->d_namlen; 2806 dp->d_namlen = 0; 2807 # else 2808 /* 2809 * The dp->d_type is the high byte 2810 * of the expected dp->d_namlen, 2811 * so must be zero'ed. 2812 */ 2813 dp->d_type = 0; 2814 # endif 2815 if (dp->d_reclen > 0) { 2816 dp = (struct dirent *) 2817 ((char *)dp + dp->d_reclen); 2818 } else { 2819 error = EIO; 2820 break; 2821 } 2822 } 2823 if (dp >= edp) 2824 error = uiomove(dirbuf, readcnt, &auio); 2825 } 2826 FREE(dirbuf, M_TEMP); 2827 } 2828 VOP_UNLOCK(vp, 0, td); 2829 if (error) { 2830 fdrop(fp, td); 2831 return (error); 2832 } 2833 if (SCARG(uap, count) == auio.uio_resid) { 2834 if (union_dircheckp) { 2835 error = union_dircheckp(td, &vp, fp); 2836 if (error == -1) 2837 goto unionread; 2838 if (error) { 2839 fdrop(fp, td); 2840 return (error); 2841 } 2842 } 2843 if ((vp->v_flag & VROOT) && 2844 (vp->v_mount->mnt_flag & MNT_UNION)) { 2845 struct vnode *tvp = vp; 2846 vp = vp->v_mount->mnt_vnodecovered; 2847 VREF(vp); 2848 fp->f_data = vp; 2849 fp->f_offset = 0; 2850 vrele(tvp); 2851 goto unionread; 2852 } 2853 } 2854 error = copyout(&loff, SCARG(uap, basep), sizeof(long)); 2855 fdrop(fp, td); 2856 td->td_retval[0] = SCARG(uap, count) - auio.uio_resid; 2857 return (error); 2858 } 2859 #endif /* COMPAT_43 */ 2860 2861 /* 2862 * Read a block of directory entries in a filesystem independent format. 2863 */ 2864 #ifndef _SYS_SYSPROTO_H_ 2865 struct getdirentries_args { 2866 int fd; 2867 char *buf; 2868 u_int count; 2869 long *basep; 2870 }; 2871 #endif 2872 int 2873 getdirentries(td, uap) 2874 struct thread *td; 2875 register struct getdirentries_args /* { 2876 syscallarg(int) fd; 2877 syscallarg(char *) buf; 2878 syscallarg(u_int) count; 2879 syscallarg(long *) basep; 2880 } */ *uap; 2881 { 2882 struct vnode *vp; 2883 struct file *fp; 2884 struct uio auio; 2885 struct iovec aiov; 2886 long loff; 2887 int error, eofflag; 2888 2889 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 2890 return (error); 2891 if ((fp->f_flag & FREAD) == 0) { 2892 fdrop(fp, td); 2893 return (EBADF); 2894 } 2895 vp = (struct vnode *)fp->f_data; 2896 unionread: 2897 if (vp->v_type != VDIR) { 2898 fdrop(fp, td); 2899 return (EINVAL); 2900 } 2901 aiov.iov_base = SCARG(uap, buf); 2902 aiov.iov_len = SCARG(uap, count); 2903 auio.uio_iov = &aiov; 2904 auio.uio_iovcnt = 1; 2905 auio.uio_rw = UIO_READ; 2906 auio.uio_segflg = UIO_USERSPACE; 2907 auio.uio_td = td; 2908 auio.uio_resid = SCARG(uap, count); 2909 /* vn_lock(vp, LK_SHARED | LK_RETRY, td); */ 2910 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2911 loff = auio.uio_offset = fp->f_offset; 2912 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL); 2913 fp->f_offset = auio.uio_offset; 2914 VOP_UNLOCK(vp, 0, td); 2915 if (error) { 2916 fdrop(fp, td); 2917 return (error); 2918 } 2919 if (SCARG(uap, count) == auio.uio_resid) { 2920 if (union_dircheckp) { 2921 error = union_dircheckp(td, &vp, fp); 2922 if (error == -1) 2923 goto unionread; 2924 if (error) { 2925 fdrop(fp, td); 2926 return (error); 2927 } 2928 } 2929 if ((vp->v_flag & VROOT) && 2930 (vp->v_mount->mnt_flag & MNT_UNION)) { 2931 struct vnode *tvp = vp; 2932 vp = vp->v_mount->mnt_vnodecovered; 2933 VREF(vp); 2934 fp->f_data = vp; 2935 fp->f_offset = 0; 2936 vrele(tvp); 2937 goto unionread; 2938 } 2939 } 2940 if (SCARG(uap, basep) != NULL) { 2941 error = copyout(&loff, SCARG(uap, basep), sizeof(long)); 2942 } 2943 td->td_retval[0] = SCARG(uap, count) - auio.uio_resid; 2944 fdrop(fp, td); 2945 return (error); 2946 } 2947 #ifndef _SYS_SYSPROTO_H_ 2948 struct getdents_args { 2949 int fd; 2950 char *buf; 2951 size_t count; 2952 }; 2953 #endif 2954 int 2955 getdents(td, uap) 2956 struct thread *td; 2957 register struct getdents_args /* { 2958 syscallarg(int) fd; 2959 syscallarg(char *) buf; 2960 syscallarg(u_int) count; 2961 } */ *uap; 2962 { 2963 struct getdirentries_args ap; 2964 ap.fd = uap->fd; 2965 ap.buf = uap->buf; 2966 ap.count = uap->count; 2967 ap.basep = NULL; 2968 return getdirentries(td, &ap); 2969 } 2970 2971 /* 2972 * Set the mode mask for creation of filesystem nodes. 2973 * 2974 * MP SAFE 2975 */ 2976 #ifndef _SYS_SYSPROTO_H_ 2977 struct umask_args { 2978 int newmask; 2979 }; 2980 #endif 2981 int 2982 umask(td, uap) 2983 struct thread *td; 2984 struct umask_args /* { 2985 syscallarg(int) newmask; 2986 } */ *uap; 2987 { 2988 register struct filedesc *fdp; 2989 2990 FILEDESC_LOCK(td->td_proc->p_fd); 2991 fdp = td->td_proc->p_fd; 2992 td->td_retval[0] = fdp->fd_cmask; 2993 fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS; 2994 FILEDESC_UNLOCK(td->td_proc->p_fd); 2995 return (0); 2996 } 2997 2998 /* 2999 * Void all references to file by ripping underlying filesystem 3000 * away from vnode. 3001 */ 3002 #ifndef _SYS_SYSPROTO_H_ 3003 struct revoke_args { 3004 char *path; 3005 }; 3006 #endif 3007 /* ARGSUSED */ 3008 int 3009 revoke(td, uap) 3010 struct thread *td; 3011 register struct revoke_args /* { 3012 syscallarg(char *) path; 3013 } */ *uap; 3014 { 3015 struct mount *mp; 3016 struct vnode *vp; 3017 struct vattr vattr; 3018 int error; 3019 struct nameidata nd; 3020 3021 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, SCARG(uap, path), 3022 td); 3023 if ((error = namei(&nd)) != 0) 3024 return (error); 3025 vp = nd.ni_vp; 3026 NDFREE(&nd, NDF_ONLY_PNBUF); 3027 if (vp->v_type != VCHR) { 3028 vput(vp); 3029 return (EINVAL); 3030 } 3031 error = VOP_GETATTR(vp, &vattr, td->td_ucred, td); 3032 if (error) { 3033 vput(vp); 3034 return (error); 3035 } 3036 VOP_UNLOCK(vp, 0, td); 3037 if (td->td_ucred->cr_uid != vattr.va_uid) { 3038 error = suser_cred(td->td_ucred, PRISON_ROOT); 3039 if (error) 3040 goto out; 3041 } 3042 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 3043 goto out; 3044 if (vcount(vp) > 1) 3045 VOP_REVOKE(vp, REVOKEALL); 3046 vn_finished_write(mp); 3047 out: 3048 vrele(vp); 3049 return (error); 3050 } 3051 3052 /* 3053 * Convert a user file descriptor to a kernel file entry. 3054 * The file entry is locked upon returning. 3055 */ 3056 int 3057 getvnode(fdp, fd, fpp) 3058 struct filedesc *fdp; 3059 int fd; 3060 struct file **fpp; 3061 { 3062 int error; 3063 struct file *fp; 3064 3065 fp = NULL; 3066 if (fdp == NULL) 3067 error = EBADF; 3068 else { 3069 FILEDESC_LOCK(fdp); 3070 if ((u_int)fd >= fdp->fd_nfiles || 3071 (fp = fdp->fd_ofiles[fd]) == NULL) 3072 error = EBADF; 3073 else if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_FIFO) { 3074 fp = NULL; 3075 error = EINVAL; 3076 } else { 3077 fhold(fp); 3078 error = 0; 3079 } 3080 FILEDESC_UNLOCK(fdp); 3081 } 3082 *fpp = fp; 3083 return (error); 3084 } 3085 /* 3086 * Get (NFS) file handle 3087 */ 3088 #ifndef _SYS_SYSPROTO_H_ 3089 struct getfh_args { 3090 char *fname; 3091 fhandle_t *fhp; 3092 }; 3093 #endif 3094 int 3095 getfh(td, uap) 3096 struct thread *td; 3097 register struct getfh_args *uap; 3098 { 3099 struct nameidata nd; 3100 fhandle_t fh; 3101 register struct vnode *vp; 3102 int error; 3103 3104 /* 3105 * Must be super user 3106 */ 3107 error = suser(td); 3108 if (error) 3109 return (error); 3110 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, td); 3111 error = namei(&nd); 3112 if (error) 3113 return (error); 3114 NDFREE(&nd, NDF_ONLY_PNBUF); 3115 vp = nd.ni_vp; 3116 bzero(&fh, sizeof(fh)); 3117 fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid; 3118 error = VFS_VPTOFH(vp, &fh.fh_fid); 3119 vput(vp); 3120 if (error) 3121 return (error); 3122 error = copyout(&fh, uap->fhp, sizeof (fh)); 3123 return (error); 3124 } 3125 3126 /* 3127 * syscall for the rpc.lockd to use to translate a NFS file handle into 3128 * an open descriptor. 3129 * 3130 * warning: do not remove the suser() call or this becomes one giant 3131 * security hole. 3132 */ 3133 #ifndef _SYS_SYSPROTO_H_ 3134 struct fhopen_args { 3135 const struct fhandle *u_fhp; 3136 int flags; 3137 }; 3138 #endif 3139 int 3140 fhopen(td, uap) 3141 struct thread *td; 3142 struct fhopen_args /* { 3143 syscallarg(const struct fhandle *) u_fhp; 3144 syscallarg(int) flags; 3145 } */ *uap; 3146 { 3147 struct proc *p = td->td_proc; 3148 struct mount *mp; 3149 struct vnode *vp; 3150 struct fhandle fhp; 3151 struct vattr vat; 3152 struct vattr *vap = &vat; 3153 struct flock lf; 3154 struct file *fp; 3155 register struct filedesc *fdp = p->p_fd; 3156 int fmode, mode, error, type; 3157 struct file *nfp; 3158 int indx; 3159 3160 /* 3161 * Must be super user 3162 */ 3163 error = suser(td); 3164 if (error) 3165 return (error); 3166 3167 fmode = FFLAGS(SCARG(uap, flags)); 3168 /* why not allow a non-read/write open for our lockd? */ 3169 if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT)) 3170 return (EINVAL); 3171 error = copyin(SCARG(uap,u_fhp), &fhp, sizeof(fhp)); 3172 if (error) 3173 return(error); 3174 /* find the mount point */ 3175 mp = vfs_getvfs(&fhp.fh_fsid); 3176 if (mp == NULL) 3177 return (ESTALE); 3178 /* now give me my vnode, it gets returned to me locked */ 3179 error = VFS_FHTOVP(mp, &fhp.fh_fid, &vp); 3180 if (error) 3181 return (error); 3182 /* 3183 * from now on we have to make sure not 3184 * to forget about the vnode 3185 * any error that causes an abort must vput(vp) 3186 * just set error = err and 'goto bad;'. 3187 */ 3188 3189 /* 3190 * from vn_open 3191 */ 3192 if (vp->v_type == VLNK) { 3193 error = EMLINK; 3194 goto bad; 3195 } 3196 if (vp->v_type == VSOCK) { 3197 error = EOPNOTSUPP; 3198 goto bad; 3199 } 3200 mode = 0; 3201 if (fmode & (FWRITE | O_TRUNC)) { 3202 if (vp->v_type == VDIR) { 3203 error = EISDIR; 3204 goto bad; 3205 } 3206 error = vn_writechk(vp); 3207 if (error) 3208 goto bad; 3209 mode |= VWRITE; 3210 } 3211 if (fmode & FREAD) 3212 mode |= VREAD; 3213 if (mode) { 3214 error = VOP_ACCESS(vp, mode, td->td_ucred, td); 3215 if (error) 3216 goto bad; 3217 } 3218 if (fmode & O_TRUNC) { 3219 VOP_UNLOCK(vp, 0, td); /* XXX */ 3220 if ((error = vn_start_write(NULL, &mp, V_WAIT | PCATCH)) != 0) { 3221 vrele(vp); 3222 return (error); 3223 } 3224 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 3225 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); /* XXX */ 3226 VATTR_NULL(vap); 3227 vap->va_size = 0; 3228 error = VOP_SETATTR(vp, vap, td->td_ucred, td); 3229 vn_finished_write(mp); 3230 if (error) 3231 goto bad; 3232 } 3233 error = VOP_OPEN(vp, fmode, td->td_ucred, td); 3234 if (error) 3235 goto bad; 3236 /* 3237 * Make sure that a VM object is created for VMIO support. 3238 */ 3239 if (vn_canvmio(vp) == TRUE) { 3240 if ((error = vfs_object_create(vp, td, td->td_ucred)) != 0) 3241 goto bad; 3242 } 3243 if (fmode & FWRITE) 3244 vp->v_writecount++; 3245 3246 /* 3247 * end of vn_open code 3248 */ 3249 3250 if ((error = falloc(td, &nfp, &indx)) != 0) { 3251 if (fmode & FWRITE) 3252 vp->v_writecount--; 3253 goto bad; 3254 } 3255 fp = nfp; 3256 3257 /* 3258 * Hold an extra reference to avoid having fp ripped out 3259 * from under us while we block in the lock op 3260 */ 3261 fhold(fp); 3262 nfp->f_data = vp; 3263 nfp->f_flag = fmode & FMASK; 3264 nfp->f_ops = &vnops; 3265 nfp->f_type = DTYPE_VNODE; 3266 if (fmode & (O_EXLOCK | O_SHLOCK)) { 3267 lf.l_whence = SEEK_SET; 3268 lf.l_start = 0; 3269 lf.l_len = 0; 3270 if (fmode & O_EXLOCK) 3271 lf.l_type = F_WRLCK; 3272 else 3273 lf.l_type = F_RDLCK; 3274 type = F_FLOCK; 3275 if ((fmode & FNONBLOCK) == 0) 3276 type |= F_WAIT; 3277 VOP_UNLOCK(vp, 0, td); 3278 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, 3279 type)) != 0) { 3280 /* 3281 * The lock request failed. Normally close the 3282 * descriptor but handle the case where someone might 3283 * have dup()d or close()d it when we weren't looking. 3284 */ 3285 FILEDESC_LOCK(fdp); 3286 if (fdp->fd_ofiles[indx] == fp) { 3287 fdp->fd_ofiles[indx] = NULL; 3288 FILEDESC_UNLOCK(fdp); 3289 fdrop(fp, td); 3290 } else 3291 FILEDESC_UNLOCK(fdp); 3292 /* 3293 * release our private reference 3294 */ 3295 fdrop(fp, td); 3296 return(error); 3297 } 3298 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3299 fp->f_flag |= FHASLOCK; 3300 } 3301 if ((vp->v_type == VREG) && (VOP_GETVOBJECT(vp, NULL) != 0)) 3302 vfs_object_create(vp, td, td->td_ucred); 3303 3304 VOP_UNLOCK(vp, 0, td); 3305 fdrop(fp, td); 3306 td->td_retval[0] = indx; 3307 return (0); 3308 3309 bad: 3310 vput(vp); 3311 return (error); 3312 } 3313 3314 /* 3315 * Stat an (NFS) file handle. 3316 */ 3317 #ifndef _SYS_SYSPROTO_H_ 3318 struct fhstat_args { 3319 struct fhandle *u_fhp; 3320 struct stat *sb; 3321 }; 3322 #endif 3323 int 3324 fhstat(td, uap) 3325 struct thread *td; 3326 register struct fhstat_args /* { 3327 syscallarg(struct fhandle *) u_fhp; 3328 syscallarg(struct stat *) sb; 3329 } */ *uap; 3330 { 3331 struct stat sb; 3332 fhandle_t fh; 3333 struct mount *mp; 3334 struct vnode *vp; 3335 int error; 3336 3337 /* 3338 * Must be super user 3339 */ 3340 error = suser(td); 3341 if (error) 3342 return (error); 3343 3344 error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t)); 3345 if (error) 3346 return (error); 3347 3348 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) 3349 return (ESTALE); 3350 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp))) 3351 return (error); 3352 error = vn_stat(vp, &sb, td); 3353 vput(vp); 3354 if (error) 3355 return (error); 3356 error = copyout(&sb, SCARG(uap, sb), sizeof(sb)); 3357 return (error); 3358 } 3359 3360 /* 3361 * Implement fstatfs() for (NFS) file handles. 3362 */ 3363 #ifndef _SYS_SYSPROTO_H_ 3364 struct fhstatfs_args { 3365 struct fhandle *u_fhp; 3366 struct statfs *buf; 3367 }; 3368 #endif 3369 int 3370 fhstatfs(td, uap) 3371 struct thread *td; 3372 struct fhstatfs_args /* { 3373 syscallarg(struct fhandle) *u_fhp; 3374 syscallarg(struct statfs) *buf; 3375 } */ *uap; 3376 { 3377 struct statfs *sp; 3378 struct mount *mp; 3379 struct vnode *vp; 3380 struct statfs sb; 3381 fhandle_t fh; 3382 int error; 3383 3384 /* 3385 * Must be super user 3386 */ 3387 error = suser(td); 3388 if (error) 3389 return (error); 3390 3391 if ((error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t))) != 0) 3392 return (error); 3393 3394 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) 3395 return (ESTALE); 3396 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp))) 3397 return (error); 3398 mp = vp->v_mount; 3399 sp = &mp->mnt_stat; 3400 vput(vp); 3401 if ((error = VFS_STATFS(mp, sp, td)) != 0) 3402 return (error); 3403 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 3404 if (suser(td)) { 3405 bcopy(sp, &sb, sizeof(sb)); 3406 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; 3407 sp = &sb; 3408 } 3409 return (copyout(sp, SCARG(uap, buf), sizeof(*sp))); 3410 } 3411 3412 /* 3413 * Syscall to push extended attribute configuration information into the 3414 * VFS. Accepts a path, which it converts to a mountpoint, as well as 3415 * a command (int cmd), and attribute name and misc data. For now, the 3416 * attribute name is left in userspace for consumption by the VFS_op. 3417 * It will probably be changed to be copied into sysspace by the 3418 * syscall in the future, once issues with various consumers of the 3419 * attribute code have raised their hands. 3420 * 3421 * Currently this is used only by UFS Extended Attributes. 3422 */ 3423 int 3424 extattrctl(td, uap) 3425 struct thread *td; 3426 struct extattrctl_args /* { 3427 syscallarg(const char *) path; 3428 syscallarg(int) cmd; 3429 syscallarg(const char *) filename; 3430 syscallarg(int) attrnamespace; 3431 syscallarg(const char *) attrname; 3432 } */ *uap; 3433 { 3434 struct vnode *filename_vp; 3435 struct nameidata nd; 3436 struct mount *mp, *mp_writable; 3437 char attrname[EXTATTR_MAXNAMELEN]; 3438 int error; 3439 3440 /* 3441 * uap->attrname is not always defined. We check again later when we 3442 * invoke the VFS call so as to pass in NULL there if needed. 3443 */ 3444 if (uap->attrname != NULL) { 3445 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, 3446 NULL); 3447 if (error) 3448 return (error); 3449 } 3450 3451 /* 3452 * uap->filename is not always defined. If it is, grab a vnode lock, 3453 * which VFS_EXTATTRCTL() will later release. 3454 */ 3455 filename_vp = NULL; 3456 if (uap->filename != NULL) { 3457 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 3458 uap->filename, td); 3459 if ((error = namei(&nd)) != 0) 3460 return (error); 3461 filename_vp = nd.ni_vp; 3462 NDFREE(&nd, NDF_NO_VP_RELE | NDF_NO_VP_UNLOCK); 3463 } 3464 3465 /* uap->path is always defined. */ 3466 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td); 3467 if ((error = namei(&nd)) != 0) { 3468 if (filename_vp != NULL) 3469 vput(filename_vp); 3470 return (error); 3471 } 3472 mp = nd.ni_vp->v_mount; 3473 error = vn_start_write(nd.ni_vp, &mp_writable, V_WAIT | PCATCH); 3474 NDFREE(&nd, 0); 3475 if (error) { 3476 if (filename_vp != NULL) 3477 vput(filename_vp); 3478 return (error); 3479 } 3480 3481 if (uap->attrname != NULL) { 3482 error = VFS_EXTATTRCTL(mp, uap->cmd, filename_vp, 3483 uap->attrnamespace, attrname, td); 3484 } else { 3485 error = VFS_EXTATTRCTL(mp, uap->cmd, filename_vp, 3486 uap->attrnamespace, NULL, td); 3487 } 3488 3489 vn_finished_write(mp_writable); 3490 /* 3491 * VFS_EXTATTRCTL will have unlocked, but not de-ref'd, 3492 * filename_vp, so vrele it if it is defined. 3493 */ 3494 if (filename_vp != NULL) 3495 vrele(filename_vp); 3496 3497 return (error); 3498 } 3499 3500 /*- 3501 * Set a named extended attribute on a file or directory 3502 * 3503 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace", 3504 * kernelspace string pointer "attrname", userspace buffer 3505 * pointer "data", buffer length "nbytes", thread "td". 3506 * Returns: 0 on success, an error number otherwise 3507 * Locks: none 3508 * References: vp must be a valid reference for the duration of the call 3509 */ 3510 static int 3511 extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname, 3512 void *data, size_t nbytes, struct thread *td) 3513 { 3514 struct mount *mp; 3515 struct uio auio; 3516 struct iovec aiov; 3517 ssize_t cnt; 3518 int error; 3519 3520 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 3521 return (error); 3522 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 3523 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3524 3525 aiov.iov_base = data; 3526 aiov.iov_len = nbytes; 3527 auio.uio_iov = &aiov; 3528 auio.uio_iovcnt = 1; 3529 auio.uio_offset = 0; 3530 if (nbytes > INT_MAX) { 3531 error = EINVAL; 3532 goto done; 3533 } 3534 auio.uio_resid = nbytes; 3535 auio.uio_rw = UIO_WRITE; 3536 auio.uio_segflg = UIO_USERSPACE; 3537 auio.uio_td = td; 3538 cnt = nbytes; 3539 3540 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio, 3541 td->td_ucred, td); 3542 cnt -= auio.uio_resid; 3543 td->td_retval[0] = cnt; 3544 3545 done: 3546 VOP_UNLOCK(vp, 0, td); 3547 vn_finished_write(mp); 3548 return (error); 3549 } 3550 3551 int 3552 extattr_set_file(td, uap) 3553 struct thread *td; 3554 struct extattr_set_file_args /* { 3555 syscallarg(const char *) path; 3556 syscallarg(int) attrnamespace; 3557 syscallarg(const char *) attrname; 3558 syscallarg(void *) data; 3559 syscallarg(size_t) nbytes; 3560 } */ *uap; 3561 { 3562 struct nameidata nd; 3563 char attrname[EXTATTR_MAXNAMELEN]; 3564 int error; 3565 3566 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL); 3567 if (error) 3568 return (error); 3569 3570 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td); 3571 if ((error = namei(&nd)) != 0) 3572 return (error); 3573 NDFREE(&nd, NDF_ONLY_PNBUF); 3574 3575 error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname, 3576 uap->data, uap->nbytes, td); 3577 3578 vrele(nd.ni_vp); 3579 return (error); 3580 } 3581 3582 int 3583 extattr_set_fd(td, uap) 3584 struct thread *td; 3585 struct extattr_set_fd_args /* { 3586 syscallarg(int) fd; 3587 syscallarg(int) attrnamespace; 3588 syscallarg(const char *) attrname; 3589 syscallarg(void *) data; 3590 syscallarg(size_t) nbytes; 3591 } */ *uap; 3592 { 3593 struct file *fp; 3594 char attrname[EXTATTR_MAXNAMELEN]; 3595 int error; 3596 3597 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL); 3598 if (error) 3599 return (error); 3600 3601 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) 3602 return (error); 3603 3604 error = extattr_set_vp((struct vnode *)fp->f_data, uap->attrnamespace, 3605 attrname, uap->data, uap->nbytes, td); 3606 fdrop(fp, td); 3607 3608 return (error); 3609 } 3610 3611 /*- 3612 * Get a named extended attribute on a file or directory 3613 * 3614 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace", 3615 * kernelspace string pointer "attrname", userspace buffer 3616 * pointer "data", buffer length "nbytes", thread "td". 3617 * Returns: 0 on success, an error number otherwise 3618 * Locks: none 3619 * References: vp must be a valid reference for the duration of the call 3620 */ 3621 static int 3622 extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname, 3623 void *data, size_t nbytes, struct thread *td) 3624 { 3625 struct uio auio, *auiop; 3626 struct iovec aiov; 3627 ssize_t cnt; 3628 size_t size, *sizep; 3629 int error; 3630 3631 VOP_LEASE(vp, td, td->td_ucred, LEASE_READ); 3632 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3633 3634 /* 3635 * Slightly unusual semantics: if the user provides a NULL data 3636 * pointer, they don't want to receive the data, just the 3637 * maximum read length. 3638 */ 3639 auiop = NULL; 3640 sizep = NULL; 3641 cnt = 0; 3642 if (data != NULL) { 3643 aiov.iov_base = data; 3644 aiov.iov_len = nbytes; 3645 auio.uio_iov = &aiov; 3646 auio.uio_offset = 0; 3647 if (nbytes > INT_MAX) { 3648 error = EINVAL; 3649 goto done; 3650 } 3651 auio.uio_resid = nbytes; 3652 auio.uio_rw = UIO_READ; 3653 auio.uio_segflg = UIO_USERSPACE; 3654 auio.uio_td = td; 3655 auiop = &auio; 3656 cnt = nbytes; 3657 } else 3658 sizep = &size; 3659 3660 error = VOP_GETEXTATTR(vp, attrnamespace, attrname, auiop, sizep, 3661 td->td_ucred, td); 3662 3663 if (auiop != NULL) { 3664 cnt -= auio.uio_resid; 3665 td->td_retval[0] = cnt; 3666 } else 3667 td->td_retval[0] = size; 3668 3669 done: 3670 VOP_UNLOCK(vp, 0, td); 3671 return (error); 3672 } 3673 3674 int 3675 extattr_get_file(td, uap) 3676 struct thread *td; 3677 struct extattr_get_file_args /* { 3678 syscallarg(const char *) path; 3679 syscallarg(int) attrnamespace; 3680 syscallarg(const char *) attrname; 3681 syscallarg(void *) data; 3682 syscallarg(size_t) nbytes; 3683 } */ *uap; 3684 { 3685 struct nameidata nd; 3686 char attrname[EXTATTR_MAXNAMELEN]; 3687 int error; 3688 3689 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL); 3690 if (error) 3691 return (error); 3692 3693 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td); 3694 if ((error = namei(&nd)) != 0) 3695 return (error); 3696 NDFREE(&nd, NDF_ONLY_PNBUF); 3697 3698 error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname, 3699 uap->data, uap->nbytes, td); 3700 3701 vrele(nd.ni_vp); 3702 return (error); 3703 } 3704 3705 int 3706 extattr_get_fd(td, uap) 3707 struct thread *td; 3708 struct extattr_get_fd_args /* { 3709 syscallarg(int) fd; 3710 syscallarg(int) attrnamespace; 3711 syscallarg(const char *) attrname; 3712 syscallarg(void *) data; 3713 syscallarg(size_t) nbytes; 3714 } */ *uap; 3715 { 3716 struct file *fp; 3717 char attrname[EXTATTR_MAXNAMELEN]; 3718 int error; 3719 3720 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL); 3721 if (error) 3722 return (error); 3723 3724 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 3725 return (error); 3726 3727 error = extattr_get_vp((struct vnode *)fp->f_data, uap->attrnamespace, 3728 attrname, uap->data, uap->nbytes, td); 3729 3730 fdrop(fp, td); 3731 return (error); 3732 } 3733 3734 /* 3735 * extattr_delete_vp(): Delete a named extended attribute on a file or 3736 * directory 3737 * 3738 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace", 3739 * kernelspace string pointer "attrname", proc "p" 3740 * Returns: 0 on success, an error number otherwise 3741 * Locks: none 3742 * References: vp must be a valid reference for the duration of the call 3743 */ 3744 static int 3745 extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname, 3746 struct thread *td) 3747 { 3748 struct mount *mp; 3749 int error; 3750 3751 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 3752 return (error); 3753 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 3754 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3755 3756 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL, td->td_ucred, 3757 td); 3758 3759 VOP_UNLOCK(vp, 0, td); 3760 vn_finished_write(mp); 3761 return (error); 3762 } 3763 3764 int 3765 extattr_delete_file(td, uap) 3766 struct thread *td; 3767 struct extattr_delete_file_args /* { 3768 syscallarg(const char *) path; 3769 syscallarg(int) attrnamespace; 3770 syscallarg(const char *) attrname; 3771 } */ *uap; 3772 { 3773 struct nameidata nd; 3774 char attrname[EXTATTR_MAXNAMELEN]; 3775 int error; 3776 3777 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL); 3778 if (error) 3779 return(error); 3780 3781 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td); 3782 if ((error = namei(&nd)) != 0) 3783 return(error); 3784 NDFREE(&nd, NDF_ONLY_PNBUF); 3785 3786 error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td); 3787 3788 vrele(nd.ni_vp); 3789 return(error); 3790 } 3791 3792 int 3793 extattr_delete_fd(td, uap) 3794 struct thread *td; 3795 struct extattr_delete_fd_args /* { 3796 syscallarg(int) fd; 3797 syscallarg(int) attrnamespace; 3798 syscallarg(const char *) attrname; 3799 } */ *uap; 3800 { 3801 struct file *fp; 3802 struct vnode *vp; 3803 char attrname[EXTATTR_MAXNAMELEN]; 3804 int error; 3805 3806 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL); 3807 if (error) 3808 return (error); 3809 3810 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) 3811 return (error); 3812 vp = (struct vnode *)fp->f_data; 3813 3814 error = extattr_delete_vp((struct vnode *)fp->f_data, 3815 uap->attrnamespace, attrname, td); 3816 3817 fdrop(fp, td); 3818 return (error); 3819 } 3820