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