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 * %sccs.include.redist.c% 11 * 12 * @(#)vfs_syscalls.c 8.19 (Berkeley) 07/28/94 13 */ 14 15 #include <sys/param.h> 16 #include <sys/systm.h> 17 #include <sys/namei.h> 18 #include <sys/filedesc.h> 19 #include <sys/kernel.h> 20 #include <sys/file.h> 21 #include <sys/stat.h> 22 #include <sys/vnode.h> 23 #include <sys/mount.h> 24 #include <sys/proc.h> 25 #include <sys/uio.h> 26 #include <sys/malloc.h> 27 #include <sys/dirent.h> 28 29 #include <vm/vm.h> 30 #include <sys/sysctl.h> 31 32 static int change_dir __P((struct nameidata *ndp, struct proc *p)); 33 34 /* 35 * Virtual File System System Calls 36 */ 37 38 /* 39 * Mount a file system. 40 */ 41 struct mount_args { 42 int type; 43 char *path; 44 int flags; 45 caddr_t data; 46 }; 47 /* ARGSUSED */ 48 mount(p, uap, retval) 49 struct proc *p; 50 register struct mount_args *uap; 51 int *retval; 52 { 53 register struct vnode *vp; 54 register struct mount *mp; 55 int error, flag; 56 struct vattr va; 57 struct nameidata nd; 58 59 /* 60 * Get vnode to be covered 61 */ 62 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 63 if (error = namei(&nd)) 64 return (error); 65 vp = nd.ni_vp; 66 if (uap->flags & MNT_UPDATE) { 67 if ((vp->v_flag & VROOT) == 0) { 68 vput(vp); 69 return (EINVAL); 70 } 71 mp = vp->v_mount; 72 flag = mp->mnt_flag; 73 /* 74 * We only allow the filesystem to be reloaded if it 75 * is currently mounted read-only. 76 */ 77 if ((uap->flags & MNT_RELOAD) && 78 ((mp->mnt_flag & MNT_RDONLY) == 0)) { 79 vput(vp); 80 return (EOPNOTSUPP); /* Needs translation */ 81 } 82 mp->mnt_flag |= 83 uap->flags & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE); 84 /* 85 * Only root, or the user that did the original mount is 86 * permitted to update it. 87 */ 88 if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid && 89 (error = suser(p->p_ucred, &p->p_acflag))) { 90 vput(vp); 91 return (error); 92 } 93 /* 94 * Do not allow NFS export by non-root users. Silently 95 * enforce MNT_NOSUID and MNT_NODEV for non-root users. 96 */ 97 if (p->p_ucred->cr_uid != 0) { 98 if (uap->flags & MNT_EXPORTED) { 99 vput(vp); 100 return (EPERM); 101 } 102 uap->flags |= MNT_NOSUID | MNT_NODEV; 103 } 104 VOP_UNLOCK(vp); 105 goto update; 106 } 107 /* 108 * If the user is not root, ensure that they own the directory 109 * onto which we are attempting to mount. 110 */ 111 if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) || 112 (va.va_uid != p->p_ucred->cr_uid && 113 (error = suser(p->p_ucred, &p->p_acflag)))) { 114 vput(vp); 115 return (error); 116 } 117 /* 118 * Do not allow NFS export by non-root users. Silently 119 * enforce MNT_NOSUID and MNT_NODEV for non-root users. 120 */ 121 if (p->p_ucred->cr_uid != 0) { 122 if (uap->flags & MNT_EXPORTED) { 123 vput(vp); 124 return (EPERM); 125 } 126 uap->flags |= MNT_NOSUID | MNT_NODEV; 127 } 128 if (error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0)) 129 return (error); 130 if (vp->v_type != VDIR) { 131 vput(vp); 132 return (ENOTDIR); 133 } 134 if ((u_long)uap->type > MOUNT_MAXTYPE || vfssw[uap->type] == NULL) { 135 vput(vp); 136 return (ENODEV); 137 } 138 139 /* 140 * Allocate and initialize the file system. 141 */ 142 mp = (struct mount *)malloc((u_long)sizeof(struct mount), 143 M_MOUNT, M_WAITOK); 144 bzero((char *)mp, (u_long)sizeof(struct mount)); 145 mp->mnt_op = vfssw[uap->type]; 146 if (error = vfs_lock(mp)) { 147 free((caddr_t)mp, M_MOUNT); 148 vput(vp); 149 return (error); 150 } 151 if (vp->v_mountedhere != NULL) { 152 vfs_unlock(mp); 153 free((caddr_t)mp, M_MOUNT); 154 vput(vp); 155 return (EBUSY); 156 } 157 vp->v_mountedhere = mp; 158 mp->mnt_vnodecovered = vp; 159 mp->mnt_stat.f_owner = p->p_ucred->cr_uid; 160 update: 161 /* 162 * Set the mount level flags. 163 */ 164 if (uap->flags & MNT_RDONLY) 165 mp->mnt_flag |= MNT_RDONLY; 166 else if (mp->mnt_flag & MNT_RDONLY) 167 mp->mnt_flag |= MNT_WANTRDWR; 168 mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV | 169 MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC); 170 mp->mnt_flag |= uap->flags & (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV | 171 MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC); 172 /* 173 * Mount the filesystem. 174 */ 175 error = VFS_MOUNT(mp, uap->path, uap->data, &nd, p); 176 if (mp->mnt_flag & MNT_UPDATE) { 177 vrele(vp); 178 if (mp->mnt_flag & MNT_WANTRDWR) 179 mp->mnt_flag &= ~MNT_RDONLY; 180 mp->mnt_flag &=~ 181 (MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_WANTRDWR); 182 if (error) 183 mp->mnt_flag = flag; 184 return (error); 185 } 186 /* 187 * Put the new filesystem on the mount list after root. 188 */ 189 cache_purge(vp); 190 if (!error) { 191 TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list); 192 VOP_UNLOCK(vp); 193 vfs_unlock(mp); 194 error = VFS_START(mp, 0, p); 195 } else { 196 mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0; 197 vfs_unlock(mp); 198 free((caddr_t)mp, M_MOUNT); 199 vput(vp); 200 } 201 return (error); 202 } 203 204 /* 205 * Unmount a file system. 206 * 207 * Note: unmount takes a path to the vnode mounted on as argument, 208 * not special file (as before). 209 */ 210 struct unmount_args { 211 char *path; 212 int flags; 213 }; 214 /* ARGSUSED */ 215 unmount(p, uap, retval) 216 struct proc *p; 217 register struct unmount_args *uap; 218 int *retval; 219 { 220 register struct vnode *vp; 221 struct mount *mp; 222 int error; 223 struct nameidata nd; 224 225 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 226 if (error = namei(&nd)) 227 return (error); 228 vp = nd.ni_vp; 229 mp = vp->v_mount; 230 231 /* 232 * Only root, or the user that did the original mount is 233 * permitted to unmount this filesystem. 234 */ 235 if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) && 236 (error = suser(p->p_ucred, &p->p_acflag))) { 237 vput(vp); 238 return (error); 239 } 240 241 /* 242 * Must be the root of the filesystem 243 */ 244 if ((vp->v_flag & VROOT) == 0) { 245 vput(vp); 246 return (EINVAL); 247 } 248 vput(vp); 249 return (dounmount(mp, uap->flags, p)); 250 } 251 252 /* 253 * Do the actual file system unmount. 254 */ 255 dounmount(mp, flags, p) 256 register struct mount *mp; 257 int flags; 258 struct proc *p; 259 { 260 struct vnode *coveredvp; 261 int error; 262 263 coveredvp = mp->mnt_vnodecovered; 264 if (vfs_busy(mp)) 265 return (EBUSY); 266 mp->mnt_flag |= MNT_UNMOUNT; 267 if (error = vfs_lock(mp)) 268 return (error); 269 270 mp->mnt_flag &=~ MNT_ASYNC; 271 vnode_pager_umount(mp); /* release cached vnodes */ 272 cache_purgevfs(mp); /* remove cache entries for this file sys */ 273 if ((error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0 || 274 (flags & MNT_FORCE)) 275 error = VFS_UNMOUNT(mp, flags, p); 276 mp->mnt_flag &= ~MNT_UNMOUNT; 277 vfs_unbusy(mp); 278 if (error) { 279 vfs_unlock(mp); 280 } else { 281 vrele(coveredvp); 282 TAILQ_REMOVE(&mountlist, mp, mnt_list); 283 mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0; 284 vfs_unlock(mp); 285 if (mp->mnt_vnodelist.lh_first != NULL) 286 panic("unmount: dangling vnode"); 287 free((caddr_t)mp, M_MOUNT); 288 } 289 return (error); 290 } 291 292 /* 293 * Sync each mounted filesystem. 294 */ 295 #ifdef DEBUG 296 int syncprt = 0; 297 struct ctldebug debug0 = { "syncprt", &syncprt }; 298 #endif 299 300 struct sync_args { 301 int dummy; 302 }; 303 /* ARGSUSED */ 304 sync(p, uap, retval) 305 struct proc *p; 306 struct sync_args *uap; 307 int *retval; 308 { 309 register struct mount *mp, *nmp; 310 int asyncflag; 311 312 for (mp = mountlist.tqh_first; mp != NULL; mp = nmp) { 313 nmp = mp->mnt_list.tqe_next; 314 /* 315 * The lock check below is to avoid races with mount 316 * and unmount. 317 */ 318 if ((mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_MPBUSY)) == 0 && 319 !vfs_busy(mp)) { 320 asyncflag = mp->mnt_flag & MNT_ASYNC; 321 mp->mnt_flag &= ~MNT_ASYNC; 322 VFS_SYNC(mp, MNT_NOWAIT, p->p_ucred, p); 323 if (asyncflag) 324 mp->mnt_flag |= MNT_ASYNC; 325 vfs_unbusy(mp); 326 } 327 } 328 #ifdef DIAGNOSTIC 329 if (syncprt) 330 vfs_bufstats(); 331 #endif /* DIAGNOSTIC */ 332 return (0); 333 } 334 335 /* 336 * Change filesystem quotas. 337 */ 338 struct quotactl_args { 339 char *path; 340 int cmd; 341 int uid; 342 caddr_t arg; 343 }; 344 /* ARGSUSED */ 345 quotactl(p, uap, retval) 346 struct proc *p; 347 register struct quotactl_args *uap; 348 int *retval; 349 { 350 register struct mount *mp; 351 int error; 352 struct nameidata nd; 353 354 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 355 if (error = namei(&nd)) 356 return (error); 357 mp = nd.ni_vp->v_mount; 358 vrele(nd.ni_vp); 359 return (VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, p)); 360 } 361 362 /* 363 * Get filesystem statistics. 364 */ 365 struct statfs_args { 366 char *path; 367 struct statfs *buf; 368 }; 369 /* ARGSUSED */ 370 statfs(p, uap, retval) 371 struct proc *p; 372 register struct statfs_args *uap; 373 int *retval; 374 { 375 register struct mount *mp; 376 register struct statfs *sp; 377 int error; 378 struct nameidata nd; 379 380 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 381 if (error = namei(&nd)) 382 return (error); 383 mp = nd.ni_vp->v_mount; 384 sp = &mp->mnt_stat; 385 vrele(nd.ni_vp); 386 if (error = VFS_STATFS(mp, sp, p)) 387 return (error); 388 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 389 return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp))); 390 } 391 392 /* 393 * Get filesystem statistics. 394 */ 395 struct fstatfs_args { 396 int fd; 397 struct statfs *buf; 398 }; 399 /* ARGSUSED */ 400 fstatfs(p, uap, retval) 401 struct proc *p; 402 register struct fstatfs_args *uap; 403 int *retval; 404 { 405 struct file *fp; 406 struct mount *mp; 407 register struct statfs *sp; 408 int error; 409 410 if (error = getvnode(p->p_fd, uap->fd, &fp)) 411 return (error); 412 mp = ((struct vnode *)fp->f_data)->v_mount; 413 sp = &mp->mnt_stat; 414 if (error = VFS_STATFS(mp, sp, p)) 415 return (error); 416 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 417 return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp))); 418 } 419 420 /* 421 * Get statistics on all filesystems. 422 */ 423 struct getfsstat_args { 424 struct statfs *buf; 425 long bufsize; 426 int flags; 427 }; 428 getfsstat(p, uap, retval) 429 struct proc *p; 430 register struct getfsstat_args *uap; 431 int *retval; 432 { 433 register struct mount *mp, *nmp; 434 register struct statfs *sp; 435 caddr_t sfsp; 436 long count, maxcount, error; 437 438 maxcount = uap->bufsize / sizeof(struct statfs); 439 sfsp = (caddr_t)uap->buf; 440 for (count = 0, mp = mountlist.tqh_first; mp != NULL; mp = nmp) { 441 nmp = mp->mnt_list.tqe_next; 442 if (sfsp && count < maxcount && 443 ((mp->mnt_flag & MNT_MLOCK) == 0)) { 444 sp = &mp->mnt_stat; 445 /* 446 * If MNT_NOWAIT is specified, do not refresh the 447 * fsstat cache. MNT_WAIT overrides MNT_NOWAIT. 448 */ 449 if (((uap->flags & MNT_NOWAIT) == 0 || 450 (uap->flags & MNT_WAIT)) && 451 (error = VFS_STATFS(mp, sp, p))) 452 continue; 453 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 454 if (error = copyout((caddr_t)sp, sfsp, sizeof(*sp))) 455 return (error); 456 sfsp += sizeof(*sp); 457 } 458 count++; 459 } 460 if (sfsp && count > maxcount) 461 *retval = maxcount; 462 else 463 *retval = count; 464 return (0); 465 } 466 467 /* 468 * Change current working directory to a given file descriptor. 469 */ 470 struct fchdir_args { 471 int fd; 472 }; 473 /* ARGSUSED */ 474 fchdir(p, uap, retval) 475 struct proc *p; 476 struct fchdir_args *uap; 477 int *retval; 478 { 479 register struct filedesc *fdp = p->p_fd; 480 register struct vnode *vp; 481 struct file *fp; 482 int error; 483 484 if (error = getvnode(fdp, uap->fd, &fp)) 485 return (error); 486 vp = (struct vnode *)fp->f_data; 487 VOP_LOCK(vp); 488 if (vp->v_type != VDIR) 489 error = ENOTDIR; 490 else 491 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 492 VOP_UNLOCK(vp); 493 if (error) 494 return (error); 495 VREF(vp); 496 vrele(fdp->fd_cdir); 497 fdp->fd_cdir = vp; 498 return (0); 499 } 500 501 /* 502 * Change current working directory (``.''). 503 */ 504 struct chdir_args { 505 char *path; 506 }; 507 /* ARGSUSED */ 508 chdir(p, uap, retval) 509 struct proc *p; 510 struct chdir_args *uap; 511 int *retval; 512 { 513 register struct filedesc *fdp = p->p_fd; 514 int error; 515 struct nameidata nd; 516 517 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 518 if (error = change_dir(&nd, p)) 519 return (error); 520 vrele(fdp->fd_cdir); 521 fdp->fd_cdir = nd.ni_vp; 522 return (0); 523 } 524 525 /* 526 * Change notion of root (``/'') directory. 527 */ 528 struct chroot_args { 529 char *path; 530 }; 531 /* ARGSUSED */ 532 chroot(p, uap, retval) 533 struct proc *p; 534 struct chroot_args *uap; 535 int *retval; 536 { 537 register struct filedesc *fdp = p->p_fd; 538 int error; 539 struct nameidata nd; 540 541 if (error = suser(p->p_ucred, &p->p_acflag)) 542 return (error); 543 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 544 if (error = change_dir(&nd, p)) 545 return (error); 546 if (fdp->fd_rdir != NULL) 547 vrele(fdp->fd_rdir); 548 fdp->fd_rdir = nd.ni_vp; 549 return (0); 550 } 551 552 /* 553 * Common routine for chroot and chdir. 554 */ 555 static int 556 change_dir(ndp, p) 557 register struct nameidata *ndp; 558 struct proc *p; 559 { 560 struct vnode *vp; 561 int error; 562 563 if (error = namei(ndp)) 564 return (error); 565 vp = ndp->ni_vp; 566 if (vp->v_type != VDIR) 567 error = ENOTDIR; 568 else 569 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 570 VOP_UNLOCK(vp); 571 if (error) 572 vrele(vp); 573 return (error); 574 } 575 576 /* 577 * Check permissions, allocate an open file structure, 578 * and call the device open routine if any. 579 */ 580 struct open_args { 581 char *path; 582 int flags; 583 int mode; 584 }; 585 open(p, uap, retval) 586 struct proc *p; 587 register struct open_args *uap; 588 int *retval; 589 { 590 register struct filedesc *fdp = p->p_fd; 591 register struct file *fp; 592 register struct vnode *vp; 593 int flags, cmode; 594 struct file *nfp; 595 int type, indx, error; 596 struct flock lf; 597 struct nameidata nd; 598 extern struct fileops vnops; 599 600 if (error = falloc(p, &nfp, &indx)) 601 return (error); 602 fp = nfp; 603 flags = FFLAGS(uap->flags); 604 cmode = ((uap->mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; 605 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 606 p->p_dupfd = -indx - 1; /* XXX check for fdopen */ 607 if (error = vn_open(&nd, flags, cmode)) { 608 ffree(fp); 609 if ((error == ENODEV || error == ENXIO) && 610 p->p_dupfd >= 0 && /* XXX from fdopen */ 611 (error = 612 dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) { 613 *retval = indx; 614 return (0); 615 } 616 if (error == ERESTART) 617 error = EINTR; 618 fdp->fd_ofiles[indx] = NULL; 619 return (error); 620 } 621 p->p_dupfd = 0; 622 vp = nd.ni_vp; 623 fp->f_flag = flags & FMASK; 624 fp->f_type = DTYPE_VNODE; 625 fp->f_ops = &vnops; 626 fp->f_data = (caddr_t)vp; 627 if (flags & (O_EXLOCK | O_SHLOCK)) { 628 lf.l_whence = SEEK_SET; 629 lf.l_start = 0; 630 lf.l_len = 0; 631 if (flags & O_EXLOCK) 632 lf.l_type = F_WRLCK; 633 else 634 lf.l_type = F_RDLCK; 635 type = F_FLOCK; 636 if ((flags & FNONBLOCK) == 0) 637 type |= F_WAIT; 638 VOP_UNLOCK(vp); 639 if (error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) { 640 (void) vn_close(vp, fp->f_flag, fp->f_cred, p); 641 ffree(fp); 642 fdp->fd_ofiles[indx] = NULL; 643 return (error); 644 } 645 VOP_LOCK(vp); 646 fp->f_flag |= FHASLOCK; 647 } 648 VOP_UNLOCK(vp); 649 *retval = indx; 650 return (0); 651 } 652 653 #ifdef COMPAT_43 654 /* 655 * Create a file. 656 */ 657 struct ocreat_args { 658 char *path; 659 int mode; 660 }; 661 ocreat(p, uap, retval) 662 struct proc *p; 663 register struct ocreat_args *uap; 664 int *retval; 665 { 666 struct open_args openuap; 667 668 openuap.path = uap->path; 669 openuap.mode = uap->mode; 670 openuap.flags = O_WRONLY | O_CREAT | O_TRUNC; 671 return (open(p, &openuap, retval)); 672 } 673 #endif /* COMPAT_43 */ 674 675 /* 676 * Create a special file. 677 */ 678 struct mknod_args { 679 char *path; 680 int mode; 681 int dev; 682 }; 683 /* ARGSUSED */ 684 mknod(p, uap, retval) 685 struct proc *p; 686 register struct mknod_args *uap; 687 int *retval; 688 { 689 register struct vnode *vp; 690 struct vattr vattr; 691 int error; 692 int whiteout; 693 struct nameidata nd; 694 695 if (error = suser(p->p_ucred, &p->p_acflag)) 696 return (error); 697 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p); 698 if (error = namei(&nd)) 699 return (error); 700 vp = nd.ni_vp; 701 if (vp != NULL) 702 error = EEXIST; 703 else { 704 VATTR_NULL(&vattr); 705 vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask; 706 vattr.va_rdev = uap->dev; 707 whiteout = 0; 708 709 switch (uap->mode & S_IFMT) { 710 case S_IFMT: /* used by badsect to flag bad sectors */ 711 vattr.va_type = VBAD; 712 break; 713 case S_IFCHR: 714 vattr.va_type = VCHR; 715 break; 716 case S_IFBLK: 717 vattr.va_type = VBLK; 718 break; 719 case S_IFWHT: 720 whiteout = 1; 721 break; 722 default: 723 error = EINVAL; 724 break; 725 } 726 } 727 if (whiteout) { 728 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE); 729 vput(nd.ni_dvp); 730 } else if (!error) { 731 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 732 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 733 } else { 734 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 735 if (nd.ni_dvp == vp) 736 vrele(nd.ni_dvp); 737 else 738 vput(nd.ni_dvp); 739 if (vp) 740 vrele(vp); 741 } 742 return (error); 743 } 744 745 /* 746 * Create named pipe. 747 */ 748 struct mkfifo_args { 749 char *path; 750 int mode; 751 }; 752 /* ARGSUSED */ 753 mkfifo(p, uap, retval) 754 struct proc *p; 755 register struct mkfifo_args *uap; 756 int *retval; 757 { 758 struct vattr vattr; 759 int error; 760 struct nameidata nd; 761 762 #ifndef FIFO 763 return (EOPNOTSUPP); 764 #else 765 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p); 766 if (error = namei(&nd)) 767 return (error); 768 if (nd.ni_vp != NULL) { 769 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 770 if (nd.ni_dvp == nd.ni_vp) 771 vrele(nd.ni_dvp); 772 else 773 vput(nd.ni_dvp); 774 vrele(nd.ni_vp); 775 return (EEXIST); 776 } 777 VATTR_NULL(&vattr); 778 vattr.va_type = VFIFO; 779 vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask; 780 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 781 return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr)); 782 #endif /* FIFO */ 783 } 784 785 /* 786 * Make a hard file link. 787 */ 788 struct link_args { 789 char *path; 790 char *link; 791 }; 792 /* ARGSUSED */ 793 link(p, uap, retval) 794 struct proc *p; 795 register struct link_args *uap; 796 int *retval; 797 { 798 register struct vnode *vp; 799 struct nameidata nd; 800 int error; 801 802 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 803 if (error = namei(&nd)) 804 return (error); 805 vp = nd.ni_vp; 806 if (vp->v_type != VDIR || 807 (error = suser(p->p_ucred, &p->p_acflag)) == 0) { 808 nd.ni_cnd.cn_nameiop = CREATE; 809 nd.ni_cnd.cn_flags = LOCKPARENT; 810 nd.ni_dirp = uap->link; 811 if ((error = namei(&nd)) == 0) { 812 if (nd.ni_vp != NULL) 813 error = EEXIST; 814 if (!error) { 815 LEASE_CHECK(nd.ni_dvp, 816 p, p->p_ucred, LEASE_WRITE); 817 LEASE_CHECK(vp, 818 p, p->p_ucred, LEASE_WRITE); 819 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); 820 } else { 821 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 822 if (nd.ni_dvp == nd.ni_vp) 823 vrele(nd.ni_dvp); 824 else 825 vput(nd.ni_dvp); 826 if (nd.ni_vp) 827 vrele(nd.ni_vp); 828 } 829 } 830 } 831 vrele(vp); 832 return (error); 833 } 834 835 /* 836 * Make a symbolic link. 837 */ 838 struct symlink_args { 839 char *path; 840 char *link; 841 }; 842 /* ARGSUSED */ 843 symlink(p, uap, retval) 844 struct proc *p; 845 register struct symlink_args *uap; 846 int *retval; 847 { 848 struct vattr vattr; 849 char *path; 850 int error; 851 struct nameidata nd; 852 853 MALLOC(path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); 854 if (error = copyinstr(uap->path, path, MAXPATHLEN, NULL)) 855 goto out; 856 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->link, p); 857 if (error = namei(&nd)) 858 goto out; 859 if (nd.ni_vp) { 860 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 861 if (nd.ni_dvp == nd.ni_vp) 862 vrele(nd.ni_dvp); 863 else 864 vput(nd.ni_dvp); 865 vrele(nd.ni_vp); 866 error = EEXIST; 867 goto out; 868 } 869 VATTR_NULL(&vattr); 870 vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask; 871 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 872 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path); 873 out: 874 FREE(path, M_NAMEI); 875 return (error); 876 } 877 878 /* 879 * Delete a whiteout from the filesystem. 880 */ 881 struct unwhiteout_args { 882 char *path; 883 }; 884 /* ARGSUSED */ 885 unwhiteout(p, uap, retval) 886 struct proc *p; 887 struct unwhiteout_args *uap; 888 int *retval; 889 { 890 int error; 891 struct nameidata nd; 892 893 NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE, uap->path, p); 894 error = namei(&nd); 895 if (error) 896 return (error); 897 898 if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) { 899 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 900 if (nd.ni_dvp == nd.ni_vp) 901 vrele(nd.ni_dvp); 902 else 903 vput(nd.ni_dvp); 904 if (nd.ni_vp) 905 vrele(nd.ni_vp); 906 return (EEXIST); 907 } 908 909 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 910 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE); 911 if (error != 0) 912 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 913 vput(nd.ni_dvp); 914 return (error); 915 } 916 917 /* 918 * Delete a name from the filesystem. 919 */ 920 struct unlink_args { 921 char *path; 922 }; 923 /* ARGSUSED */ 924 unlink(p, uap, retval) 925 struct proc *p; 926 struct unlink_args *uap; 927 int *retval; 928 { 929 register struct vnode *vp; 930 int error; 931 struct nameidata nd; 932 933 NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, uap->path, p); 934 if (error = namei(&nd)) 935 return (error); 936 vp = nd.ni_vp; 937 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 938 VOP_LOCK(vp); 939 940 if (vp->v_type != VDIR || 941 (error = suser(p->p_ucred, &p->p_acflag)) == 0) { 942 /* 943 * The root of a mounted filesystem cannot be deleted. 944 */ 945 if (vp->v_flag & VROOT) 946 error = EBUSY; 947 else 948 (void)vnode_pager_uncache(vp); 949 } 950 951 if (!error) { 952 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 953 error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 954 } else { 955 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 956 if (nd.ni_dvp == vp) 957 vrele(nd.ni_dvp); 958 else 959 vput(nd.ni_dvp); 960 if (vp != NULLVP) 961 vput(vp); 962 } 963 return (error); 964 } 965 966 /* 967 * Reposition read/write file offset. 968 */ 969 struct lseek_args { 970 int fd; 971 int pad; 972 off_t offset; 973 int whence; 974 }; 975 lseek(p, uap, retval) 976 struct proc *p; 977 register struct lseek_args *uap; 978 int *retval; 979 { 980 struct ucred *cred = p->p_ucred; 981 register struct filedesc *fdp = p->p_fd; 982 register struct file *fp; 983 struct vattr vattr; 984 int error; 985 986 if ((u_int)uap->fd >= fdp->fd_nfiles || 987 (fp = fdp->fd_ofiles[uap->fd]) == NULL) 988 return (EBADF); 989 if (fp->f_type != DTYPE_VNODE) 990 return (ESPIPE); 991 switch (uap->whence) { 992 case L_INCR: 993 fp->f_offset += uap->offset; 994 break; 995 case L_XTND: 996 if (error = 997 VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p)) 998 return (error); 999 fp->f_offset = uap->offset + vattr.va_size; 1000 break; 1001 case L_SET: 1002 fp->f_offset = uap->offset; 1003 break; 1004 default: 1005 return (EINVAL); 1006 } 1007 *(off_t *)retval = fp->f_offset; 1008 return (0); 1009 } 1010 1011 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1012 /* 1013 * Reposition read/write file offset. 1014 */ 1015 struct olseek_args { 1016 int fd; 1017 long offset; 1018 int whence; 1019 }; 1020 olseek(p, uap, retval) 1021 struct proc *p; 1022 register struct olseek_args *uap; 1023 int *retval; 1024 { 1025 struct lseek_args nuap; 1026 off_t qret; 1027 int error; 1028 1029 nuap.fd = uap->fd; 1030 nuap.offset = uap->offset; 1031 nuap.whence = uap->whence; 1032 error = lseek(p, &nuap, &qret); 1033 *(long *)retval = qret; 1034 return (error); 1035 } 1036 #endif /* COMPAT_43 */ 1037 1038 /* 1039 * Check access permissions. 1040 */ 1041 struct access_args { 1042 char *path; 1043 int flags; 1044 }; 1045 access(p, uap, retval) 1046 struct proc *p; 1047 register struct access_args *uap; 1048 int *retval; 1049 { 1050 register struct ucred *cred = p->p_ucred; 1051 register struct vnode *vp; 1052 int error, flags, t_gid, t_uid; 1053 struct nameidata nd; 1054 1055 t_uid = cred->cr_uid; 1056 t_gid = cred->cr_groups[0]; 1057 cred->cr_uid = p->p_cred->p_ruid; 1058 cred->cr_groups[0] = p->p_cred->p_rgid; 1059 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 1060 if (error = namei(&nd)) 1061 goto out1; 1062 vp = nd.ni_vp; 1063 1064 /* Flags == 0 means only check for existence. */ 1065 if (uap->flags) { 1066 flags = 0; 1067 if (uap->flags & R_OK) 1068 flags |= VREAD; 1069 if (uap->flags & W_OK) 1070 flags |= VWRITE; 1071 if (uap->flags & X_OK) 1072 flags |= VEXEC; 1073 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0) 1074 error = VOP_ACCESS(vp, flags, cred, p); 1075 } 1076 vput(vp); 1077 out1: 1078 cred->cr_uid = t_uid; 1079 cred->cr_groups[0] = t_gid; 1080 return (error); 1081 } 1082 1083 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1084 /* 1085 * Get file status; this version follows links. 1086 */ 1087 struct ostat_args { 1088 char *path; 1089 struct ostat *ub; 1090 }; 1091 /* ARGSUSED */ 1092 ostat(p, uap, retval) 1093 struct proc *p; 1094 register struct ostat_args *uap; 1095 int *retval; 1096 { 1097 struct stat sb; 1098 struct ostat osb; 1099 int error; 1100 struct nameidata nd; 1101 1102 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 1103 if (error = namei(&nd)) 1104 return (error); 1105 error = vn_stat(nd.ni_vp, &sb, p); 1106 vput(nd.ni_vp); 1107 if (error) 1108 return (error); 1109 cvtstat(&sb, &osb); 1110 error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb)); 1111 return (error); 1112 } 1113 1114 /* 1115 * Get file status; this version does not follow links. 1116 */ 1117 struct olstat_args { 1118 char *path; 1119 struct ostat *ub; 1120 }; 1121 /* ARGSUSED */ 1122 olstat(p, uap, retval) 1123 struct proc *p; 1124 register struct olstat_args *uap; 1125 int *retval; 1126 { 1127 struct stat sb; 1128 struct ostat osb; 1129 int error; 1130 struct nameidata nd; 1131 1132 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 1133 if (error = namei(&nd)) 1134 return (error); 1135 error = vn_stat(nd.ni_vp, &sb, p); 1136 vput(nd.ni_vp); 1137 if (error) 1138 return (error); 1139 cvtstat(&sb, &osb); 1140 error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb)); 1141 return (error); 1142 } 1143 1144 /* 1145 * Convert from an old to a new stat structure. 1146 */ 1147 cvtstat(st, ost) 1148 struct stat *st; 1149 struct ostat *ost; 1150 { 1151 1152 ost->st_dev = st->st_dev; 1153 ost->st_ino = st->st_ino; 1154 ost->st_mode = st->st_mode; 1155 ost->st_nlink = st->st_nlink; 1156 ost->st_uid = st->st_uid; 1157 ost->st_gid = st->st_gid; 1158 ost->st_rdev = st->st_rdev; 1159 if (st->st_size < (quad_t)1 << 32) 1160 ost->st_size = st->st_size; 1161 else 1162 ost->st_size = -2; 1163 ost->st_atime = st->st_atime; 1164 ost->st_mtime = st->st_mtime; 1165 ost->st_ctime = st->st_ctime; 1166 ost->st_blksize = st->st_blksize; 1167 ost->st_blocks = st->st_blocks; 1168 ost->st_flags = st->st_flags; 1169 ost->st_gen = st->st_gen; 1170 } 1171 #endif /* COMPAT_43 || COMPAT_SUNOS */ 1172 1173 /* 1174 * Get file status; this version follows links. 1175 */ 1176 struct stat_args { 1177 char *path; 1178 struct stat *ub; 1179 }; 1180 /* ARGSUSED */ 1181 stat(p, uap, retval) 1182 struct proc *p; 1183 register struct stat_args *uap; 1184 int *retval; 1185 { 1186 struct stat sb; 1187 int error; 1188 struct nameidata nd; 1189 1190 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 1191 if (error = namei(&nd)) 1192 return (error); 1193 error = vn_stat(nd.ni_vp, &sb, p); 1194 vput(nd.ni_vp); 1195 if (error) 1196 return (error); 1197 error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); 1198 return (error); 1199 } 1200 1201 /* 1202 * Get file status; this version does not follow links. 1203 */ 1204 struct lstat_args { 1205 char *path; 1206 struct stat *ub; 1207 }; 1208 /* ARGSUSED */ 1209 lstat(p, uap, retval) 1210 struct proc *p; 1211 register struct lstat_args *uap; 1212 int *retval; 1213 { 1214 int error; 1215 struct vnode *vp, *dvp; 1216 struct stat sb, sb1; 1217 struct nameidata nd; 1218 1219 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE, 1220 uap->path, p); 1221 if (error = namei(&nd)) 1222 return (error); 1223 /* 1224 * For symbolic links, always return the attributes of its 1225 * containing directory, except for mode, size, and links. 1226 */ 1227 vp = nd.ni_vp; 1228 dvp = nd.ni_dvp; 1229 if (vp->v_type != VLNK) { 1230 if (dvp == vp) 1231 vrele(dvp); 1232 else 1233 vput(dvp); 1234 error = vn_stat(vp, &sb, p); 1235 vput(vp); 1236 if (error) 1237 return (error); 1238 } else { 1239 error = vn_stat(dvp, &sb, p); 1240 vput(dvp); 1241 if (error) { 1242 vput(vp); 1243 return (error); 1244 } 1245 error = vn_stat(vp, &sb1, p); 1246 vput(vp); 1247 if (error) 1248 return (error); 1249 sb.st_mode &= ~S_IFDIR; 1250 sb.st_mode |= S_IFLNK; 1251 sb.st_nlink = sb1.st_nlink; 1252 sb.st_size = sb1.st_size; 1253 sb.st_blocks = sb1.st_blocks; 1254 } 1255 error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); 1256 return (error); 1257 } 1258 1259 /* 1260 * Get configurable pathname variables. 1261 */ 1262 struct pathconf_args { 1263 char *path; 1264 int name; 1265 }; 1266 /* ARGSUSED */ 1267 pathconf(p, uap, retval) 1268 struct proc *p; 1269 register struct pathconf_args *uap; 1270 int *retval; 1271 { 1272 int error; 1273 struct nameidata nd; 1274 1275 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 1276 if (error = namei(&nd)) 1277 return (error); 1278 error = VOP_PATHCONF(nd.ni_vp, uap->name, retval); 1279 vput(nd.ni_vp); 1280 return (error); 1281 } 1282 1283 /* 1284 * Return target name of a symbolic link. 1285 */ 1286 struct readlink_args { 1287 char *path; 1288 char *buf; 1289 int count; 1290 }; 1291 /* ARGSUSED */ 1292 readlink(p, uap, retval) 1293 struct proc *p; 1294 register struct readlink_args *uap; 1295 int *retval; 1296 { 1297 register struct vnode *vp; 1298 struct iovec aiov; 1299 struct uio auio; 1300 int error; 1301 struct nameidata nd; 1302 1303 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 1304 if (error = namei(&nd)) 1305 return (error); 1306 vp = nd.ni_vp; 1307 if (vp->v_type != VLNK) 1308 error = EINVAL; 1309 else { 1310 aiov.iov_base = uap->buf; 1311 aiov.iov_len = uap->count; 1312 auio.uio_iov = &aiov; 1313 auio.uio_iovcnt = 1; 1314 auio.uio_offset = 0; 1315 auio.uio_rw = UIO_READ; 1316 auio.uio_segflg = UIO_USERSPACE; 1317 auio.uio_procp = p; 1318 auio.uio_resid = uap->count; 1319 error = VOP_READLINK(vp, &auio, p->p_ucred); 1320 } 1321 vput(vp); 1322 *retval = uap->count - auio.uio_resid; 1323 return (error); 1324 } 1325 1326 /* 1327 * Change flags of a file given a path name. 1328 */ 1329 struct chflags_args { 1330 char *path; 1331 int flags; 1332 }; 1333 /* ARGSUSED */ 1334 chflags(p, uap, retval) 1335 struct proc *p; 1336 register struct chflags_args *uap; 1337 int *retval; 1338 { 1339 register struct vnode *vp; 1340 struct vattr vattr; 1341 int error; 1342 struct nameidata nd; 1343 1344 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 1345 if (error = namei(&nd)) 1346 return (error); 1347 vp = nd.ni_vp; 1348 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1349 VOP_LOCK(vp); 1350 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1351 error = EROFS; 1352 else { 1353 VATTR_NULL(&vattr); 1354 vattr.va_flags = uap->flags; 1355 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1356 } 1357 vput(vp); 1358 return (error); 1359 } 1360 1361 /* 1362 * Change flags of a file given a file descriptor. 1363 */ 1364 struct fchflags_args { 1365 int fd; 1366 int flags; 1367 }; 1368 /* ARGSUSED */ 1369 fchflags(p, uap, retval) 1370 struct proc *p; 1371 register struct fchflags_args *uap; 1372 int *retval; 1373 { 1374 struct vattr vattr; 1375 struct vnode *vp; 1376 struct file *fp; 1377 int error; 1378 1379 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1380 return (error); 1381 vp = (struct vnode *)fp->f_data; 1382 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1383 VOP_LOCK(vp); 1384 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1385 error = EROFS; 1386 else { 1387 VATTR_NULL(&vattr); 1388 vattr.va_flags = uap->flags; 1389 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1390 } 1391 VOP_UNLOCK(vp); 1392 return (error); 1393 } 1394 1395 /* 1396 * Change mode of a file given path name. 1397 */ 1398 struct chmod_args { 1399 char *path; 1400 int mode; 1401 }; 1402 /* ARGSUSED */ 1403 chmod(p, uap, retval) 1404 struct proc *p; 1405 register struct chmod_args *uap; 1406 int *retval; 1407 { 1408 register struct vnode *vp; 1409 struct vattr vattr; 1410 int error; 1411 struct nameidata nd; 1412 1413 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 1414 if (error = namei(&nd)) 1415 return (error); 1416 vp = nd.ni_vp; 1417 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1418 VOP_LOCK(vp); 1419 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1420 error = EROFS; 1421 else { 1422 VATTR_NULL(&vattr); 1423 vattr.va_mode = uap->mode & ALLPERMS; 1424 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1425 } 1426 vput(vp); 1427 return (error); 1428 } 1429 1430 /* 1431 * Change mode of a file given a file descriptor. 1432 */ 1433 struct fchmod_args { 1434 int fd; 1435 int mode; 1436 }; 1437 /* ARGSUSED */ 1438 fchmod(p, uap, retval) 1439 struct proc *p; 1440 register struct fchmod_args *uap; 1441 int *retval; 1442 { 1443 struct vattr vattr; 1444 struct vnode *vp; 1445 struct file *fp; 1446 int error; 1447 1448 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1449 return (error); 1450 vp = (struct vnode *)fp->f_data; 1451 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1452 VOP_LOCK(vp); 1453 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1454 error = EROFS; 1455 else { 1456 VATTR_NULL(&vattr); 1457 vattr.va_mode = uap->mode & ALLPERMS; 1458 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1459 } 1460 VOP_UNLOCK(vp); 1461 return (error); 1462 } 1463 1464 /* 1465 * Set ownership given a path name. 1466 */ 1467 struct chown_args { 1468 char *path; 1469 int uid; 1470 int gid; 1471 }; 1472 /* ARGSUSED */ 1473 chown(p, uap, retval) 1474 struct proc *p; 1475 register struct chown_args *uap; 1476 int *retval; 1477 { 1478 register struct vnode *vp; 1479 struct vattr vattr; 1480 int error; 1481 struct nameidata nd; 1482 1483 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 1484 if (error = namei(&nd)) 1485 return (error); 1486 vp = nd.ni_vp; 1487 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1488 VOP_LOCK(vp); 1489 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1490 error = EROFS; 1491 else { 1492 VATTR_NULL(&vattr); 1493 vattr.va_uid = uap->uid; 1494 vattr.va_gid = uap->gid; 1495 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1496 } 1497 vput(vp); 1498 return (error); 1499 } 1500 1501 /* 1502 * Set ownership given a file descriptor. 1503 */ 1504 struct fchown_args { 1505 int fd; 1506 int uid; 1507 int gid; 1508 }; 1509 /* ARGSUSED */ 1510 fchown(p, uap, retval) 1511 struct proc *p; 1512 register struct fchown_args *uap; 1513 int *retval; 1514 { 1515 struct vattr vattr; 1516 struct vnode *vp; 1517 struct file *fp; 1518 int error; 1519 1520 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1521 return (error); 1522 vp = (struct vnode *)fp->f_data; 1523 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1524 VOP_LOCK(vp); 1525 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1526 error = EROFS; 1527 else { 1528 VATTR_NULL(&vattr); 1529 vattr.va_uid = uap->uid; 1530 vattr.va_gid = uap->gid; 1531 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1532 } 1533 VOP_UNLOCK(vp); 1534 return (error); 1535 } 1536 1537 /* 1538 * Set the access and modification times of a file. 1539 */ 1540 struct utimes_args { 1541 char *path; 1542 struct timeval *tptr; 1543 }; 1544 /* ARGSUSED */ 1545 utimes(p, uap, retval) 1546 struct proc *p; 1547 register struct utimes_args *uap; 1548 int *retval; 1549 { 1550 register struct vnode *vp; 1551 struct timeval tv[2]; 1552 struct vattr vattr; 1553 int error; 1554 struct nameidata nd; 1555 1556 VATTR_NULL(&vattr); 1557 if (uap->tptr == NULL) { 1558 microtime(&tv[0]); 1559 tv[1] = tv[0]; 1560 vattr.va_vaflags |= VA_UTIMES_NULL; 1561 } else if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv))) 1562 return (error); 1563 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 1564 if (error = namei(&nd)) 1565 return (error); 1566 vp = nd.ni_vp; 1567 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1568 VOP_LOCK(vp); 1569 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1570 error = EROFS; 1571 else { 1572 vattr.va_atime.ts_sec = tv[0].tv_sec; 1573 vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000; 1574 vattr.va_mtime.ts_sec = tv[1].tv_sec; 1575 vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000; 1576 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1577 } 1578 vput(vp); 1579 return (error); 1580 } 1581 1582 /* 1583 * Truncate a file given its path name. 1584 */ 1585 struct truncate_args { 1586 char *path; 1587 int pad; 1588 off_t length; 1589 }; 1590 /* ARGSUSED */ 1591 truncate(p, uap, retval) 1592 struct proc *p; 1593 register struct truncate_args *uap; 1594 int *retval; 1595 { 1596 register struct vnode *vp; 1597 struct vattr vattr; 1598 int error; 1599 struct nameidata nd; 1600 1601 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 1602 if (error = namei(&nd)) 1603 return (error); 1604 vp = nd.ni_vp; 1605 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1606 VOP_LOCK(vp); 1607 if (vp->v_type == VDIR) 1608 error = EISDIR; 1609 else if ((error = vn_writechk(vp)) == 0 && 1610 (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) { 1611 VATTR_NULL(&vattr); 1612 vattr.va_size = uap->length; 1613 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1614 } 1615 vput(vp); 1616 return (error); 1617 } 1618 1619 /* 1620 * Truncate a file given a file descriptor. 1621 */ 1622 struct ftruncate_args { 1623 int fd; 1624 int pad; 1625 off_t length; 1626 }; 1627 /* ARGSUSED */ 1628 ftruncate(p, uap, retval) 1629 struct proc *p; 1630 register struct ftruncate_args *uap; 1631 int *retval; 1632 { 1633 struct vattr vattr; 1634 struct vnode *vp; 1635 struct file *fp; 1636 int error; 1637 1638 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1639 return (error); 1640 if ((fp->f_flag & FWRITE) == 0) 1641 return (EINVAL); 1642 vp = (struct vnode *)fp->f_data; 1643 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1644 VOP_LOCK(vp); 1645 if (vp->v_type == VDIR) 1646 error = EISDIR; 1647 else if ((error = vn_writechk(vp)) == 0) { 1648 VATTR_NULL(&vattr); 1649 vattr.va_size = uap->length; 1650 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p); 1651 } 1652 VOP_UNLOCK(vp); 1653 return (error); 1654 } 1655 1656 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1657 /* 1658 * Truncate a file given its path name. 1659 */ 1660 struct otruncate_args { 1661 char *path; 1662 long length; 1663 }; 1664 /* ARGSUSED */ 1665 otruncate(p, uap, retval) 1666 struct proc *p; 1667 register struct otruncate_args *uap; 1668 int *retval; 1669 { 1670 struct truncate_args nuap; 1671 1672 nuap.path = uap->path; 1673 nuap.length = uap->length; 1674 return (truncate(p, &nuap, retval)); 1675 } 1676 1677 /* 1678 * Truncate a file given a file descriptor. 1679 */ 1680 struct oftruncate_args { 1681 int fd; 1682 long length; 1683 }; 1684 /* ARGSUSED */ 1685 oftruncate(p, uap, retval) 1686 struct proc *p; 1687 register struct oftruncate_args *uap; 1688 int *retval; 1689 { 1690 struct ftruncate_args nuap; 1691 1692 nuap.fd = uap->fd; 1693 nuap.length = uap->length; 1694 return (ftruncate(p, &nuap, retval)); 1695 } 1696 #endif /* COMPAT_43 || COMPAT_SUNOS */ 1697 1698 /* 1699 * Sync an open file. 1700 */ 1701 struct fsync_args { 1702 int fd; 1703 }; 1704 /* ARGSUSED */ 1705 fsync(p, uap, retval) 1706 struct proc *p; 1707 struct fsync_args *uap; 1708 int *retval; 1709 { 1710 register struct vnode *vp; 1711 struct file *fp; 1712 int error; 1713 1714 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1715 return (error); 1716 vp = (struct vnode *)fp->f_data; 1717 VOP_LOCK(vp); 1718 error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p); 1719 VOP_UNLOCK(vp); 1720 return (error); 1721 } 1722 1723 /* 1724 * Rename files. Source and destination must either both be directories, 1725 * or both not be directories. If target is a directory, it must be empty. 1726 */ 1727 struct rename_args { 1728 char *from; 1729 char *to; 1730 }; 1731 /* ARGSUSED */ 1732 rename(p, uap, retval) 1733 struct proc *p; 1734 register struct rename_args *uap; 1735 int *retval; 1736 { 1737 register struct vnode *tvp, *fvp, *tdvp; 1738 struct nameidata fromnd, tond; 1739 int error; 1740 1741 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE, 1742 uap->from, p); 1743 if (error = namei(&fromnd)) 1744 return (error); 1745 fvp = fromnd.ni_vp; 1746 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART, 1747 UIO_USERSPACE, uap->to, p); 1748 if (error = namei(&tond)) { 1749 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 1750 vrele(fromnd.ni_dvp); 1751 vrele(fvp); 1752 goto out1; 1753 } 1754 tdvp = tond.ni_dvp; 1755 tvp = tond.ni_vp; 1756 if (tvp != NULL) { 1757 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 1758 error = ENOTDIR; 1759 goto out; 1760 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 1761 error = EISDIR; 1762 goto out; 1763 } 1764 } 1765 if (fvp == tdvp) 1766 error = EINVAL; 1767 /* 1768 * If source is the same as the destination (that is the 1769 * same inode number with the same name in the same directory), 1770 * then there is nothing to do. 1771 */ 1772 if (fvp == tvp && fromnd.ni_dvp == tdvp && 1773 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen && 1774 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr, 1775 fromnd.ni_cnd.cn_namelen)) 1776 error = -1; 1777 out: 1778 if (!error) { 1779 LEASE_CHECK(tdvp, p, p->p_ucred, LEASE_WRITE); 1780 if (fromnd.ni_dvp != tdvp) 1781 LEASE_CHECK(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1782 if (tvp) 1783 LEASE_CHECK(tvp, p, p->p_ucred, LEASE_WRITE); 1784 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, 1785 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); 1786 } else { 1787 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd); 1788 if (tdvp == tvp) 1789 vrele(tdvp); 1790 else 1791 vput(tdvp); 1792 if (tvp) 1793 vput(tvp); 1794 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 1795 vrele(fromnd.ni_dvp); 1796 vrele(fvp); 1797 } 1798 vrele(tond.ni_startdir); 1799 FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI); 1800 out1: 1801 if (fromnd.ni_startdir) 1802 vrele(fromnd.ni_startdir); 1803 FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI); 1804 if (error == -1) 1805 return (0); 1806 return (error); 1807 } 1808 1809 /* 1810 * Make a directory file. 1811 */ 1812 struct mkdir_args { 1813 char *path; 1814 int mode; 1815 }; 1816 /* ARGSUSED */ 1817 mkdir(p, uap, retval) 1818 struct proc *p; 1819 register struct mkdir_args *uap; 1820 int *retval; 1821 { 1822 register struct vnode *vp; 1823 struct vattr vattr; 1824 int error; 1825 struct nameidata nd; 1826 1827 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p); 1828 if (error = namei(&nd)) 1829 return (error); 1830 vp = nd.ni_vp; 1831 if (vp != NULL) { 1832 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1833 if (nd.ni_dvp == vp) 1834 vrele(nd.ni_dvp); 1835 else 1836 vput(nd.ni_dvp); 1837 vrele(vp); 1838 return (EEXIST); 1839 } 1840 VATTR_NULL(&vattr); 1841 vattr.va_type = VDIR; 1842 vattr.va_mode = (uap->mode & ACCESSPERMS) &~ p->p_fd->fd_cmask; 1843 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1844 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 1845 if (!error) 1846 vput(nd.ni_vp); 1847 return (error); 1848 } 1849 1850 /* 1851 * Remove a directory file. 1852 */ 1853 struct rmdir_args { 1854 char *path; 1855 }; 1856 /* ARGSUSED */ 1857 rmdir(p, uap, retval) 1858 struct proc *p; 1859 struct rmdir_args *uap; 1860 int *retval; 1861 { 1862 register struct vnode *vp; 1863 int error; 1864 struct nameidata nd; 1865 1866 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, uap->path, p); 1867 if (error = namei(&nd)) 1868 return (error); 1869 vp = nd.ni_vp; 1870 if (vp->v_type != VDIR) { 1871 error = ENOTDIR; 1872 goto out; 1873 } 1874 /* 1875 * No rmdir "." please. 1876 */ 1877 if (nd.ni_dvp == vp) { 1878 error = EINVAL; 1879 goto out; 1880 } 1881 /* 1882 * The root of a mounted filesystem cannot be deleted. 1883 */ 1884 if (vp->v_flag & VROOT) 1885 error = EBUSY; 1886 out: 1887 if (!error) { 1888 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1889 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1890 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 1891 } else { 1892 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1893 if (nd.ni_dvp == vp) 1894 vrele(nd.ni_dvp); 1895 else 1896 vput(nd.ni_dvp); 1897 vput(vp); 1898 } 1899 return (error); 1900 } 1901 1902 #ifdef COMPAT_43 1903 /* 1904 * Read a block of directory entries in a file system independent format. 1905 */ 1906 struct ogetdirentries_args { 1907 int fd; 1908 char *buf; 1909 u_int count; 1910 long *basep; 1911 }; 1912 ogetdirentries(p, uap, retval) 1913 struct proc *p; 1914 register struct ogetdirentries_args *uap; 1915 int *retval; 1916 { 1917 register struct vnode *vp; 1918 struct file *fp; 1919 struct uio auio, kuio; 1920 struct iovec aiov, kiov; 1921 struct dirent *dp, *edp; 1922 caddr_t dirbuf; 1923 int error, eofflag, readcnt; 1924 long loff; 1925 1926 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1927 return (error); 1928 if ((fp->f_flag & FREAD) == 0) 1929 return (EBADF); 1930 vp = (struct vnode *)fp->f_data; 1931 unionread: 1932 if (vp->v_type != VDIR) 1933 return (EINVAL); 1934 aiov.iov_base = uap->buf; 1935 aiov.iov_len = uap->count; 1936 auio.uio_iov = &aiov; 1937 auio.uio_iovcnt = 1; 1938 auio.uio_rw = UIO_READ; 1939 auio.uio_segflg = UIO_USERSPACE; 1940 auio.uio_procp = p; 1941 auio.uio_resid = uap->count; 1942 VOP_LOCK(vp); 1943 loff = auio.uio_offset = fp->f_offset; 1944 # if (BYTE_ORDER != LITTLE_ENDIAN) 1945 if (vp->v_mount->mnt_maxsymlinklen <= 0) { 1946 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, 1947 (u_long *)0, 0); 1948 fp->f_offset = auio.uio_offset; 1949 } else 1950 # endif 1951 { 1952 kuio = auio; 1953 kuio.uio_iov = &kiov; 1954 kuio.uio_segflg = UIO_SYSSPACE; 1955 kiov.iov_len = uap->count; 1956 MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK); 1957 kiov.iov_base = dirbuf; 1958 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag, 1959 (u_long *)0, 0); 1960 fp->f_offset = kuio.uio_offset; 1961 if (error == 0) { 1962 readcnt = uap->count - kuio.uio_resid; 1963 edp = (struct dirent *)&dirbuf[readcnt]; 1964 for (dp = (struct dirent *)dirbuf; dp < edp; ) { 1965 # if (BYTE_ORDER == LITTLE_ENDIAN) 1966 /* 1967 * The expected low byte of 1968 * dp->d_namlen is our dp->d_type. 1969 * The high MBZ byte of dp->d_namlen 1970 * is our dp->d_namlen. 1971 */ 1972 dp->d_type = dp->d_namlen; 1973 dp->d_namlen = 0; 1974 # else 1975 /* 1976 * The dp->d_type is the high byte 1977 * of the expected dp->d_namlen, 1978 * so must be zero'ed. 1979 */ 1980 dp->d_type = 0; 1981 # endif 1982 if (dp->d_reclen > 0) { 1983 dp = (struct dirent *) 1984 ((char *)dp + dp->d_reclen); 1985 } else { 1986 error = EIO; 1987 break; 1988 } 1989 } 1990 if (dp >= edp) 1991 error = uiomove(dirbuf, readcnt, &auio); 1992 } 1993 FREE(dirbuf, M_TEMP); 1994 } 1995 VOP_UNLOCK(vp); 1996 if (error) 1997 return (error); 1998 1999 #ifdef UNION 2000 { 2001 extern int (**union_vnodeop_p)(); 2002 extern struct vnode *union_lowervp __P((struct vnode *)); 2003 2004 if ((uap->count == auio.uio_resid) && 2005 (vp->v_op == union_vnodeop_p)) { 2006 struct vnode *lvp; 2007 2008 lvp = union_lowervp(vp); 2009 if (lvp != NULLVP) { 2010 struct vattr va; 2011 2012 /* 2013 * If the directory is opaque, 2014 * then don't show lower entries 2015 */ 2016 error = VOP_GETATTR(vp, &va, fp->f_cred, p); 2017 if (va.va_flags & OPAQUE) { 2018 vrele(lvp); 2019 lvp = NULL; 2020 } 2021 } 2022 2023 if (lvp != NULLVP) { 2024 VOP_LOCK(lvp); 2025 error = VOP_OPEN(lvp, FREAD, fp->f_cred, p); 2026 VOP_UNLOCK(lvp); 2027 2028 if (error) { 2029 vrele(lvp); 2030 return (error); 2031 } 2032 fp->f_data = (caddr_t) lvp; 2033 fp->f_offset = 0; 2034 error = vn_close(vp, FREAD, fp->f_cred, p); 2035 if (error) 2036 return (error); 2037 vp = lvp; 2038 goto unionread; 2039 } 2040 } 2041 } 2042 #endif /* UNION */ 2043 2044 if ((uap->count == auio.uio_resid) && 2045 (vp->v_flag & VROOT) && 2046 (vp->v_mount->mnt_flag & MNT_UNION)) { 2047 struct vnode *tvp = vp; 2048 vp = vp->v_mount->mnt_vnodecovered; 2049 VREF(vp); 2050 fp->f_data = (caddr_t) vp; 2051 fp->f_offset = 0; 2052 vrele(tvp); 2053 goto unionread; 2054 } 2055 error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long)); 2056 *retval = uap->count - auio.uio_resid; 2057 return (error); 2058 } 2059 #endif /* COMPAT_43 */ 2060 2061 /* 2062 * Read a block of directory entries in a file system independent format. 2063 */ 2064 struct getdirentries_args { 2065 int fd; 2066 char *buf; 2067 u_int count; 2068 long *basep; 2069 }; 2070 getdirentries(p, uap, retval) 2071 struct proc *p; 2072 register struct getdirentries_args *uap; 2073 int *retval; 2074 { 2075 register struct vnode *vp; 2076 struct file *fp; 2077 struct uio auio; 2078 struct iovec aiov; 2079 long loff; 2080 int error, eofflag; 2081 2082 if (error = getvnode(p->p_fd, uap->fd, &fp)) 2083 return (error); 2084 if ((fp->f_flag & FREAD) == 0) 2085 return (EBADF); 2086 vp = (struct vnode *)fp->f_data; 2087 unionread: 2088 if (vp->v_type != VDIR) 2089 return (EINVAL); 2090 aiov.iov_base = uap->buf; 2091 aiov.iov_len = uap->count; 2092 auio.uio_iov = &aiov; 2093 auio.uio_iovcnt = 1; 2094 auio.uio_rw = UIO_READ; 2095 auio.uio_segflg = UIO_USERSPACE; 2096 auio.uio_procp = p; 2097 auio.uio_resid = uap->count; 2098 VOP_LOCK(vp); 2099 loff = auio.uio_offset = fp->f_offset; 2100 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, (u_long *)0, 0); 2101 fp->f_offset = auio.uio_offset; 2102 VOP_UNLOCK(vp); 2103 if (error) 2104 return (error); 2105 2106 #ifdef UNION 2107 { 2108 extern int (**union_vnodeop_p)(); 2109 extern struct vnode *union_lowervp __P((struct vnode *)); 2110 2111 if ((uap->count == auio.uio_resid) && 2112 (vp->v_op == union_vnodeop_p)) { 2113 struct vnode *lvp; 2114 2115 lvp = union_lowervp(vp); 2116 if (lvp != NULLVP) { 2117 struct vattr va; 2118 2119 /* 2120 * If the directory is opaque, 2121 * then don't show lower entries 2122 */ 2123 error = VOP_GETATTR(vp, &va, fp->f_cred, p); 2124 if (va.va_flags & OPAQUE) { 2125 vrele(lvp); 2126 lvp = NULL; 2127 } 2128 } 2129 2130 if (lvp != NULLVP) { 2131 VOP_LOCK(lvp); 2132 error = VOP_OPEN(lvp, FREAD, fp->f_cred, p); 2133 VOP_UNLOCK(lvp); 2134 2135 if (error) { 2136 vrele(lvp); 2137 return (error); 2138 } 2139 fp->f_data = (caddr_t) lvp; 2140 fp->f_offset = 0; 2141 error = vn_close(vp, FREAD, fp->f_cred, p); 2142 if (error) 2143 return (error); 2144 vp = lvp; 2145 goto unionread; 2146 } 2147 } 2148 } 2149 #endif 2150 2151 if ((uap->count == auio.uio_resid) && 2152 (vp->v_flag & VROOT) && 2153 (vp->v_mount->mnt_flag & MNT_UNION)) { 2154 struct vnode *tvp = vp; 2155 vp = vp->v_mount->mnt_vnodecovered; 2156 VREF(vp); 2157 fp->f_data = (caddr_t) vp; 2158 fp->f_offset = 0; 2159 vrele(tvp); 2160 goto unionread; 2161 } 2162 error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long)); 2163 *retval = uap->count - auio.uio_resid; 2164 return (error); 2165 } 2166 2167 /* 2168 * Set the mode mask for creation of filesystem nodes. 2169 */ 2170 struct umask_args { 2171 int newmask; 2172 }; 2173 mode_t /* XXX */ 2174 umask(p, uap, retval) 2175 struct proc *p; 2176 struct umask_args *uap; 2177 int *retval; 2178 { 2179 register struct filedesc *fdp; 2180 2181 fdp = p->p_fd; 2182 *retval = fdp->fd_cmask; 2183 fdp->fd_cmask = uap->newmask & ALLPERMS; 2184 return (0); 2185 } 2186 2187 /* 2188 * Void all references to file by ripping underlying filesystem 2189 * away from vnode. 2190 */ 2191 struct revoke_args { 2192 char *path; 2193 }; 2194 /* ARGSUSED */ 2195 revoke(p, uap, retval) 2196 struct proc *p; 2197 register struct revoke_args *uap; 2198 int *retval; 2199 { 2200 register struct vnode *vp; 2201 struct vattr vattr; 2202 int error; 2203 struct nameidata nd; 2204 2205 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 2206 if (error = namei(&nd)) 2207 return (error); 2208 vp = nd.ni_vp; 2209 if (vp->v_type != VCHR && vp->v_type != VBLK) { 2210 error = EINVAL; 2211 goto out; 2212 } 2213 if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) 2214 goto out; 2215 if (p->p_ucred->cr_uid != vattr.va_uid && 2216 (error = suser(p->p_ucred, &p->p_acflag))) 2217 goto out; 2218 if (vp->v_usecount > 1 || (vp->v_flag & VALIASED)) 2219 vgoneall(vp); 2220 out: 2221 vrele(vp); 2222 return (error); 2223 } 2224 2225 /* 2226 * Convert a user file descriptor to a kernel file entry. 2227 */ 2228 getvnode(fdp, fd, fpp) 2229 struct filedesc *fdp; 2230 struct file **fpp; 2231 int fd; 2232 { 2233 struct file *fp; 2234 2235 if ((u_int)fd >= fdp->fd_nfiles || 2236 (fp = fdp->fd_ofiles[fd]) == NULL) 2237 return (EBADF); 2238 if (fp->f_type != DTYPE_VNODE) 2239 return (EINVAL); 2240 *fpp = fp; 2241 return (0); 2242 } 2243