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.3 (Berkeley) 09/23/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 else { 660 VATTR_NULL(&vattr); 661 vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask; 662 vattr.va_rdev = uap->dev; 663 664 switch (uap->mode & S_IFMT) { 665 case S_IFMT: /* used by badsect to flag bad sectors */ 666 vattr.va_type = VBAD; 667 break; 668 case S_IFCHR: 669 vattr.va_type = VCHR; 670 break; 671 case S_IFBLK: 672 vattr.va_type = VBLK; 673 break; 674 default: 675 error = EINVAL; 676 break; 677 } 678 } 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)) == 0) { 757 nd.ni_cnd.cn_nameiop = CREATE; 758 nd.ni_cnd.cn_flags = LOCKPARENT; 759 nd.ni_dirp = uap->link; 760 if ((error = namei(&nd)) == 0) { 761 if (nd.ni_vp != NULL) 762 error = EEXIST; 763 if (!error) { 764 LEASE_CHECK(nd.ni_dvp, 765 p, p->p_ucred, LEASE_WRITE); 766 LEASE_CHECK(vp, 767 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 } 779 } 780 vrele(vp); 781 return (error); 782 } 783 784 /* 785 * Make a symbolic link. 786 */ 787 struct symlink_args { 788 char *path; 789 char *link; 790 }; 791 /* ARGSUSED */ 792 symlink(p, uap, retval) 793 struct proc *p; 794 register struct symlink_args *uap; 795 int *retval; 796 { 797 struct vattr vattr; 798 char *path; 799 int error; 800 struct nameidata nd; 801 802 MALLOC(path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); 803 if (error = copyinstr(uap->path, path, MAXPATHLEN, NULL)) 804 goto out; 805 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->link, p); 806 if (error = namei(&nd)) 807 goto out; 808 if (nd.ni_vp) { 809 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 810 if (nd.ni_dvp == nd.ni_vp) 811 vrele(nd.ni_dvp); 812 else 813 vput(nd.ni_dvp); 814 vrele(nd.ni_vp); 815 error = EEXIST; 816 goto out; 817 } 818 VATTR_NULL(&vattr); 819 vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask; 820 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 821 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path); 822 out: 823 FREE(path, M_NAMEI); 824 return (error); 825 } 826 827 /* 828 * Delete a name from the filesystem. 829 */ 830 struct unlink_args { 831 char *path; 832 }; 833 /* ARGSUSED */ 834 unlink(p, uap, retval) 835 struct proc *p; 836 struct unlink_args *uap; 837 int *retval; 838 { 839 register struct vnode *vp; 840 int error; 841 struct nameidata nd; 842 843 NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, uap->path, p); 844 if (error = namei(&nd)) 845 return (error); 846 vp = nd.ni_vp; 847 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 848 VOP_LOCK(vp); 849 850 if (vp->v_type != VDIR || 851 (error = suser(p->p_ucred, &p->p_acflag)) == 0) { 852 /* 853 * The root of a mounted filesystem cannot be deleted. 854 */ 855 if (vp->v_flag & VROOT) 856 error = EBUSY; 857 else 858 (void)vnode_pager_uncache(vp); 859 } 860 861 if (!error) { 862 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 863 error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 864 } else { 865 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 866 if (nd.ni_dvp == vp) 867 vrele(nd.ni_dvp); 868 else 869 vput(nd.ni_dvp); 870 vput(vp); 871 } 872 return (error); 873 } 874 875 /* 876 * Reposition read/write file offset. 877 */ 878 struct lseek_args { 879 int fd; 880 int pad; 881 off_t offset; 882 int whence; 883 }; 884 lseek(p, uap, retval) 885 struct proc *p; 886 register struct lseek_args *uap; 887 int *retval; 888 { 889 struct ucred *cred = p->p_ucred; 890 register struct filedesc *fdp = p->p_fd; 891 register struct file *fp; 892 struct vattr vattr; 893 int error; 894 895 if ((u_int)uap->fd >= fdp->fd_nfiles || 896 (fp = fdp->fd_ofiles[uap->fd]) == NULL) 897 return (EBADF); 898 if (fp->f_type != DTYPE_VNODE) 899 return (ESPIPE); 900 switch (uap->whence) { 901 case L_INCR: 902 fp->f_offset += uap->offset; 903 break; 904 case L_XTND: 905 if (error = 906 VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p)) 907 return (error); 908 fp->f_offset = uap->offset + vattr.va_size; 909 break; 910 case L_SET: 911 fp->f_offset = uap->offset; 912 break; 913 default: 914 return (EINVAL); 915 } 916 *(off_t *)retval = fp->f_offset; 917 return (0); 918 } 919 920 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 921 /* 922 * Reposition read/write file offset. 923 */ 924 struct olseek_args { 925 int fd; 926 long offset; 927 int whence; 928 }; 929 olseek(p, uap, retval) 930 struct proc *p; 931 register struct olseek_args *uap; 932 int *retval; 933 { 934 struct lseek_args nuap; 935 off_t qret; 936 int error; 937 938 nuap.fd = uap->fd; 939 nuap.offset = uap->offset; 940 nuap.whence = uap->whence; 941 error = lseek(p, &nuap, &qret); 942 *(long *)retval = qret; 943 return (error); 944 } 945 #endif /* COMPAT_43 */ 946 947 /* 948 * Check access permissions. 949 */ 950 struct access_args { 951 char *path; 952 int flags; 953 }; 954 access(p, uap, retval) 955 struct proc *p; 956 register struct access_args *uap; 957 int *retval; 958 { 959 register struct ucred *cred = p->p_ucred; 960 register struct vnode *vp; 961 int error, flags, t_gid, t_uid; 962 struct nameidata nd; 963 964 t_uid = cred->cr_uid; 965 t_gid = cred->cr_groups[0]; 966 cred->cr_uid = p->p_cred->p_ruid; 967 cred->cr_groups[0] = p->p_cred->p_rgid; 968 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 969 if (error = namei(&nd)) 970 goto out1; 971 vp = nd.ni_vp; 972 973 /* Flags == 0 means only check for existence. */ 974 if (uap->flags) { 975 flags = 0; 976 if (uap->flags & R_OK) 977 flags |= VREAD; 978 if (uap->flags & W_OK) 979 flags |= VWRITE; 980 if (uap->flags & X_OK) 981 flags |= VEXEC; 982 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0) 983 error = VOP_ACCESS(vp, flags, cred, p); 984 } 985 vput(vp); 986 out1: 987 cred->cr_uid = t_uid; 988 cred->cr_groups[0] = t_gid; 989 return (error); 990 } 991 992 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 993 /* 994 * Get file status; this version follows links. 995 */ 996 struct ostat_args { 997 char *path; 998 struct ostat *ub; 999 }; 1000 /* ARGSUSED */ 1001 ostat(p, uap, retval) 1002 struct proc *p; 1003 register struct ostat_args *uap; 1004 int *retval; 1005 { 1006 struct stat sb; 1007 struct ostat osb; 1008 int error; 1009 struct nameidata nd; 1010 1011 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 1012 if (error = namei(&nd)) 1013 return (error); 1014 error = vn_stat(nd.ni_vp, &sb, p); 1015 vput(nd.ni_vp); 1016 if (error) 1017 return (error); 1018 cvtstat(&sb, &osb); 1019 error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb)); 1020 return (error); 1021 } 1022 1023 /* 1024 * Get file status; this version does not follow links. 1025 */ 1026 struct olstat_args { 1027 char *path; 1028 struct ostat *ub; 1029 }; 1030 /* ARGSUSED */ 1031 olstat(p, uap, retval) 1032 struct proc *p; 1033 register struct olstat_args *uap; 1034 int *retval; 1035 { 1036 struct stat sb; 1037 struct ostat osb; 1038 int error; 1039 struct nameidata nd; 1040 1041 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 1042 if (error = namei(&nd)) 1043 return (error); 1044 error = vn_stat(nd.ni_vp, &sb, p); 1045 vput(nd.ni_vp); 1046 if (error) 1047 return (error); 1048 cvtstat(&sb, &osb); 1049 error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb)); 1050 return (error); 1051 } 1052 1053 /* 1054 * Convert from an old to a new stat structure. 1055 */ 1056 cvtstat(st, ost) 1057 struct stat *st; 1058 struct ostat *ost; 1059 { 1060 1061 ost->st_dev = st->st_dev; 1062 ost->st_ino = st->st_ino; 1063 ost->st_mode = st->st_mode; 1064 ost->st_nlink = st->st_nlink; 1065 ost->st_uid = st->st_uid; 1066 ost->st_gid = st->st_gid; 1067 ost->st_rdev = st->st_rdev; 1068 if (st->st_size < (quad_t)1 << 32) 1069 ost->st_size = st->st_size; 1070 else 1071 ost->st_size = -2; 1072 ost->st_atime = st->st_atime; 1073 ost->st_mtime = st->st_mtime; 1074 ost->st_ctime = st->st_ctime; 1075 ost->st_blksize = st->st_blksize; 1076 ost->st_blocks = st->st_blocks; 1077 ost->st_flags = st->st_flags; 1078 ost->st_gen = st->st_gen; 1079 } 1080 #endif /* COMPAT_43 || COMPAT_SUNOS */ 1081 1082 /* 1083 * Get file status; this version follows links. 1084 */ 1085 struct stat_args { 1086 char *path; 1087 struct stat *ub; 1088 }; 1089 /* ARGSUSED */ 1090 stat(p, uap, retval) 1091 struct proc *p; 1092 register struct stat_args *uap; 1093 int *retval; 1094 { 1095 struct stat sb; 1096 int error; 1097 struct nameidata nd; 1098 1099 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 1100 if (error = namei(&nd)) 1101 return (error); 1102 error = vn_stat(nd.ni_vp, &sb, p); 1103 vput(nd.ni_vp); 1104 if (error) 1105 return (error); 1106 error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); 1107 return (error); 1108 } 1109 1110 /* 1111 * Get file status; this version does not follow links. 1112 */ 1113 struct lstat_args { 1114 char *path; 1115 struct stat *ub; 1116 }; 1117 /* ARGSUSED */ 1118 lstat(p, uap, retval) 1119 struct proc *p; 1120 register struct lstat_args *uap; 1121 int *retval; 1122 { 1123 int error; 1124 struct vnode *vp, *dvp; 1125 struct stat sb, sb1; 1126 struct nameidata nd; 1127 1128 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE, 1129 uap->path, p); 1130 if (error = namei(&nd)) 1131 return (error); 1132 /* 1133 * For symbolic links, always return the attributes of its 1134 * containing directory, except for mode, size, and links. 1135 */ 1136 vp = nd.ni_vp; 1137 dvp = nd.ni_dvp; 1138 if (vp->v_type != VLNK) { 1139 if (dvp == vp) 1140 vrele(dvp); 1141 else 1142 vput(dvp); 1143 error = vn_stat(vp, &sb, p); 1144 vput(vp); 1145 if (error) 1146 return (error); 1147 } else { 1148 error = vn_stat(dvp, &sb, p); 1149 vput(dvp); 1150 if (error) { 1151 vput(vp); 1152 return (error); 1153 } 1154 error = vn_stat(vp, &sb1, p); 1155 vput(vp); 1156 if (error) 1157 return (error); 1158 sb.st_mode &= ~S_IFDIR; 1159 sb.st_mode |= S_IFLNK; 1160 sb.st_nlink = sb1.st_nlink; 1161 sb.st_size = sb1.st_size; 1162 sb.st_blocks = sb1.st_blocks; 1163 } 1164 error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); 1165 return (error); 1166 } 1167 1168 /* 1169 * Get configurable pathname variables. 1170 */ 1171 struct pathconf_args { 1172 char *path; 1173 int name; 1174 }; 1175 /* ARGSUSED */ 1176 pathconf(p, uap, retval) 1177 struct proc *p; 1178 register struct pathconf_args *uap; 1179 int *retval; 1180 { 1181 int error; 1182 struct nameidata nd; 1183 1184 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 1185 if (error = namei(&nd)) 1186 return (error); 1187 error = VOP_PATHCONF(nd.ni_vp, uap->name, retval); 1188 vput(nd.ni_vp); 1189 return (error); 1190 } 1191 1192 /* 1193 * Return target name of a symbolic link. 1194 */ 1195 struct readlink_args { 1196 char *path; 1197 char *buf; 1198 int count; 1199 }; 1200 /* ARGSUSED */ 1201 readlink(p, uap, retval) 1202 struct proc *p; 1203 register struct readlink_args *uap; 1204 int *retval; 1205 { 1206 register struct vnode *vp; 1207 struct iovec aiov; 1208 struct uio auio; 1209 int error; 1210 struct nameidata nd; 1211 1212 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 1213 if (error = namei(&nd)) 1214 return (error); 1215 vp = nd.ni_vp; 1216 if (vp->v_type != VLNK) 1217 error = EINVAL; 1218 else { 1219 aiov.iov_base = uap->buf; 1220 aiov.iov_len = uap->count; 1221 auio.uio_iov = &aiov; 1222 auio.uio_iovcnt = 1; 1223 auio.uio_offset = 0; 1224 auio.uio_rw = UIO_READ; 1225 auio.uio_segflg = UIO_USERSPACE; 1226 auio.uio_procp = p; 1227 auio.uio_resid = uap->count; 1228 error = VOP_READLINK(vp, &auio, p->p_ucred); 1229 } 1230 vput(vp); 1231 *retval = uap->count - auio.uio_resid; 1232 return (error); 1233 } 1234 1235 /* 1236 * Change flags of a file given a path name. 1237 */ 1238 struct chflags_args { 1239 char *path; 1240 int flags; 1241 }; 1242 /* ARGSUSED */ 1243 chflags(p, uap, retval) 1244 struct proc *p; 1245 register struct chflags_args *uap; 1246 int *retval; 1247 { 1248 register struct vnode *vp; 1249 struct vattr vattr; 1250 int error; 1251 struct nameidata nd; 1252 1253 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 1254 if (error = namei(&nd)) 1255 return (error); 1256 vp = nd.ni_vp; 1257 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1258 VOP_LOCK(vp); 1259 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1260 error = EROFS; 1261 else { 1262 VATTR_NULL(&vattr); 1263 vattr.va_flags = uap->flags; 1264 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1265 } 1266 vput(vp); 1267 return (error); 1268 } 1269 1270 /* 1271 * Change flags of a file given a file descriptor. 1272 */ 1273 struct fchflags_args { 1274 int fd; 1275 int flags; 1276 }; 1277 /* ARGSUSED */ 1278 fchflags(p, uap, retval) 1279 struct proc *p; 1280 register struct fchflags_args *uap; 1281 int *retval; 1282 { 1283 struct vattr vattr; 1284 struct vnode *vp; 1285 struct file *fp; 1286 int error; 1287 1288 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1289 return (error); 1290 vp = (struct vnode *)fp->f_data; 1291 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1292 VOP_LOCK(vp); 1293 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1294 error = EROFS; 1295 else { 1296 VATTR_NULL(&vattr); 1297 vattr.va_flags = uap->flags; 1298 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1299 } 1300 VOP_UNLOCK(vp); 1301 return (error); 1302 } 1303 1304 /* 1305 * Change mode of a file given path name. 1306 */ 1307 struct chmod_args { 1308 char *path; 1309 int mode; 1310 }; 1311 /* ARGSUSED */ 1312 chmod(p, uap, retval) 1313 struct proc *p; 1314 register struct chmod_args *uap; 1315 int *retval; 1316 { 1317 register struct vnode *vp; 1318 struct vattr vattr; 1319 int error; 1320 struct nameidata nd; 1321 1322 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 1323 if (error = namei(&nd)) 1324 return (error); 1325 vp = nd.ni_vp; 1326 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1327 VOP_LOCK(vp); 1328 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1329 error = EROFS; 1330 else { 1331 VATTR_NULL(&vattr); 1332 vattr.va_mode = uap->mode & ALLPERMS; 1333 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1334 } 1335 vput(vp); 1336 return (error); 1337 } 1338 1339 /* 1340 * Change mode of a file given a file descriptor. 1341 */ 1342 struct fchmod_args { 1343 int fd; 1344 int mode; 1345 }; 1346 /* ARGSUSED */ 1347 fchmod(p, uap, retval) 1348 struct proc *p; 1349 register struct fchmod_args *uap; 1350 int *retval; 1351 { 1352 struct vattr vattr; 1353 struct vnode *vp; 1354 struct file *fp; 1355 int error; 1356 1357 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1358 return (error); 1359 vp = (struct vnode *)fp->f_data; 1360 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1361 VOP_LOCK(vp); 1362 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1363 error = EROFS; 1364 else { 1365 VATTR_NULL(&vattr); 1366 vattr.va_mode = uap->mode & ALLPERMS; 1367 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1368 } 1369 VOP_UNLOCK(vp); 1370 return (error); 1371 } 1372 1373 /* 1374 * Set ownership given a path name. 1375 */ 1376 struct chown_args { 1377 char *path; 1378 int uid; 1379 int gid; 1380 }; 1381 /* ARGSUSED */ 1382 chown(p, uap, retval) 1383 struct proc *p; 1384 register struct chown_args *uap; 1385 int *retval; 1386 { 1387 register struct vnode *vp; 1388 struct vattr vattr; 1389 int error; 1390 struct nameidata nd; 1391 1392 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, p); 1393 if (error = namei(&nd)) 1394 return (error); 1395 vp = nd.ni_vp; 1396 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1397 VOP_LOCK(vp); 1398 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1399 error = EROFS; 1400 else { 1401 VATTR_NULL(&vattr); 1402 vattr.va_uid = uap->uid; 1403 vattr.va_gid = uap->gid; 1404 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1405 } 1406 vput(vp); 1407 return (error); 1408 } 1409 1410 /* 1411 * Set ownership given a file descriptor. 1412 */ 1413 struct fchown_args { 1414 int fd; 1415 int uid; 1416 int gid; 1417 }; 1418 /* ARGSUSED */ 1419 fchown(p, uap, retval) 1420 struct proc *p; 1421 register struct fchown_args *uap; 1422 int *retval; 1423 { 1424 struct vattr vattr; 1425 struct vnode *vp; 1426 struct file *fp; 1427 int error; 1428 1429 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1430 return (error); 1431 vp = (struct vnode *)fp->f_data; 1432 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1433 VOP_LOCK(vp); 1434 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1435 error = EROFS; 1436 else { 1437 VATTR_NULL(&vattr); 1438 vattr.va_uid = uap->uid; 1439 vattr.va_gid = uap->gid; 1440 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1441 } 1442 VOP_UNLOCK(vp); 1443 return (error); 1444 } 1445 1446 /* 1447 * Set the access and modification times of a file. 1448 */ 1449 struct utimes_args { 1450 char *path; 1451 struct timeval *tptr; 1452 }; 1453 /* ARGSUSED */ 1454 utimes(p, uap, retval) 1455 struct proc *p; 1456 register struct utimes_args *uap; 1457 int *retval; 1458 { 1459 register struct vnode *vp; 1460 struct timeval tv[2]; 1461 struct vattr vattr; 1462 int error; 1463 struct nameidata nd; 1464 1465 VATTR_NULL(&vattr); 1466 if (uap->tptr == NULL) { 1467 microtime(&tv[0]); 1468 tv[1] = tv[0]; 1469 vattr.va_vaflags |= VA_UTIMES_NULL; 1470 } else if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv))) 1471 return (error); 1472 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 1473 if (error = namei(&nd)) 1474 return (error); 1475 vp = nd.ni_vp; 1476 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1477 VOP_LOCK(vp); 1478 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1479 error = EROFS; 1480 else { 1481 vattr.va_atime.ts_sec = tv[0].tv_sec; 1482 vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000; 1483 vattr.va_mtime.ts_sec = tv[1].tv_sec; 1484 vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000; 1485 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1486 } 1487 vput(vp); 1488 return (error); 1489 } 1490 1491 /* 1492 * Truncate a file given its path name. 1493 */ 1494 struct truncate_args { 1495 char *path; 1496 int pad; 1497 off_t length; 1498 }; 1499 /* ARGSUSED */ 1500 truncate(p, uap, retval) 1501 struct proc *p; 1502 register struct truncate_args *uap; 1503 int *retval; 1504 { 1505 register struct vnode *vp; 1506 struct vattr vattr; 1507 int error; 1508 struct nameidata nd; 1509 1510 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 1511 if (error = namei(&nd)) 1512 return (error); 1513 vp = nd.ni_vp; 1514 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1515 VOP_LOCK(vp); 1516 if (vp->v_type == VDIR) 1517 error = EISDIR; 1518 else if ((error = vn_writechk(vp)) == 0 && 1519 (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) { 1520 VATTR_NULL(&vattr); 1521 vattr.va_size = uap->length; 1522 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1523 } 1524 vput(vp); 1525 return (error); 1526 } 1527 1528 /* 1529 * Truncate a file given a file descriptor. 1530 */ 1531 struct ftruncate_args { 1532 int fd; 1533 int pad; 1534 off_t length; 1535 }; 1536 /* ARGSUSED */ 1537 ftruncate(p, uap, retval) 1538 struct proc *p; 1539 register struct ftruncate_args *uap; 1540 int *retval; 1541 { 1542 struct vattr vattr; 1543 struct vnode *vp; 1544 struct file *fp; 1545 int error; 1546 1547 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1548 return (error); 1549 if ((fp->f_flag & FWRITE) == 0) 1550 return (EINVAL); 1551 vp = (struct vnode *)fp->f_data; 1552 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1553 VOP_LOCK(vp); 1554 if (vp->v_type == VDIR) 1555 error = EISDIR; 1556 else if ((error = vn_writechk(vp)) == 0) { 1557 VATTR_NULL(&vattr); 1558 vattr.va_size = uap->length; 1559 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p); 1560 } 1561 VOP_UNLOCK(vp); 1562 return (error); 1563 } 1564 1565 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1566 /* 1567 * Truncate a file given its path name. 1568 */ 1569 struct otruncate_args { 1570 char *path; 1571 long length; 1572 }; 1573 /* ARGSUSED */ 1574 otruncate(p, uap, retval) 1575 struct proc *p; 1576 register struct otruncate_args *uap; 1577 int *retval; 1578 { 1579 struct truncate_args nuap; 1580 1581 nuap.path = uap->path; 1582 nuap.length = uap->length; 1583 return (truncate(p, &nuap, retval)); 1584 } 1585 1586 /* 1587 * Truncate a file given a file descriptor. 1588 */ 1589 struct oftruncate_args { 1590 int fd; 1591 long length; 1592 }; 1593 /* ARGSUSED */ 1594 oftruncate(p, uap, retval) 1595 struct proc *p; 1596 register struct oftruncate_args *uap; 1597 int *retval; 1598 { 1599 struct ftruncate_args nuap; 1600 1601 nuap.fd = uap->fd; 1602 nuap.length = uap->length; 1603 return (ftruncate(p, &nuap, retval)); 1604 } 1605 #endif /* COMPAT_43 || COMPAT_SUNOS */ 1606 1607 /* 1608 * Sync an open file. 1609 */ 1610 struct fsync_args { 1611 int fd; 1612 }; 1613 /* ARGSUSED */ 1614 fsync(p, uap, retval) 1615 struct proc *p; 1616 struct fsync_args *uap; 1617 int *retval; 1618 { 1619 register struct vnode *vp; 1620 struct file *fp; 1621 int error; 1622 1623 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1624 return (error); 1625 vp = (struct vnode *)fp->f_data; 1626 VOP_LOCK(vp); 1627 error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p); 1628 VOP_UNLOCK(vp); 1629 return (error); 1630 } 1631 1632 /* 1633 * Rename files. Source and destination must either both be directories, 1634 * or both not be directories. If target is a directory, it must be empty. 1635 */ 1636 struct rename_args { 1637 char *from; 1638 char *to; 1639 }; 1640 /* ARGSUSED */ 1641 rename(p, uap, retval) 1642 struct proc *p; 1643 register struct rename_args *uap; 1644 int *retval; 1645 { 1646 register struct vnode *tvp, *fvp, *tdvp; 1647 struct nameidata fromnd, tond; 1648 int error; 1649 1650 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE, 1651 uap->from, p); 1652 if (error = namei(&fromnd)) 1653 return (error); 1654 fvp = fromnd.ni_vp; 1655 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART, 1656 UIO_USERSPACE, uap->to, p); 1657 if (error = namei(&tond)) { 1658 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 1659 vrele(fromnd.ni_dvp); 1660 vrele(fvp); 1661 goto out1; 1662 } 1663 tdvp = tond.ni_dvp; 1664 tvp = tond.ni_vp; 1665 if (tvp != NULL) { 1666 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 1667 error = ENOTDIR; 1668 goto out; 1669 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 1670 error = EISDIR; 1671 goto out; 1672 } 1673 } 1674 if (fvp == tdvp) 1675 error = EINVAL; 1676 /* 1677 * If source is the same as the destination (that is the 1678 * same inode number with the same name in the same directory), 1679 * then there is nothing to do. 1680 */ 1681 if (fvp == tvp && fromnd.ni_dvp == tdvp && 1682 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen && 1683 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr, 1684 fromnd.ni_cnd.cn_namelen)) 1685 error = -1; 1686 out: 1687 if (!error) { 1688 LEASE_CHECK(tdvp, p, p->p_ucred, LEASE_WRITE); 1689 if (fromnd.ni_dvp != tdvp) 1690 LEASE_CHECK(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1691 if (tvp) 1692 LEASE_CHECK(tvp, p, p->p_ucred, LEASE_WRITE); 1693 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, 1694 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); 1695 } else { 1696 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd); 1697 if (tdvp == tvp) 1698 vrele(tdvp); 1699 else 1700 vput(tdvp); 1701 if (tvp) 1702 vput(tvp); 1703 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 1704 vrele(fromnd.ni_dvp); 1705 vrele(fvp); 1706 } 1707 vrele(tond.ni_startdir); 1708 FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI); 1709 out1: 1710 vrele(fromnd.ni_startdir); 1711 FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI); 1712 if (error == -1) 1713 return (0); 1714 return (error); 1715 } 1716 1717 /* 1718 * Make a directory file. 1719 */ 1720 struct mkdir_args { 1721 char *path; 1722 int mode; 1723 }; 1724 /* ARGSUSED */ 1725 mkdir(p, uap, retval) 1726 struct proc *p; 1727 register struct mkdir_args *uap; 1728 int *retval; 1729 { 1730 register struct vnode *vp; 1731 struct vattr vattr; 1732 int error; 1733 struct nameidata nd; 1734 1735 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p); 1736 if (error = namei(&nd)) 1737 return (error); 1738 vp = nd.ni_vp; 1739 if (vp != NULL) { 1740 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1741 if (nd.ni_dvp == vp) 1742 vrele(nd.ni_dvp); 1743 else 1744 vput(nd.ni_dvp); 1745 vrele(vp); 1746 return (EEXIST); 1747 } 1748 VATTR_NULL(&vattr); 1749 vattr.va_type = VDIR; 1750 vattr.va_mode = (uap->mode & ACCESSPERMS) &~ p->p_fd->fd_cmask; 1751 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1752 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 1753 if (!error) 1754 vput(nd.ni_vp); 1755 return (error); 1756 } 1757 1758 /* 1759 * Remove a directory file. 1760 */ 1761 struct rmdir_args { 1762 char *path; 1763 }; 1764 /* ARGSUSED */ 1765 rmdir(p, uap, retval) 1766 struct proc *p; 1767 struct rmdir_args *uap; 1768 int *retval; 1769 { 1770 register struct vnode *vp; 1771 int error; 1772 struct nameidata nd; 1773 1774 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, uap->path, p); 1775 if (error = namei(&nd)) 1776 return (error); 1777 vp = nd.ni_vp; 1778 if (vp->v_type != VDIR) { 1779 error = ENOTDIR; 1780 goto out; 1781 } 1782 /* 1783 * No rmdir "." please. 1784 */ 1785 if (nd.ni_dvp == vp) { 1786 error = EINVAL; 1787 goto out; 1788 } 1789 /* 1790 * The root of a mounted filesystem cannot be deleted. 1791 */ 1792 if (vp->v_flag & VROOT) 1793 error = EBUSY; 1794 out: 1795 if (!error) { 1796 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1797 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1798 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 1799 } else { 1800 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1801 if (nd.ni_dvp == vp) 1802 vrele(nd.ni_dvp); 1803 else 1804 vput(nd.ni_dvp); 1805 vput(vp); 1806 } 1807 return (error); 1808 } 1809 1810 #ifdef COMPAT_43 1811 /* 1812 * Read a block of directory entries in a file system independent format. 1813 */ 1814 struct ogetdirentries_args { 1815 int fd; 1816 char *buf; 1817 u_int count; 1818 long *basep; 1819 }; 1820 ogetdirentries(p, uap, retval) 1821 struct proc *p; 1822 register struct ogetdirentries_args *uap; 1823 int *retval; 1824 { 1825 register struct vnode *vp; 1826 struct file *fp; 1827 struct uio auio, kuio; 1828 struct iovec aiov, kiov; 1829 struct dirent *dp, *edp; 1830 caddr_t dirbuf; 1831 int error, readcnt; 1832 long loff; 1833 1834 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1835 return (error); 1836 if ((fp->f_flag & FREAD) == 0) 1837 return (EBADF); 1838 vp = (struct vnode *)fp->f_data; 1839 if (vp->v_type != VDIR) 1840 return (EINVAL); 1841 aiov.iov_base = uap->buf; 1842 aiov.iov_len = uap->count; 1843 auio.uio_iov = &aiov; 1844 auio.uio_iovcnt = 1; 1845 auio.uio_rw = UIO_READ; 1846 auio.uio_segflg = UIO_USERSPACE; 1847 auio.uio_procp = p; 1848 auio.uio_resid = uap->count; 1849 VOP_LOCK(vp); 1850 loff = auio.uio_offset = fp->f_offset; 1851 # if (BYTE_ORDER != LITTLE_ENDIAN) 1852 if (vp->v_mount->mnt_maxsymlinklen <= 0) { 1853 error = VOP_READDIR(vp, &auio, fp->f_cred); 1854 fp->f_offset = auio.uio_offset; 1855 } else 1856 # endif 1857 { 1858 kuio = auio; 1859 kuio.uio_iov = &kiov; 1860 kuio.uio_segflg = UIO_SYSSPACE; 1861 kiov.iov_len = uap->count; 1862 MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK); 1863 kiov.iov_base = dirbuf; 1864 error = VOP_READDIR(vp, &kuio, fp->f_cred); 1865 fp->f_offset = kuio.uio_offset; 1866 if (error == 0) { 1867 readcnt = uap->count - kuio.uio_resid; 1868 edp = (struct dirent *)&dirbuf[readcnt]; 1869 for (dp = (struct dirent *)dirbuf; dp < edp; ) { 1870 # if (BYTE_ORDER == LITTLE_ENDIAN) 1871 /* 1872 * The expected low byte of 1873 * dp->d_namlen is our dp->d_type. 1874 * The high MBZ byte of dp->d_namlen 1875 * is our dp->d_namlen. 1876 */ 1877 dp->d_type = dp->d_namlen; 1878 dp->d_namlen = 0; 1879 # else 1880 /* 1881 * The dp->d_type is the high byte 1882 * of the expected dp->d_namlen, 1883 * so must be zero'ed. 1884 */ 1885 dp->d_type = 0; 1886 # endif 1887 if (dp->d_reclen > 0) { 1888 dp = (struct dirent *) 1889 ((char *)dp + dp->d_reclen); 1890 } else { 1891 error = EIO; 1892 break; 1893 } 1894 } 1895 if (dp >= edp) 1896 error = uiomove(dirbuf, readcnt, &auio); 1897 } 1898 FREE(dirbuf, M_TEMP); 1899 } 1900 VOP_UNLOCK(vp); 1901 if (error) 1902 return (error); 1903 error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long)); 1904 *retval = uap->count - auio.uio_resid; 1905 return (error); 1906 } 1907 #endif 1908 1909 /* 1910 * Read a block of directory entries in a file system independent format. 1911 */ 1912 struct getdirentries_args { 1913 int fd; 1914 char *buf; 1915 u_int count; 1916 long *basep; 1917 }; 1918 getdirentries(p, uap, retval) 1919 struct proc *p; 1920 register struct getdirentries_args *uap; 1921 int *retval; 1922 { 1923 register struct vnode *vp; 1924 struct file *fp; 1925 struct uio auio; 1926 struct iovec aiov; 1927 long loff; 1928 int error; 1929 1930 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1931 return (error); 1932 if ((fp->f_flag & FREAD) == 0) 1933 return (EBADF); 1934 vp = (struct vnode *)fp->f_data; 1935 unionread: 1936 if (vp->v_type != VDIR) 1937 return (EINVAL); 1938 aiov.iov_base = uap->buf; 1939 aiov.iov_len = uap->count; 1940 auio.uio_iov = &aiov; 1941 auio.uio_iovcnt = 1; 1942 auio.uio_rw = UIO_READ; 1943 auio.uio_segflg = UIO_USERSPACE; 1944 auio.uio_procp = p; 1945 auio.uio_resid = uap->count; 1946 VOP_LOCK(vp); 1947 loff = auio.uio_offset = fp->f_offset; 1948 error = VOP_READDIR(vp, &auio, fp->f_cred); 1949 fp->f_offset = auio.uio_offset; 1950 VOP_UNLOCK(vp); 1951 if (error) 1952 return (error); 1953 if ((uap->count == auio.uio_resid) && 1954 (vp->v_flag & VROOT) && 1955 (vp->v_mount->mnt_flag & MNT_UNION)) { 1956 struct vnode *tvp = vp; 1957 vp = vp->v_mount->mnt_vnodecovered; 1958 VREF(vp); 1959 fp->f_data = (caddr_t) vp; 1960 fp->f_offset = 0; 1961 vrele(tvp); 1962 goto unionread; 1963 } 1964 error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long)); 1965 *retval = uap->count - auio.uio_resid; 1966 return (error); 1967 } 1968 1969 /* 1970 * Set the mode mask for creation of filesystem nodes. 1971 */ 1972 struct umask_args { 1973 int newmask; 1974 }; 1975 mode_t /* XXX */ 1976 umask(p, uap, retval) 1977 struct proc *p; 1978 struct umask_args *uap; 1979 int *retval; 1980 { 1981 register struct filedesc *fdp; 1982 1983 fdp = p->p_fd; 1984 *retval = fdp->fd_cmask; 1985 fdp->fd_cmask = uap->newmask & ALLPERMS; 1986 return (0); 1987 } 1988 1989 /* 1990 * Void all references to file by ripping underlying filesystem 1991 * away from vnode. 1992 */ 1993 struct revoke_args { 1994 char *path; 1995 }; 1996 /* ARGSUSED */ 1997 revoke(p, uap, retval) 1998 struct proc *p; 1999 register struct revoke_args *uap; 2000 int *retval; 2001 { 2002 register struct vnode *vp; 2003 struct vattr vattr; 2004 int error; 2005 struct nameidata nd; 2006 2007 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 2008 if (error = namei(&nd)) 2009 return (error); 2010 vp = nd.ni_vp; 2011 if (vp->v_type != VCHR && vp->v_type != VBLK) { 2012 error = EINVAL; 2013 goto out; 2014 } 2015 if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) 2016 goto out; 2017 if (p->p_ucred->cr_uid != vattr.va_uid && 2018 (error = suser(p->p_ucred, &p->p_acflag))) 2019 goto out; 2020 if (vp->v_usecount > 1 || (vp->v_flag & VALIASED)) 2021 vgoneall(vp); 2022 out: 2023 vrele(vp); 2024 return (error); 2025 } 2026 2027 /* 2028 * Convert a user file descriptor to a kernel file entry. 2029 */ 2030 getvnode(fdp, fd, fpp) 2031 struct filedesc *fdp; 2032 struct file **fpp; 2033 int fd; 2034 { 2035 struct file *fp; 2036 2037 if ((u_int)fd >= fdp->fd_nfiles || 2038 (fp = fdp->fd_ofiles[fd]) == NULL) 2039 return (EBADF); 2040 if (fp->f_type != DTYPE_VNODE) 2041 return (EINVAL); 2042 *fpp = fp; 2043 return (0); 2044 } 2045