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