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