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