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