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