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