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