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