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.20 (Berkeley) 08/11/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 VOP_LEASE(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 VOP_LEASE(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 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, 816 LEASE_WRITE); 817 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 818 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); 819 } else { 820 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 821 if (nd.ni_dvp == nd.ni_vp) 822 vrele(nd.ni_dvp); 823 else 824 vput(nd.ni_dvp); 825 if (nd.ni_vp) 826 vrele(nd.ni_vp); 827 } 828 } 829 } 830 vrele(vp); 831 return (error); 832 } 833 834 /* 835 * Make a symbolic link. 836 */ 837 struct symlink_args { 838 char *path; 839 char *link; 840 }; 841 /* ARGSUSED */ 842 symlink(p, uap, retval) 843 struct proc *p; 844 register struct symlink_args *uap; 845 int *retval; 846 { 847 struct vattr vattr; 848 char *path; 849 int error; 850 struct nameidata nd; 851 852 MALLOC(path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); 853 if (error = copyinstr(uap->path, path, MAXPATHLEN, NULL)) 854 goto out; 855 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->link, p); 856 if (error = namei(&nd)) 857 goto out; 858 if (nd.ni_vp) { 859 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 860 if (nd.ni_dvp == nd.ni_vp) 861 vrele(nd.ni_dvp); 862 else 863 vput(nd.ni_dvp); 864 vrele(nd.ni_vp); 865 error = EEXIST; 866 goto out; 867 } 868 VATTR_NULL(&vattr); 869 vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask; 870 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 871 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path); 872 out: 873 FREE(path, M_NAMEI); 874 return (error); 875 } 876 877 /* 878 * Delete a whiteout from the filesystem. 879 */ 880 struct unwhiteout_args { 881 char *path; 882 }; 883 /* ARGSUSED */ 884 unwhiteout(p, uap, retval) 885 struct proc *p; 886 struct unwhiteout_args *uap; 887 int *retval; 888 { 889 int error; 890 struct nameidata nd; 891 892 NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE, uap->path, p); 893 error = namei(&nd); 894 if (error) 895 return (error); 896 897 if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) { 898 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 899 if (nd.ni_dvp == nd.ni_vp) 900 vrele(nd.ni_dvp); 901 else 902 vput(nd.ni_dvp); 903 if (nd.ni_vp) 904 vrele(nd.ni_vp); 905 return (EEXIST); 906 } 907 908 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 909 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE); 910 if (error != 0) 911 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 912 vput(nd.ni_dvp); 913 return (error); 914 } 915 916 /* 917 * Delete a name from the filesystem. 918 */ 919 struct unlink_args { 920 char *path; 921 }; 922 /* ARGSUSED */ 923 unlink(p, uap, retval) 924 struct proc *p; 925 struct unlink_args *uap; 926 int *retval; 927 { 928 register struct vnode *vp; 929 int error; 930 struct nameidata nd; 931 932 NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, uap->path, p); 933 if (error = namei(&nd)) 934 return (error); 935 vp = nd.ni_vp; 936 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 937 VOP_LOCK(vp); 938 939 if (vp->v_type != VDIR || 940 (error = suser(p->p_ucred, &p->p_acflag)) == 0) { 941 /* 942 * The root of a mounted filesystem cannot be deleted. 943 */ 944 if (vp->v_flag & VROOT) 945 error = EBUSY; 946 else 947 (void)vnode_pager_uncache(vp); 948 } 949 950 if (!error) { 951 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 952 error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 953 } else { 954 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 955 if (nd.ni_dvp == vp) 956 vrele(nd.ni_dvp); 957 else 958 vput(nd.ni_dvp); 959 if (vp != NULLVP) 960 vput(vp); 961 } 962 return (error); 963 } 964 965 /* 966 * Reposition read/write file offset. 967 */ 968 struct lseek_args { 969 int fd; 970 int pad; 971 off_t offset; 972 int whence; 973 }; 974 lseek(p, uap, retval) 975 struct proc *p; 976 register struct lseek_args *uap; 977 int *retval; 978 { 979 struct ucred *cred = p->p_ucred; 980 register struct filedesc *fdp = p->p_fd; 981 register struct file *fp; 982 struct vattr vattr; 983 int error; 984 985 if ((u_int)uap->fd >= fdp->fd_nfiles || 986 (fp = fdp->fd_ofiles[uap->fd]) == NULL) 987 return (EBADF); 988 if (fp->f_type != DTYPE_VNODE) 989 return (ESPIPE); 990 switch (uap->whence) { 991 case L_INCR: 992 fp->f_offset += uap->offset; 993 break; 994 case L_XTND: 995 if (error = 996 VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p)) 997 return (error); 998 fp->f_offset = uap->offset + vattr.va_size; 999 break; 1000 case L_SET: 1001 fp->f_offset = uap->offset; 1002 break; 1003 default: 1004 return (EINVAL); 1005 } 1006 *(off_t *)retval = fp->f_offset; 1007 return (0); 1008 } 1009 1010 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1011 /* 1012 * Reposition read/write file offset. 1013 */ 1014 struct olseek_args { 1015 int fd; 1016 long offset; 1017 int whence; 1018 }; 1019 olseek(p, uap, retval) 1020 struct proc *p; 1021 register struct olseek_args *uap; 1022 int *retval; 1023 { 1024 struct lseek_args nuap; 1025 off_t qret; 1026 int error; 1027 1028 nuap.fd = uap->fd; 1029 nuap.offset = uap->offset; 1030 nuap.whence = uap->whence; 1031 error = lseek(p, &nuap, &qret); 1032 *(long *)retval = qret; 1033 return (error); 1034 } 1035 #endif /* COMPAT_43 */ 1036 1037 /* 1038 * Check access permissions. 1039 */ 1040 struct access_args { 1041 char *path; 1042 int flags; 1043 }; 1044 access(p, uap, retval) 1045 struct proc *p; 1046 register struct access_args *uap; 1047 int *retval; 1048 { 1049 register struct ucred *cred = p->p_ucred; 1050 register struct vnode *vp; 1051 int error, flags, t_gid, t_uid; 1052 struct nameidata nd; 1053 1054 t_uid = cred->cr_uid; 1055 t_gid = cred->cr_groups[0]; 1056 cred->cr_uid = p->p_cred->p_ruid; 1057 cred->cr_groups[0] = p->p_cred->p_rgid; 1058 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 1059 if (error = namei(&nd)) 1060 goto out1; 1061 vp = nd.ni_vp; 1062 1063 /* Flags == 0 means only check for existence. */ 1064 if (uap->flags) { 1065 flags = 0; 1066 if (uap->flags & R_OK) 1067 flags |= VREAD; 1068 if (uap->flags & W_OK) 1069 flags |= VWRITE; 1070 if (uap->flags & X_OK) 1071 flags |= VEXEC; 1072 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0) 1073 error = VOP_ACCESS(vp, flags, cred, p); 1074 } 1075 vput(vp); 1076 out1: 1077 cred->cr_uid = t_uid; 1078 cred->cr_groups[0] = t_gid; 1079 return (error); 1080 } 1081 1082 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1083 /* 1084 * Get file status; this version follows links. 1085 */ 1086 struct ostat_args { 1087 char *path; 1088 struct ostat *ub; 1089 }; 1090 /* ARGSUSED */ 1091 ostat(p, uap, retval) 1092 struct proc *p; 1093 register struct ostat_args *uap; 1094 int *retval; 1095 { 1096 struct stat sb; 1097 struct ostat osb; 1098 int error; 1099 struct nameidata nd; 1100 1101 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 1102 if (error = namei(&nd)) 1103 return (error); 1104 error = vn_stat(nd.ni_vp, &sb, p); 1105 vput(nd.ni_vp); 1106 if (error) 1107 return (error); 1108 cvtstat(&sb, &osb); 1109 error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb)); 1110 return (error); 1111 } 1112 1113 /* 1114 * Get file status; this version does not follow links. 1115 */ 1116 struct olstat_args { 1117 char *path; 1118 struct ostat *ub; 1119 }; 1120 /* ARGSUSED */ 1121 olstat(p, uap, retval) 1122 struct proc *p; 1123 register struct olstat_args *uap; 1124 int *retval; 1125 { 1126 struct stat sb; 1127 struct ostat osb; 1128 int error; 1129 struct nameidata nd; 1130 1131 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 1132 if (error = namei(&nd)) 1133 return (error); 1134 error = vn_stat(nd.ni_vp, &sb, p); 1135 vput(nd.ni_vp); 1136 if (error) 1137 return (error); 1138 cvtstat(&sb, &osb); 1139 error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb)); 1140 return (error); 1141 } 1142 1143 /* 1144 * Convert from an old to a new stat structure. 1145 */ 1146 cvtstat(st, ost) 1147 struct stat *st; 1148 struct ostat *ost; 1149 { 1150 1151 ost->st_dev = st->st_dev; 1152 ost->st_ino = st->st_ino; 1153 ost->st_mode = st->st_mode; 1154 ost->st_nlink = st->st_nlink; 1155 ost->st_uid = st->st_uid; 1156 ost->st_gid = st->st_gid; 1157 ost->st_rdev = st->st_rdev; 1158 if (st->st_size < (quad_t)1 << 32) 1159 ost->st_size = st->st_size; 1160 else 1161 ost->st_size = -2; 1162 ost->st_atime = st->st_atime; 1163 ost->st_mtime = st->st_mtime; 1164 ost->st_ctime = st->st_ctime; 1165 ost->st_blksize = st->st_blksize; 1166 ost->st_blocks = st->st_blocks; 1167 ost->st_flags = st->st_flags; 1168 ost->st_gen = st->st_gen; 1169 } 1170 #endif /* COMPAT_43 || COMPAT_SUNOS */ 1171 1172 /* 1173 * Get file status; this version follows links. 1174 */ 1175 struct stat_args { 1176 char *path; 1177 struct stat *ub; 1178 }; 1179 /* ARGSUSED */ 1180 stat(p, uap, retval) 1181 struct proc *p; 1182 register struct stat_args *uap; 1183 int *retval; 1184 { 1185 struct stat sb; 1186 int error; 1187 struct nameidata nd; 1188 1189 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 1190 if (error = namei(&nd)) 1191 return (error); 1192 error = vn_stat(nd.ni_vp, &sb, p); 1193 vput(nd.ni_vp); 1194 if (error) 1195 return (error); 1196 error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); 1197 return (error); 1198 } 1199 1200 /* 1201 * Get file status; this version does not follow links. 1202 */ 1203 struct lstat_args { 1204 char *path; 1205 struct stat *ub; 1206 }; 1207 /* ARGSUSED */ 1208 lstat(p, uap, retval) 1209 struct proc *p; 1210 register struct lstat_args *uap; 1211 int *retval; 1212 { 1213 int error; 1214 struct vnode *vp, *dvp; 1215 struct stat sb, sb1; 1216 struct nameidata nd; 1217 1218 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE, 1219 uap->path, p); 1220 if (error = namei(&nd)) 1221 return (error); 1222 /* 1223 * For symbolic links, always return the attributes of its 1224 * containing directory, except for mode, size, and links. 1225 */ 1226 vp = nd.ni_vp; 1227 dvp = nd.ni_dvp; 1228 if (vp->v_type != VLNK) { 1229 if (dvp == vp) 1230 vrele(dvp); 1231 else 1232 vput(dvp); 1233 error = vn_stat(vp, &sb, p); 1234 vput(vp); 1235 if (error) 1236 return (error); 1237 } else { 1238 error = vn_stat(dvp, &sb, p); 1239 vput(dvp); 1240 if (error) { 1241 vput(vp); 1242 return (error); 1243 } 1244 error = vn_stat(vp, &sb1, p); 1245 vput(vp); 1246 if (error) 1247 return (error); 1248 sb.st_mode &= ~S_IFDIR; 1249 sb.st_mode |= S_IFLNK; 1250 sb.st_nlink = sb1.st_nlink; 1251 sb.st_size = sb1.st_size; 1252 sb.st_blocks = sb1.st_blocks; 1253 } 1254 error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); 1255 return (error); 1256 } 1257 1258 /* 1259 * Get configurable pathname variables. 1260 */ 1261 struct pathconf_args { 1262 char *path; 1263 int name; 1264 }; 1265 /* ARGSUSED */ 1266 pathconf(p, uap, retval) 1267 struct proc *p; 1268 register struct pathconf_args *uap; 1269 int *retval; 1270 { 1271 int error; 1272 struct nameidata nd; 1273 1274 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 1275 if (error = namei(&nd)) 1276 return (error); 1277 error = VOP_PATHCONF(nd.ni_vp, uap->name, retval); 1278 vput(nd.ni_vp); 1279 return (error); 1280 } 1281 1282 /* 1283 * Return target name of a symbolic link. 1284 */ 1285 struct readlink_args { 1286 char *path; 1287 char *buf; 1288 int count; 1289 }; 1290 /* ARGSUSED */ 1291 readlink(p, uap, retval) 1292 struct proc *p; 1293 register struct readlink_args *uap; 1294 int *retval; 1295 { 1296 register struct vnode *vp; 1297 struct iovec aiov; 1298 struct uio auio; 1299 int error; 1300 struct nameidata nd; 1301 1302 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 1303 if (error = namei(&nd)) 1304 return (error); 1305 vp = nd.ni_vp; 1306 if (vp->v_type != VLNK) 1307 error = EINVAL; 1308 else { 1309 aiov.iov_base = uap->buf; 1310 aiov.iov_len = uap->count; 1311 auio.uio_iov = &aiov; 1312 auio.uio_iovcnt = 1; 1313 auio.uio_offset = 0; 1314 auio.uio_rw = UIO_READ; 1315 auio.uio_segflg = UIO_USERSPACE; 1316 auio.uio_procp = p; 1317 auio.uio_resid = uap->count; 1318 error = VOP_READLINK(vp, &auio, p->p_ucred); 1319 } 1320 vput(vp); 1321 *retval = uap->count - auio.uio_resid; 1322 return (error); 1323 } 1324 1325 /* 1326 * Change flags of a file given a path name. 1327 */ 1328 struct chflags_args { 1329 char *path; 1330 int flags; 1331 }; 1332 /* ARGSUSED */ 1333 chflags(p, uap, retval) 1334 struct proc *p; 1335 register struct chflags_args *uap; 1336 int *retval; 1337 { 1338 register struct vnode *vp; 1339 struct vattr vattr; 1340 int error; 1341 struct nameidata nd; 1342 1343 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 1344 if (error = namei(&nd)) 1345 return (error); 1346 vp = nd.ni_vp; 1347 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1348 VOP_LOCK(vp); 1349 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1350 error = EROFS; 1351 else { 1352 VATTR_NULL(&vattr); 1353 vattr.va_flags = uap->flags; 1354 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1355 } 1356 vput(vp); 1357 return (error); 1358 } 1359 1360 /* 1361 * Change flags of a file given a file descriptor. 1362 */ 1363 struct fchflags_args { 1364 int fd; 1365 int flags; 1366 }; 1367 /* ARGSUSED */ 1368 fchflags(p, uap, retval) 1369 struct proc *p; 1370 register struct fchflags_args *uap; 1371 int *retval; 1372 { 1373 struct vattr vattr; 1374 struct vnode *vp; 1375 struct file *fp; 1376 int error; 1377 1378 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1379 return (error); 1380 vp = (struct vnode *)fp->f_data; 1381 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1382 VOP_LOCK(vp); 1383 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1384 error = EROFS; 1385 else { 1386 VATTR_NULL(&vattr); 1387 vattr.va_flags = uap->flags; 1388 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1389 } 1390 VOP_UNLOCK(vp); 1391 return (error); 1392 } 1393 1394 /* 1395 * Change mode of a file given path name. 1396 */ 1397 struct chmod_args { 1398 char *path; 1399 int mode; 1400 }; 1401 /* ARGSUSED */ 1402 chmod(p, uap, retval) 1403 struct proc *p; 1404 register struct chmod_args *uap; 1405 int *retval; 1406 { 1407 register struct vnode *vp; 1408 struct vattr vattr; 1409 int error; 1410 struct nameidata nd; 1411 1412 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 1413 if (error = namei(&nd)) 1414 return (error); 1415 vp = nd.ni_vp; 1416 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1417 VOP_LOCK(vp); 1418 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1419 error = EROFS; 1420 else { 1421 VATTR_NULL(&vattr); 1422 vattr.va_mode = uap->mode & ALLPERMS; 1423 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1424 } 1425 vput(vp); 1426 return (error); 1427 } 1428 1429 /* 1430 * Change mode of a file given a file descriptor. 1431 */ 1432 struct fchmod_args { 1433 int fd; 1434 int mode; 1435 }; 1436 /* ARGSUSED */ 1437 fchmod(p, uap, retval) 1438 struct proc *p; 1439 register struct fchmod_args *uap; 1440 int *retval; 1441 { 1442 struct vattr vattr; 1443 struct vnode *vp; 1444 struct file *fp; 1445 int error; 1446 1447 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1448 return (error); 1449 vp = (struct vnode *)fp->f_data; 1450 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1451 VOP_LOCK(vp); 1452 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1453 error = EROFS; 1454 else { 1455 VATTR_NULL(&vattr); 1456 vattr.va_mode = uap->mode & ALLPERMS; 1457 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1458 } 1459 VOP_UNLOCK(vp); 1460 return (error); 1461 } 1462 1463 /* 1464 * Set ownership given a path name. 1465 */ 1466 struct chown_args { 1467 char *path; 1468 int uid; 1469 int gid; 1470 }; 1471 /* ARGSUSED */ 1472 chown(p, uap, retval) 1473 struct proc *p; 1474 register struct chown_args *uap; 1475 int *retval; 1476 { 1477 register struct vnode *vp; 1478 struct vattr vattr; 1479 int error; 1480 struct nameidata nd; 1481 1482 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 1483 if (error = namei(&nd)) 1484 return (error); 1485 vp = nd.ni_vp; 1486 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1487 VOP_LOCK(vp); 1488 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1489 error = EROFS; 1490 else { 1491 VATTR_NULL(&vattr); 1492 vattr.va_uid = uap->uid; 1493 vattr.va_gid = uap->gid; 1494 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1495 } 1496 vput(vp); 1497 return (error); 1498 } 1499 1500 /* 1501 * Set ownership given a file descriptor. 1502 */ 1503 struct fchown_args { 1504 int fd; 1505 int uid; 1506 int gid; 1507 }; 1508 /* ARGSUSED */ 1509 fchown(p, uap, retval) 1510 struct proc *p; 1511 register struct fchown_args *uap; 1512 int *retval; 1513 { 1514 struct vattr vattr; 1515 struct vnode *vp; 1516 struct file *fp; 1517 int error; 1518 1519 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1520 return (error); 1521 vp = (struct vnode *)fp->f_data; 1522 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1523 VOP_LOCK(vp); 1524 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1525 error = EROFS; 1526 else { 1527 VATTR_NULL(&vattr); 1528 vattr.va_uid = uap->uid; 1529 vattr.va_gid = uap->gid; 1530 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1531 } 1532 VOP_UNLOCK(vp); 1533 return (error); 1534 } 1535 1536 /* 1537 * Set the access and modification times of a file. 1538 */ 1539 struct utimes_args { 1540 char *path; 1541 struct timeval *tptr; 1542 }; 1543 /* ARGSUSED */ 1544 utimes(p, uap, retval) 1545 struct proc *p; 1546 register struct utimes_args *uap; 1547 int *retval; 1548 { 1549 register struct vnode *vp; 1550 struct timeval tv[2]; 1551 struct vattr vattr; 1552 int error; 1553 struct nameidata nd; 1554 1555 VATTR_NULL(&vattr); 1556 if (uap->tptr == NULL) { 1557 microtime(&tv[0]); 1558 tv[1] = tv[0]; 1559 vattr.va_vaflags |= VA_UTIMES_NULL; 1560 } else if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv))) 1561 return (error); 1562 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 1563 if (error = namei(&nd)) 1564 return (error); 1565 vp = nd.ni_vp; 1566 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1567 VOP_LOCK(vp); 1568 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1569 error = EROFS; 1570 else { 1571 vattr.va_atime.ts_sec = tv[0].tv_sec; 1572 vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000; 1573 vattr.va_mtime.ts_sec = tv[1].tv_sec; 1574 vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000; 1575 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1576 } 1577 vput(vp); 1578 return (error); 1579 } 1580 1581 /* 1582 * Truncate a file given its path name. 1583 */ 1584 struct truncate_args { 1585 char *path; 1586 int pad; 1587 off_t length; 1588 }; 1589 /* ARGSUSED */ 1590 truncate(p, uap, retval) 1591 struct proc *p; 1592 register struct truncate_args *uap; 1593 int *retval; 1594 { 1595 register struct vnode *vp; 1596 struct vattr vattr; 1597 int error; 1598 struct nameidata nd; 1599 1600 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 1601 if (error = namei(&nd)) 1602 return (error); 1603 vp = nd.ni_vp; 1604 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1605 VOP_LOCK(vp); 1606 if (vp->v_type == VDIR) 1607 error = EISDIR; 1608 else if ((error = vn_writechk(vp)) == 0 && 1609 (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) { 1610 VATTR_NULL(&vattr); 1611 vattr.va_size = uap->length; 1612 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1613 } 1614 vput(vp); 1615 return (error); 1616 } 1617 1618 /* 1619 * Truncate a file given a file descriptor. 1620 */ 1621 struct ftruncate_args { 1622 int fd; 1623 int pad; 1624 off_t length; 1625 }; 1626 /* ARGSUSED */ 1627 ftruncate(p, uap, retval) 1628 struct proc *p; 1629 register struct ftruncate_args *uap; 1630 int *retval; 1631 { 1632 struct vattr vattr; 1633 struct vnode *vp; 1634 struct file *fp; 1635 int error; 1636 1637 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1638 return (error); 1639 if ((fp->f_flag & FWRITE) == 0) 1640 return (EINVAL); 1641 vp = (struct vnode *)fp->f_data; 1642 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1643 VOP_LOCK(vp); 1644 if (vp->v_type == VDIR) 1645 error = EISDIR; 1646 else if ((error = vn_writechk(vp)) == 0) { 1647 VATTR_NULL(&vattr); 1648 vattr.va_size = uap->length; 1649 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p); 1650 } 1651 VOP_UNLOCK(vp); 1652 return (error); 1653 } 1654 1655 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1656 /* 1657 * Truncate a file given its path name. 1658 */ 1659 struct otruncate_args { 1660 char *path; 1661 long length; 1662 }; 1663 /* ARGSUSED */ 1664 otruncate(p, uap, retval) 1665 struct proc *p; 1666 register struct otruncate_args *uap; 1667 int *retval; 1668 { 1669 struct truncate_args nuap; 1670 1671 nuap.path = uap->path; 1672 nuap.length = uap->length; 1673 return (truncate(p, &nuap, retval)); 1674 } 1675 1676 /* 1677 * Truncate a file given a file descriptor. 1678 */ 1679 struct oftruncate_args { 1680 int fd; 1681 long length; 1682 }; 1683 /* ARGSUSED */ 1684 oftruncate(p, uap, retval) 1685 struct proc *p; 1686 register struct oftruncate_args *uap; 1687 int *retval; 1688 { 1689 struct ftruncate_args nuap; 1690 1691 nuap.fd = uap->fd; 1692 nuap.length = uap->length; 1693 return (ftruncate(p, &nuap, retval)); 1694 } 1695 #endif /* COMPAT_43 || COMPAT_SUNOS */ 1696 1697 /* 1698 * Sync an open file. 1699 */ 1700 struct fsync_args { 1701 int fd; 1702 }; 1703 /* ARGSUSED */ 1704 fsync(p, uap, retval) 1705 struct proc *p; 1706 struct fsync_args *uap; 1707 int *retval; 1708 { 1709 register struct vnode *vp; 1710 struct file *fp; 1711 int error; 1712 1713 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1714 return (error); 1715 vp = (struct vnode *)fp->f_data; 1716 VOP_LOCK(vp); 1717 error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p); 1718 VOP_UNLOCK(vp); 1719 return (error); 1720 } 1721 1722 /* 1723 * Rename files. Source and destination must either both be directories, 1724 * or both not be directories. If target is a directory, it must be empty. 1725 */ 1726 struct rename_args { 1727 char *from; 1728 char *to; 1729 }; 1730 /* ARGSUSED */ 1731 rename(p, uap, retval) 1732 struct proc *p; 1733 register struct rename_args *uap; 1734 int *retval; 1735 { 1736 register struct vnode *tvp, *fvp, *tdvp; 1737 struct nameidata fromnd, tond; 1738 int error; 1739 1740 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE, 1741 uap->from, p); 1742 if (error = namei(&fromnd)) 1743 return (error); 1744 fvp = fromnd.ni_vp; 1745 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART, 1746 UIO_USERSPACE, uap->to, p); 1747 if (error = namei(&tond)) { 1748 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 1749 vrele(fromnd.ni_dvp); 1750 vrele(fvp); 1751 goto out1; 1752 } 1753 tdvp = tond.ni_dvp; 1754 tvp = tond.ni_vp; 1755 if (tvp != NULL) { 1756 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 1757 error = ENOTDIR; 1758 goto out; 1759 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 1760 error = EISDIR; 1761 goto out; 1762 } 1763 } 1764 if (fvp == tdvp) 1765 error = EINVAL; 1766 /* 1767 * If source is the same as the destination (that is the 1768 * same inode number with the same name in the same directory), 1769 * then there is nothing to do. 1770 */ 1771 if (fvp == tvp && fromnd.ni_dvp == tdvp && 1772 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen && 1773 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr, 1774 fromnd.ni_cnd.cn_namelen)) 1775 error = -1; 1776 out: 1777 if (!error) { 1778 VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE); 1779 if (fromnd.ni_dvp != tdvp) 1780 VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1781 if (tvp) 1782 VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE); 1783 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, 1784 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); 1785 } else { 1786 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd); 1787 if (tdvp == tvp) 1788 vrele(tdvp); 1789 else 1790 vput(tdvp); 1791 if (tvp) 1792 vput(tvp); 1793 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 1794 vrele(fromnd.ni_dvp); 1795 vrele(fvp); 1796 } 1797 vrele(tond.ni_startdir); 1798 FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI); 1799 out1: 1800 if (fromnd.ni_startdir) 1801 vrele(fromnd.ni_startdir); 1802 FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI); 1803 if (error == -1) 1804 return (0); 1805 return (error); 1806 } 1807 1808 /* 1809 * Make a directory file. 1810 */ 1811 struct mkdir_args { 1812 char *path; 1813 int mode; 1814 }; 1815 /* ARGSUSED */ 1816 mkdir(p, uap, retval) 1817 struct proc *p; 1818 register struct mkdir_args *uap; 1819 int *retval; 1820 { 1821 register struct vnode *vp; 1822 struct vattr vattr; 1823 int error; 1824 struct nameidata nd; 1825 1826 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p); 1827 if (error = namei(&nd)) 1828 return (error); 1829 vp = nd.ni_vp; 1830 if (vp != NULL) { 1831 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1832 if (nd.ni_dvp == vp) 1833 vrele(nd.ni_dvp); 1834 else 1835 vput(nd.ni_dvp); 1836 vrele(vp); 1837 return (EEXIST); 1838 } 1839 VATTR_NULL(&vattr); 1840 vattr.va_type = VDIR; 1841 vattr.va_mode = (uap->mode & ACCESSPERMS) &~ p->p_fd->fd_cmask; 1842 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1843 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 1844 if (!error) 1845 vput(nd.ni_vp); 1846 return (error); 1847 } 1848 1849 /* 1850 * Remove a directory file. 1851 */ 1852 struct rmdir_args { 1853 char *path; 1854 }; 1855 /* ARGSUSED */ 1856 rmdir(p, uap, retval) 1857 struct proc *p; 1858 struct rmdir_args *uap; 1859 int *retval; 1860 { 1861 register struct vnode *vp; 1862 int error; 1863 struct nameidata nd; 1864 1865 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, uap->path, p); 1866 if (error = namei(&nd)) 1867 return (error); 1868 vp = nd.ni_vp; 1869 if (vp->v_type != VDIR) { 1870 error = ENOTDIR; 1871 goto out; 1872 } 1873 /* 1874 * No rmdir "." please. 1875 */ 1876 if (nd.ni_dvp == vp) { 1877 error = EINVAL; 1878 goto out; 1879 } 1880 /* 1881 * The root of a mounted filesystem cannot be deleted. 1882 */ 1883 if (vp->v_flag & VROOT) 1884 error = EBUSY; 1885 out: 1886 if (!error) { 1887 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1888 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1889 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 1890 } else { 1891 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1892 if (nd.ni_dvp == vp) 1893 vrele(nd.ni_dvp); 1894 else 1895 vput(nd.ni_dvp); 1896 vput(vp); 1897 } 1898 return (error); 1899 } 1900 1901 #ifdef COMPAT_43 1902 /* 1903 * Read a block of directory entries in a file system independent format. 1904 */ 1905 struct ogetdirentries_args { 1906 int fd; 1907 char *buf; 1908 u_int count; 1909 long *basep; 1910 }; 1911 ogetdirentries(p, uap, retval) 1912 struct proc *p; 1913 register struct ogetdirentries_args *uap; 1914 int *retval; 1915 { 1916 register struct vnode *vp; 1917 struct file *fp; 1918 struct uio auio, kuio; 1919 struct iovec aiov, kiov; 1920 struct dirent *dp, *edp; 1921 caddr_t dirbuf; 1922 int error, eofflag, readcnt; 1923 long loff; 1924 1925 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1926 return (error); 1927 if ((fp->f_flag & FREAD) == 0) 1928 return (EBADF); 1929 vp = (struct vnode *)fp->f_data; 1930 unionread: 1931 if (vp->v_type != VDIR) 1932 return (EINVAL); 1933 aiov.iov_base = uap->buf; 1934 aiov.iov_len = uap->count; 1935 auio.uio_iov = &aiov; 1936 auio.uio_iovcnt = 1; 1937 auio.uio_rw = UIO_READ; 1938 auio.uio_segflg = UIO_USERSPACE; 1939 auio.uio_procp = p; 1940 auio.uio_resid = uap->count; 1941 VOP_LOCK(vp); 1942 loff = auio.uio_offset = fp->f_offset; 1943 # if (BYTE_ORDER != LITTLE_ENDIAN) 1944 if (vp->v_mount->mnt_maxsymlinklen <= 0) { 1945 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, 1946 (u_long *)0, 0); 1947 fp->f_offset = auio.uio_offset; 1948 } else 1949 # endif 1950 { 1951 kuio = auio; 1952 kuio.uio_iov = &kiov; 1953 kuio.uio_segflg = UIO_SYSSPACE; 1954 kiov.iov_len = uap->count; 1955 MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK); 1956 kiov.iov_base = dirbuf; 1957 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag, 1958 (u_long *)0, 0); 1959 fp->f_offset = kuio.uio_offset; 1960 if (error == 0) { 1961 readcnt = uap->count - kuio.uio_resid; 1962 edp = (struct dirent *)&dirbuf[readcnt]; 1963 for (dp = (struct dirent *)dirbuf; dp < edp; ) { 1964 # if (BYTE_ORDER == LITTLE_ENDIAN) 1965 /* 1966 * The expected low byte of 1967 * dp->d_namlen is our dp->d_type. 1968 * The high MBZ byte of dp->d_namlen 1969 * is our dp->d_namlen. 1970 */ 1971 dp->d_type = dp->d_namlen; 1972 dp->d_namlen = 0; 1973 # else 1974 /* 1975 * The dp->d_type is the high byte 1976 * of the expected dp->d_namlen, 1977 * so must be zero'ed. 1978 */ 1979 dp->d_type = 0; 1980 # endif 1981 if (dp->d_reclen > 0) { 1982 dp = (struct dirent *) 1983 ((char *)dp + dp->d_reclen); 1984 } else { 1985 error = EIO; 1986 break; 1987 } 1988 } 1989 if (dp >= edp) 1990 error = uiomove(dirbuf, readcnt, &auio); 1991 } 1992 FREE(dirbuf, M_TEMP); 1993 } 1994 VOP_UNLOCK(vp); 1995 if (error) 1996 return (error); 1997 1998 #ifdef UNION 1999 { 2000 extern int (**union_vnodeop_p)(); 2001 extern struct vnode *union_lowervp __P((struct vnode *)); 2002 2003 if ((uap->count == auio.uio_resid) && 2004 (vp->v_op == union_vnodeop_p)) { 2005 struct vnode *lvp; 2006 2007 lvp = union_lowervp(vp); 2008 if (lvp != NULLVP) { 2009 struct vattr va; 2010 2011 /* 2012 * If the directory is opaque, 2013 * then don't show lower entries 2014 */ 2015 error = VOP_GETATTR(vp, &va, fp->f_cred, p); 2016 if (va.va_flags & OPAQUE) { 2017 vrele(lvp); 2018 lvp = NULL; 2019 } 2020 } 2021 2022 if (lvp != NULLVP) { 2023 VOP_LOCK(lvp); 2024 error = VOP_OPEN(lvp, FREAD, fp->f_cred, p); 2025 VOP_UNLOCK(lvp); 2026 2027 if (error) { 2028 vrele(lvp); 2029 return (error); 2030 } 2031 fp->f_data = (caddr_t) lvp; 2032 fp->f_offset = 0; 2033 error = vn_close(vp, FREAD, fp->f_cred, p); 2034 if (error) 2035 return (error); 2036 vp = lvp; 2037 goto unionread; 2038 } 2039 } 2040 } 2041 #endif /* UNION */ 2042 2043 if ((uap->count == auio.uio_resid) && 2044 (vp->v_flag & VROOT) && 2045 (vp->v_mount->mnt_flag & MNT_UNION)) { 2046 struct vnode *tvp = vp; 2047 vp = vp->v_mount->mnt_vnodecovered; 2048 VREF(vp); 2049 fp->f_data = (caddr_t) vp; 2050 fp->f_offset = 0; 2051 vrele(tvp); 2052 goto unionread; 2053 } 2054 error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long)); 2055 *retval = uap->count - auio.uio_resid; 2056 return (error); 2057 } 2058 #endif /* COMPAT_43 */ 2059 2060 /* 2061 * Read a block of directory entries in a file system independent format. 2062 */ 2063 struct getdirentries_args { 2064 int fd; 2065 char *buf; 2066 u_int count; 2067 long *basep; 2068 }; 2069 getdirentries(p, uap, retval) 2070 struct proc *p; 2071 register struct getdirentries_args *uap; 2072 int *retval; 2073 { 2074 register struct vnode *vp; 2075 struct file *fp; 2076 struct uio auio; 2077 struct iovec aiov; 2078 long loff; 2079 int error, eofflag; 2080 2081 if (error = getvnode(p->p_fd, uap->fd, &fp)) 2082 return (error); 2083 if ((fp->f_flag & FREAD) == 0) 2084 return (EBADF); 2085 vp = (struct vnode *)fp->f_data; 2086 unionread: 2087 if (vp->v_type != VDIR) 2088 return (EINVAL); 2089 aiov.iov_base = uap->buf; 2090 aiov.iov_len = uap->count; 2091 auio.uio_iov = &aiov; 2092 auio.uio_iovcnt = 1; 2093 auio.uio_rw = UIO_READ; 2094 auio.uio_segflg = UIO_USERSPACE; 2095 auio.uio_procp = p; 2096 auio.uio_resid = uap->count; 2097 VOP_LOCK(vp); 2098 loff = auio.uio_offset = fp->f_offset; 2099 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, (u_long *)0, 0); 2100 fp->f_offset = auio.uio_offset; 2101 VOP_UNLOCK(vp); 2102 if (error) 2103 return (error); 2104 2105 #ifdef UNION 2106 { 2107 extern int (**union_vnodeop_p)(); 2108 extern struct vnode *union_lowervp __P((struct vnode *)); 2109 2110 if ((uap->count == auio.uio_resid) && 2111 (vp->v_op == union_vnodeop_p)) { 2112 struct vnode *lvp; 2113 2114 lvp = union_lowervp(vp); 2115 if (lvp != NULLVP) { 2116 struct vattr va; 2117 2118 /* 2119 * If the directory is opaque, 2120 * then don't show lower entries 2121 */ 2122 error = VOP_GETATTR(vp, &va, fp->f_cred, p); 2123 if (va.va_flags & OPAQUE) { 2124 vrele(lvp); 2125 lvp = NULL; 2126 } 2127 } 2128 2129 if (lvp != NULLVP) { 2130 VOP_LOCK(lvp); 2131 error = VOP_OPEN(lvp, FREAD, fp->f_cred, p); 2132 VOP_UNLOCK(lvp); 2133 2134 if (error) { 2135 vrele(lvp); 2136 return (error); 2137 } 2138 fp->f_data = (caddr_t) lvp; 2139 fp->f_offset = 0; 2140 error = vn_close(vp, FREAD, fp->f_cred, p); 2141 if (error) 2142 return (error); 2143 vp = lvp; 2144 goto unionread; 2145 } 2146 } 2147 } 2148 #endif 2149 2150 if ((uap->count == auio.uio_resid) && 2151 (vp->v_flag & VROOT) && 2152 (vp->v_mount->mnt_flag & MNT_UNION)) { 2153 struct vnode *tvp = vp; 2154 vp = vp->v_mount->mnt_vnodecovered; 2155 VREF(vp); 2156 fp->f_data = (caddr_t) vp; 2157 fp->f_offset = 0; 2158 vrele(tvp); 2159 goto unionread; 2160 } 2161 error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long)); 2162 *retval = uap->count - auio.uio_resid; 2163 return (error); 2164 } 2165 2166 /* 2167 * Set the mode mask for creation of filesystem nodes. 2168 */ 2169 struct umask_args { 2170 int newmask; 2171 }; 2172 mode_t /* XXX */ 2173 umask(p, uap, retval) 2174 struct proc *p; 2175 struct umask_args *uap; 2176 int *retval; 2177 { 2178 register struct filedesc *fdp; 2179 2180 fdp = p->p_fd; 2181 *retval = fdp->fd_cmask; 2182 fdp->fd_cmask = uap->newmask & ALLPERMS; 2183 return (0); 2184 } 2185 2186 /* 2187 * Void all references to file by ripping underlying filesystem 2188 * away from vnode. 2189 */ 2190 struct revoke_args { 2191 char *path; 2192 }; 2193 /* ARGSUSED */ 2194 revoke(p, uap, retval) 2195 struct proc *p; 2196 register struct revoke_args *uap; 2197 int *retval; 2198 { 2199 register struct vnode *vp; 2200 struct vattr vattr; 2201 int error; 2202 struct nameidata nd; 2203 2204 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 2205 if (error = namei(&nd)) 2206 return (error); 2207 vp = nd.ni_vp; 2208 if (vp->v_type != VCHR && vp->v_type != VBLK) { 2209 error = EINVAL; 2210 goto out; 2211 } 2212 if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) 2213 goto out; 2214 if (p->p_ucred->cr_uid != vattr.va_uid && 2215 (error = suser(p->p_ucred, &p->p_acflag))) 2216 goto out; 2217 if (vp->v_usecount > 1 || (vp->v_flag & VALIASED)) 2218 vgoneall(vp); 2219 out: 2220 vrele(vp); 2221 return (error); 2222 } 2223 2224 /* 2225 * Convert a user file descriptor to a kernel file entry. 2226 */ 2227 getvnode(fdp, fd, fpp) 2228 struct filedesc *fdp; 2229 struct file **fpp; 2230 int fd; 2231 { 2232 struct file *fp; 2233 2234 if ((u_int)fd >= fdp->fd_nfiles || 2235 (fp = fdp->fd_ofiles[fd]) == NULL) 2236 return (EBADF); 2237 if (fp->f_type != DTYPE_VNODE) 2238 return (EINVAL); 2239 *fpp = fp; 2240 return (0); 2241 } 2242