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