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