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