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