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