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