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