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