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