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