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.71 (Berkeley) 05/30/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 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 crfree(fp->f_cred); 573 fp->f_count--; 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 if (fmode & (O_EXLOCK | O_SHLOCK)) { 586 lf.l_whence = SEEK_SET; 587 lf.l_start = 0; 588 lf.l_len = 0; 589 if (fmode & O_EXLOCK) 590 lf.l_type = F_WRLCK; 591 else 592 lf.l_type = F_RDLCK; 593 type = F_FLOCK; 594 if ((fmode & FNONBLOCK) == 0) 595 type |= F_WAIT; 596 if (error = 597 VOP_ADVLOCK(ndp->ni_vp, (caddr_t)fp, F_SETLK, &lf, type)) { 598 vput(ndp->ni_vp); 599 crfree(fp->f_cred); 600 fp->f_count--; 601 fdp->fd_ofiles[indx] = NULL; 602 return (error); 603 } 604 } 605 VOP_UNLOCK(ndp->ni_vp); 606 fp->f_flag = fmode & FMASK; 607 fp->f_type = DTYPE_VNODE; 608 fp->f_ops = &vnops; 609 fp->f_data = (caddr_t)ndp->ni_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 error = VOP_MKNOD(ndp, &vattr, p->p_ucred, p); 692 } else { 693 VOP_ABORTOP(ndp); 694 if (ndp->ni_dvp == vp) 695 vrele(ndp->ni_dvp); 696 else 697 vput(ndp->ni_dvp); 698 if (vp) 699 vrele(vp); 700 } 701 return (error); 702 } 703 704 /* 705 * Mkfifo system call. 706 */ 707 /* ARGSUSED */ 708 mkfifo(p, uap, retval) 709 struct proc *p; 710 register struct args { 711 char *fname; 712 int fmode; 713 } *uap; 714 int *retval; 715 { 716 register struct nameidata *ndp; 717 struct vattr vattr; 718 int error; 719 struct nameidata nd; 720 721 #ifndef FIFO 722 return (EOPNOTSUPP); 723 #else 724 ndp = &nd; 725 ndp->ni_nameiop = CREATE | LOCKPARENT; 726 ndp->ni_segflg = UIO_USERSPACE; 727 ndp->ni_dirp = uap->fname; 728 if (error = namei(ndp, p)) 729 return (error); 730 if (ndp->ni_vp != NULL) { 731 VOP_ABORTOP(ndp); 732 if (ndp->ni_dvp == ndp->ni_vp) 733 vrele(ndp->ni_dvp); 734 else 735 vput(ndp->ni_dvp); 736 vrele(ndp->ni_vp); 737 return (EEXIST); 738 } 739 VATTR_NULL(&vattr); 740 vattr.va_type = VFIFO; 741 vattr.va_mode = (uap->fmode & 07777) &~ p->p_fd->fd_cmask; 742 return (VOP_MKNOD(ndp, &vattr, p->p_ucred, p)); 743 #endif /* FIFO */ 744 } 745 746 /* 747 * Link system call. 748 */ 749 /* ARGSUSED */ 750 link(p, uap, retval) 751 struct proc *p; 752 register struct args { 753 char *target; 754 char *linkname; 755 } *uap; 756 int *retval; 757 { 758 register struct nameidata *ndp; 759 register struct vnode *vp, *xp; 760 int error; 761 struct nameidata nd; 762 763 ndp = &nd; 764 ndp->ni_nameiop = LOOKUP | FOLLOW; 765 ndp->ni_segflg = UIO_USERSPACE; 766 ndp->ni_dirp = uap->target; 767 if (error = namei(ndp, p)) 768 return (error); 769 vp = ndp->ni_vp; 770 if (vp->v_type == VDIR && 771 (error = suser(p->p_ucred, &p->p_acflag))) 772 goto out1; 773 ndp->ni_nameiop = CREATE | LOCKPARENT; 774 ndp->ni_dirp = (caddr_t)uap->linkname; 775 if (error = namei(ndp, p)) 776 goto out1; 777 xp = ndp->ni_vp; 778 if (xp != NULL) { 779 error = EEXIST; 780 goto out; 781 } 782 xp = ndp->ni_dvp; 783 if (vp->v_mount != xp->v_mount) 784 error = EXDEV; 785 out: 786 if (!error) { 787 error = VOP_LINK(vp, ndp, p); 788 } else { 789 VOP_ABORTOP(ndp); 790 if (ndp->ni_dvp == ndp->ni_vp) 791 vrele(ndp->ni_dvp); 792 else 793 vput(ndp->ni_dvp); 794 if (ndp->ni_vp) 795 vrele(ndp->ni_vp); 796 } 797 out1: 798 vrele(vp); 799 return (error); 800 } 801 802 /* 803 * Make a symbolic link. 804 */ 805 /* ARGSUSED */ 806 symlink(p, uap, retval) 807 struct proc *p; 808 register struct args { 809 char *target; 810 char *linkname; 811 } *uap; 812 int *retval; 813 { 814 register struct nameidata *ndp; 815 struct vattr vattr; 816 char *target; 817 int error; 818 struct nameidata nd; 819 820 ndp = &nd; 821 ndp->ni_segflg = UIO_USERSPACE; 822 ndp->ni_dirp = uap->linkname; 823 MALLOC(target, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); 824 if (error = copyinstr(uap->target, target, MAXPATHLEN, (u_int *)0)) 825 goto out; 826 ndp->ni_nameiop = CREATE | LOCKPARENT; 827 if (error = namei(ndp, p)) 828 goto out; 829 if (ndp->ni_vp) { 830 VOP_ABORTOP(ndp); 831 if (ndp->ni_dvp == ndp->ni_vp) 832 vrele(ndp->ni_dvp); 833 else 834 vput(ndp->ni_dvp); 835 vrele(ndp->ni_vp); 836 error = EEXIST; 837 goto out; 838 } 839 VATTR_NULL(&vattr); 840 vattr.va_mode = 0777 &~ p->p_fd->fd_cmask; 841 error = VOP_SYMLINK(ndp, &vattr, target, p); 842 out: 843 FREE(target, M_NAMEI); 844 return (error); 845 } 846 847 /* 848 * Delete a name from the filesystem. 849 */ 850 /* ARGSUSED */ 851 unlink(p, uap, retval) 852 struct proc *p; 853 struct args { 854 char *fname; 855 } *uap; 856 int *retval; 857 { 858 register struct nameidata *ndp; 859 register struct vnode *vp; 860 int error; 861 struct nameidata nd; 862 863 ndp = &nd; 864 ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF; 865 ndp->ni_segflg = UIO_USERSPACE; 866 ndp->ni_dirp = uap->fname; 867 if (error = namei(ndp, p)) 868 return (error); 869 vp = ndp->ni_vp; 870 if (vp->v_type == VDIR && 871 (error = suser(p->p_ucred, &p->p_acflag))) 872 goto out; 873 /* 874 * The root of a mounted filesystem cannot be deleted. 875 */ 876 if (vp->v_flag & VROOT) { 877 error = EBUSY; 878 goto out; 879 } 880 (void) vnode_pager_uncache(vp); 881 out: 882 if (!error) { 883 error = VOP_REMOVE(ndp, p); 884 } else { 885 VOP_ABORTOP(ndp); 886 if (ndp->ni_dvp == vp) 887 vrele(ndp->ni_dvp); 888 else 889 vput(ndp->ni_dvp); 890 vput(vp); 891 } 892 return (error); 893 } 894 895 /* 896 * Seek system call. 897 */ 898 lseek(p, uap, retval) 899 struct proc *p; 900 register struct args { 901 int fdes; 902 off_t off; 903 int sbase; 904 } *uap; 905 off_t *retval; 906 { 907 struct ucred *cred = p->p_ucred; 908 register struct filedesc *fdp = p->p_fd; 909 register struct file *fp; 910 struct vattr vattr; 911 int error; 912 913 if ((unsigned)uap->fdes >= fdp->fd_nfiles || 914 (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 915 return (EBADF); 916 if (fp->f_type != DTYPE_VNODE) 917 return (ESPIPE); 918 switch (uap->sbase) { 919 920 case L_INCR: 921 fp->f_offset += uap->off; 922 break; 923 924 case L_XTND: 925 if (error = VOP_GETATTR((struct vnode *)fp->f_data, 926 &vattr, cred, p)) 927 return (error); 928 fp->f_offset = uap->off + vattr.va_size; 929 break; 930 931 case L_SET: 932 fp->f_offset = uap->off; 933 break; 934 935 default: 936 return (EINVAL); 937 } 938 *retval = fp->f_offset; 939 return (0); 940 } 941 942 /* 943 * Check access permissions. 944 */ 945 /* ARGSUSED */ 946 saccess(p, uap, retval) 947 struct proc *p; 948 register struct args { 949 char *fname; 950 int fmode; 951 } *uap; 952 int *retval; 953 { 954 register struct nameidata *ndp; 955 register struct ucred *cred = p->p_ucred; 956 register struct vnode *vp; 957 int error, mode, svuid, svgid; 958 struct nameidata nd; 959 960 ndp = &nd; 961 svuid = cred->cr_uid; 962 svgid = cred->cr_groups[0]; 963 cred->cr_uid = p->p_cred->p_ruid; 964 cred->cr_groups[0] = p->p_cred->p_rgid; 965 ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 966 ndp->ni_segflg = UIO_USERSPACE; 967 ndp->ni_dirp = uap->fname; 968 if (error = namei(ndp, p)) 969 goto out1; 970 vp = ndp->ni_vp; 971 /* 972 * fmode == 0 means only check for exist 973 */ 974 if (uap->fmode) { 975 mode = 0; 976 if (uap->fmode & R_OK) 977 mode |= VREAD; 978 if (uap->fmode & W_OK) 979 mode |= VWRITE; 980 if (uap->fmode & X_OK) 981 mode |= VEXEC; 982 if ((mode & VWRITE) == 0 || (error = vn_writechk(vp)) == 0) 983 error = VOP_ACCESS(vp, mode, cred, p); 984 } 985 vput(vp); 986 out1: 987 cred->cr_uid = svuid; 988 cred->cr_groups[0] = svgid; 989 return (error); 990 } 991 992 /* 993 * Stat system call. 994 * This version follows links. 995 */ 996 /* ARGSUSED */ 997 stat(p, uap, retval) 998 struct proc *p; 999 register struct args { 1000 char *fname; 1001 struct stat *ub; 1002 } *uap; 1003 int *retval; 1004 { 1005 register struct nameidata *ndp; 1006 struct stat sb; 1007 int error; 1008 struct nameidata nd; 1009 1010 ndp = &nd; 1011 ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; 1012 ndp->ni_segflg = UIO_USERSPACE; 1013 ndp->ni_dirp = uap->fname; 1014 if (error = namei(ndp, p)) 1015 return (error); 1016 error = vn_stat(ndp->ni_vp, &sb, p); 1017 vput(ndp->ni_vp); 1018 if (error) 1019 return (error); 1020 error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); 1021 return (error); 1022 } 1023 1024 /* 1025 * Lstat system call. 1026 * This version does not follow links. 1027 */ 1028 /* ARGSUSED */ 1029 lstat(p, uap, retval) 1030 struct proc *p; 1031 register struct args { 1032 char *fname; 1033 struct stat *ub; 1034 } *uap; 1035 int *retval; 1036 { 1037 register struct nameidata *ndp; 1038 struct stat sb; 1039 int error; 1040 struct nameidata nd; 1041 1042 ndp = &nd; 1043 ndp->ni_nameiop = LOOKUP | LOCKLEAF | NOFOLLOW; 1044 ndp->ni_segflg = UIO_USERSPACE; 1045 ndp->ni_dirp = uap->fname; 1046 if (error = namei(ndp, p)) 1047 return (error); 1048 error = vn_stat(ndp->ni_vp, &sb, p); 1049 vput(ndp->ni_vp); 1050 if (error) 1051 return (error); 1052 error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); 1053 return (error); 1054 } 1055 1056 /* 1057 * Return target name of a symbolic link. 1058 */ 1059 /* ARGSUSED */ 1060 readlink(p, uap, retval) 1061 struct proc *p; 1062 register struct args { 1063 char *name; 1064 char *buf; 1065 int count; 1066 } *uap; 1067 int *retval; 1068 { 1069 register struct nameidata *ndp; 1070 register struct vnode *vp; 1071 struct iovec aiov; 1072 struct uio auio; 1073 int error; 1074 struct nameidata nd; 1075 1076 ndp = &nd; 1077 ndp->ni_nameiop = LOOKUP | LOCKLEAF; 1078 ndp->ni_segflg = UIO_USERSPACE; 1079 ndp->ni_dirp = uap->name; 1080 if (error = namei(ndp, p)) 1081 return (error); 1082 vp = ndp->ni_vp; 1083 if (vp->v_type != VLNK) { 1084 error = EINVAL; 1085 goto out; 1086 } 1087 aiov.iov_base = uap->buf; 1088 aiov.iov_len = uap->count; 1089 auio.uio_iov = &aiov; 1090 auio.uio_iovcnt = 1; 1091 auio.uio_offset = 0; 1092 auio.uio_rw = UIO_READ; 1093 auio.uio_segflg = UIO_USERSPACE; 1094 auio.uio_procp = p; 1095 auio.uio_resid = uap->count; 1096 error = VOP_READLINK(vp, &auio, p->p_ucred); 1097 out: 1098 vput(vp); 1099 *retval = uap->count - auio.uio_resid; 1100 return (error); 1101 } 1102 1103 /* 1104 * Change flags of a file given path name. 1105 */ 1106 /* ARGSUSED */ 1107 chflags(p, uap, retval) 1108 struct proc *p; 1109 register struct args { 1110 char *fname; 1111 int flags; 1112 } *uap; 1113 int *retval; 1114 { 1115 register struct nameidata *ndp; 1116 register struct vnode *vp; 1117 struct vattr vattr; 1118 int error; 1119 struct nameidata nd; 1120 1121 ndp = &nd; 1122 ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 1123 ndp->ni_segflg = UIO_USERSPACE; 1124 ndp->ni_dirp = uap->fname; 1125 if (error = namei(ndp, p)) 1126 return (error); 1127 vp = ndp->ni_vp; 1128 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 1129 error = EROFS; 1130 goto out; 1131 } 1132 VATTR_NULL(&vattr); 1133 vattr.va_flags = uap->flags; 1134 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1135 out: 1136 vput(vp); 1137 return (error); 1138 } 1139 1140 /* 1141 * Change flags of a file given a file descriptor. 1142 */ 1143 /* ARGSUSED */ 1144 fchflags(p, uap, retval) 1145 struct proc *p; 1146 register struct args { 1147 int fd; 1148 int flags; 1149 } *uap; 1150 int *retval; 1151 { 1152 struct vattr vattr; 1153 struct vnode *vp; 1154 struct file *fp; 1155 int error; 1156 1157 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1158 return (error); 1159 vp = (struct vnode *)fp->f_data; 1160 VOP_LOCK(vp); 1161 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 1162 error = EROFS; 1163 goto out; 1164 } 1165 VATTR_NULL(&vattr); 1166 vattr.va_flags = uap->flags; 1167 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1168 out: 1169 VOP_UNLOCK(vp); 1170 return (error); 1171 } 1172 1173 /* 1174 * Change mode of a file given path name. 1175 */ 1176 /* ARGSUSED */ 1177 chmod(p, uap, retval) 1178 struct proc *p; 1179 register struct args { 1180 char *fname; 1181 int fmode; 1182 } *uap; 1183 int *retval; 1184 { 1185 register struct nameidata *ndp; 1186 register struct vnode *vp; 1187 struct vattr vattr; 1188 int error; 1189 struct nameidata nd; 1190 1191 ndp = &nd; 1192 ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 1193 ndp->ni_segflg = UIO_USERSPACE; 1194 ndp->ni_dirp = uap->fname; 1195 if (error = namei(ndp, p)) 1196 return (error); 1197 vp = ndp->ni_vp; 1198 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 1199 error = EROFS; 1200 goto out; 1201 } 1202 VATTR_NULL(&vattr); 1203 vattr.va_mode = uap->fmode & 07777; 1204 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1205 out: 1206 vput(vp); 1207 return (error); 1208 } 1209 1210 /* 1211 * Change mode of a file given a file descriptor. 1212 */ 1213 /* ARGSUSED */ 1214 fchmod(p, uap, retval) 1215 struct proc *p; 1216 register struct args { 1217 int fd; 1218 int fmode; 1219 } *uap; 1220 int *retval; 1221 { 1222 struct vattr vattr; 1223 struct vnode *vp; 1224 struct file *fp; 1225 int error; 1226 1227 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1228 return (error); 1229 vp = (struct vnode *)fp->f_data; 1230 VOP_LOCK(vp); 1231 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 1232 error = EROFS; 1233 goto out; 1234 } 1235 VATTR_NULL(&vattr); 1236 vattr.va_mode = uap->fmode & 07777; 1237 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1238 out: 1239 VOP_UNLOCK(vp); 1240 return (error); 1241 } 1242 1243 /* 1244 * Set ownership given a path name. 1245 */ 1246 /* ARGSUSED */ 1247 chown(p, uap, retval) 1248 struct proc *p; 1249 register struct args { 1250 char *fname; 1251 int uid; 1252 int gid; 1253 } *uap; 1254 int *retval; 1255 { 1256 register struct nameidata *ndp; 1257 register struct vnode *vp; 1258 struct vattr vattr; 1259 int error; 1260 struct nameidata nd; 1261 1262 ndp = &nd; 1263 ndp->ni_nameiop = LOOKUP | NOFOLLOW | LOCKLEAF; 1264 ndp->ni_segflg = UIO_USERSPACE; 1265 ndp->ni_dirp = uap->fname; 1266 if (error = namei(ndp, p)) 1267 return (error); 1268 vp = ndp->ni_vp; 1269 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 1270 error = EROFS; 1271 goto out; 1272 } 1273 VATTR_NULL(&vattr); 1274 vattr.va_uid = uap->uid; 1275 vattr.va_gid = uap->gid; 1276 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1277 out: 1278 vput(vp); 1279 return (error); 1280 } 1281 1282 /* 1283 * Set ownership given a file descriptor. 1284 */ 1285 /* ARGSUSED */ 1286 fchown(p, uap, retval) 1287 struct proc *p; 1288 register struct args { 1289 int fd; 1290 int uid; 1291 int gid; 1292 } *uap; 1293 int *retval; 1294 { 1295 struct vattr vattr; 1296 struct vnode *vp; 1297 struct file *fp; 1298 int error; 1299 1300 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1301 return (error); 1302 vp = (struct vnode *)fp->f_data; 1303 VOP_LOCK(vp); 1304 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 1305 error = EROFS; 1306 goto out; 1307 } 1308 VATTR_NULL(&vattr); 1309 vattr.va_uid = uap->uid; 1310 vattr.va_gid = uap->gid; 1311 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1312 out: 1313 VOP_UNLOCK(vp); 1314 return (error); 1315 } 1316 1317 /* 1318 * Set the access and modification times of a file. 1319 */ 1320 /* ARGSUSED */ 1321 utimes(p, uap, retval) 1322 struct proc *p; 1323 register struct args { 1324 char *fname; 1325 struct timeval *tptr; 1326 } *uap; 1327 int *retval; 1328 { 1329 register struct nameidata *ndp; 1330 register struct vnode *vp; 1331 struct timeval tv[2]; 1332 struct vattr vattr; 1333 int error; 1334 struct nameidata nd; 1335 1336 if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv))) 1337 return (error); 1338 ndp = &nd; 1339 ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 1340 ndp->ni_segflg = UIO_USERSPACE; 1341 ndp->ni_dirp = uap->fname; 1342 if (error = namei(ndp, p)) 1343 return (error); 1344 vp = ndp->ni_vp; 1345 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 1346 error = EROFS; 1347 goto out; 1348 } 1349 VATTR_NULL(&vattr); 1350 vattr.va_atime = tv[0]; 1351 vattr.va_mtime = tv[1]; 1352 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1353 out: 1354 vput(vp); 1355 return (error); 1356 } 1357 1358 /* 1359 * Truncate a file given its path name. 1360 */ 1361 /* ARGSUSED */ 1362 truncate(p, uap, retval) 1363 struct proc *p; 1364 register struct args { 1365 char *fname; 1366 off_t length; 1367 } *uap; 1368 int *retval; 1369 { 1370 register struct nameidata *ndp; 1371 register struct vnode *vp; 1372 struct vattr vattr; 1373 int error; 1374 struct nameidata nd; 1375 1376 ndp = &nd; 1377 ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 1378 ndp->ni_segflg = UIO_USERSPACE; 1379 ndp->ni_dirp = uap->fname; 1380 if (error = namei(ndp, p)) 1381 return (error); 1382 vp = ndp->ni_vp; 1383 if (vp->v_type == VDIR) { 1384 error = EISDIR; 1385 goto out; 1386 } 1387 if ((error = vn_writechk(vp)) || 1388 (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p))) 1389 goto out; 1390 VATTR_NULL(&vattr); 1391 vattr.va_size = uap->length; 1392 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1393 out: 1394 vput(vp); 1395 return (error); 1396 } 1397 1398 /* 1399 * Truncate a file given a file descriptor. 1400 */ 1401 /* ARGSUSED */ 1402 ftruncate(p, uap, retval) 1403 struct proc *p; 1404 register struct args { 1405 int fd; 1406 off_t length; 1407 } *uap; 1408 int *retval; 1409 { 1410 struct vattr vattr; 1411 struct vnode *vp; 1412 struct file *fp; 1413 int error; 1414 1415 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1416 return (error); 1417 if ((fp->f_flag & FWRITE) == 0) 1418 return (EINVAL); 1419 vp = (struct vnode *)fp->f_data; 1420 VOP_LOCK(vp); 1421 if (vp->v_type == VDIR) { 1422 error = EISDIR; 1423 goto out; 1424 } 1425 if (error = vn_writechk(vp)) 1426 goto out; 1427 VATTR_NULL(&vattr); 1428 vattr.va_size = uap->length; 1429 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p); 1430 out: 1431 VOP_UNLOCK(vp); 1432 return (error); 1433 } 1434 1435 /* 1436 * Synch an open file. 1437 */ 1438 /* ARGSUSED */ 1439 fsync(p, uap, retval) 1440 struct proc *p; 1441 struct args { 1442 int fd; 1443 } *uap; 1444 int *retval; 1445 { 1446 register struct vnode *vp; 1447 struct file *fp; 1448 int error; 1449 1450 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1451 return (error); 1452 vp = (struct vnode *)fp->f_data; 1453 VOP_LOCK(vp); 1454 error = VOP_FSYNC(vp, fp->f_flag, fp->f_cred, MNT_WAIT, p); 1455 VOP_UNLOCK(vp); 1456 return (error); 1457 } 1458 1459 /* 1460 * Rename system call. 1461 * 1462 * Source and destination must either both be directories, or both 1463 * not be directories. If target is a directory, it must be empty. 1464 */ 1465 /* ARGSUSED */ 1466 rename(p, uap, retval) 1467 struct proc *p; 1468 register struct args { 1469 char *from; 1470 char *to; 1471 } *uap; 1472 int *retval; 1473 { 1474 register struct vnode *tvp, *fvp, *tdvp; 1475 struct nameidata fromnd, tond; 1476 int error; 1477 1478 fromnd.ni_nameiop = DELETE | WANTPARENT | SAVESTART; 1479 fromnd.ni_segflg = UIO_USERSPACE; 1480 fromnd.ni_dirp = uap->from; 1481 if (error = namei(&fromnd, p)) 1482 return (error); 1483 fvp = fromnd.ni_vp; 1484 tond.ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART; 1485 tond.ni_segflg = UIO_USERSPACE; 1486 tond.ni_dirp = uap->to; 1487 if (error = namei(&tond, p)) { 1488 VOP_ABORTOP(&fromnd); 1489 vrele(fromnd.ni_dvp); 1490 vrele(fvp); 1491 goto out1; 1492 } 1493 tdvp = tond.ni_dvp; 1494 tvp = tond.ni_vp; 1495 if (tvp != NULL) { 1496 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 1497 error = ENOTDIR; 1498 goto out; 1499 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 1500 error = EISDIR; 1501 goto out; 1502 } 1503 if (fvp->v_mount != tvp->v_mount) { 1504 error = EXDEV; 1505 goto out; 1506 } 1507 } 1508 if (fvp->v_mount != tdvp->v_mount) { 1509 error = EXDEV; 1510 goto out; 1511 } 1512 if (fvp == tdvp) 1513 error = EINVAL; 1514 /* 1515 * If source is the same as the destination (that is the 1516 * same inode number with the same name in the same directory), 1517 * then there is nothing to do. 1518 */ 1519 if (fvp == tvp && fromnd.ni_dvp == tdvp && 1520 fromnd.ni_namelen == tond.ni_namelen && 1521 !bcmp(fromnd.ni_ptr, tond.ni_ptr, fromnd.ni_namelen)) 1522 error = -1; 1523 out: 1524 if (!error) { 1525 error = VOP_RENAME(&fromnd, &tond, p); 1526 } else { 1527 VOP_ABORTOP(&tond); 1528 if (tdvp == tvp) 1529 vrele(tdvp); 1530 else 1531 vput(tdvp); 1532 if (tvp) 1533 vput(tvp); 1534 VOP_ABORTOP(&fromnd); 1535 vrele(fromnd.ni_dvp); 1536 vrele(fvp); 1537 } 1538 vrele(tond.ni_startdir); 1539 FREE(tond.ni_pnbuf, M_NAMEI); 1540 out1: 1541 vrele(fromnd.ni_startdir); 1542 FREE(fromnd.ni_pnbuf, M_NAMEI); 1543 if (error == -1) 1544 return (0); 1545 return (error); 1546 } 1547 1548 /* 1549 * Mkdir system call. 1550 */ 1551 /* ARGSUSED */ 1552 mkdir(p, uap, retval) 1553 struct proc *p; 1554 register struct args { 1555 char *name; 1556 int dmode; 1557 } *uap; 1558 int *retval; 1559 { 1560 register struct nameidata *ndp; 1561 register struct vnode *vp; 1562 struct vattr vattr; 1563 int error; 1564 struct nameidata nd; 1565 1566 ndp = &nd; 1567 ndp->ni_nameiop = CREATE | LOCKPARENT; 1568 ndp->ni_segflg = UIO_USERSPACE; 1569 ndp->ni_dirp = uap->name; 1570 if (error = namei(ndp, p)) 1571 return (error); 1572 vp = ndp->ni_vp; 1573 if (vp != NULL) { 1574 VOP_ABORTOP(ndp); 1575 if (ndp->ni_dvp == vp) 1576 vrele(ndp->ni_dvp); 1577 else 1578 vput(ndp->ni_dvp); 1579 vrele(vp); 1580 return (EEXIST); 1581 } 1582 VATTR_NULL(&vattr); 1583 vattr.va_type = VDIR; 1584 vattr.va_mode = (uap->dmode & 0777) &~ p->p_fd->fd_cmask; 1585 error = VOP_MKDIR(ndp, &vattr, p); 1586 if (!error) 1587 vput(ndp->ni_vp); 1588 return (error); 1589 } 1590 1591 /* 1592 * Rmdir system call. 1593 */ 1594 /* ARGSUSED */ 1595 rmdir(p, uap, retval) 1596 struct proc *p; 1597 struct args { 1598 char *name; 1599 } *uap; 1600 int *retval; 1601 { 1602 register struct nameidata *ndp; 1603 register struct vnode *vp; 1604 int error; 1605 struct nameidata nd; 1606 1607 ndp = &nd; 1608 ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF; 1609 ndp->ni_segflg = UIO_USERSPACE; 1610 ndp->ni_dirp = uap->name; 1611 if (error = namei(ndp, p)) 1612 return (error); 1613 vp = ndp->ni_vp; 1614 if (vp->v_type != VDIR) { 1615 error = ENOTDIR; 1616 goto out; 1617 } 1618 /* 1619 * No rmdir "." please. 1620 */ 1621 if (ndp->ni_dvp == vp) { 1622 error = EINVAL; 1623 goto out; 1624 } 1625 /* 1626 * The root of a mounted filesystem cannot be deleted. 1627 */ 1628 if (vp->v_flag & VROOT) 1629 error = EBUSY; 1630 out: 1631 if (!error) { 1632 error = VOP_RMDIR(ndp, p); 1633 } else { 1634 VOP_ABORTOP(ndp); 1635 if (ndp->ni_dvp == vp) 1636 vrele(ndp->ni_dvp); 1637 else 1638 vput(ndp->ni_dvp); 1639 vput(vp); 1640 } 1641 return (error); 1642 } 1643 1644 /* 1645 * Read a block of directory entries in a file system independent format. 1646 */ 1647 getdirentries(p, uap, retval) 1648 struct proc *p; 1649 register struct args { 1650 int fd; 1651 char *buf; 1652 unsigned count; 1653 long *basep; 1654 } *uap; 1655 int *retval; 1656 { 1657 register struct vnode *vp; 1658 struct file *fp; 1659 struct uio auio; 1660 struct iovec aiov; 1661 off_t off; 1662 int error, eofflag; 1663 1664 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1665 return (error); 1666 if ((fp->f_flag & FREAD) == 0) 1667 return (EBADF); 1668 vp = (struct vnode *)fp->f_data; 1669 if (vp->v_type != VDIR) 1670 return (EINVAL); 1671 aiov.iov_base = uap->buf; 1672 aiov.iov_len = uap->count; 1673 auio.uio_iov = &aiov; 1674 auio.uio_iovcnt = 1; 1675 auio.uio_rw = UIO_READ; 1676 auio.uio_segflg = UIO_USERSPACE; 1677 auio.uio_procp = p; 1678 auio.uio_resid = uap->count; 1679 VOP_LOCK(vp); 1680 auio.uio_offset = off = fp->f_offset; 1681 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag); 1682 fp->f_offset = auio.uio_offset; 1683 VOP_UNLOCK(vp); 1684 if (error) 1685 return (error); 1686 error = copyout((caddr_t)&off, (caddr_t)uap->basep, sizeof(long)); 1687 *retval = uap->count - auio.uio_resid; 1688 return (error); 1689 } 1690 1691 /* 1692 * Set the mode mask for creation of filesystem nodes. 1693 */ 1694 mode_t 1695 umask(p, uap, retval) 1696 struct proc *p; 1697 struct args { 1698 int mask; 1699 } *uap; 1700 int *retval; 1701 { 1702 register struct filedesc *fdp = p->p_fd; 1703 1704 *retval = fdp->fd_cmask; 1705 fdp->fd_cmask = uap->mask & 07777; 1706 return (0); 1707 } 1708 1709 /* 1710 * Void all references to file by ripping underlying filesystem 1711 * away from vnode. 1712 */ 1713 /* ARGSUSED */ 1714 revoke(p, uap, retval) 1715 struct proc *p; 1716 register struct args { 1717 char *fname; 1718 } *uap; 1719 int *retval; 1720 { 1721 register struct nameidata *ndp; 1722 register struct vnode *vp; 1723 struct vattr vattr; 1724 int error; 1725 struct nameidata nd; 1726 1727 ndp = &nd; 1728 ndp->ni_nameiop = LOOKUP | FOLLOW; 1729 ndp->ni_segflg = UIO_USERSPACE; 1730 ndp->ni_dirp = uap->fname; 1731 if (error = namei(ndp, p)) 1732 return (error); 1733 vp = ndp->ni_vp; 1734 if (vp->v_type != VCHR && vp->v_type != VBLK) { 1735 error = EINVAL; 1736 goto out; 1737 } 1738 if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) 1739 goto out; 1740 if (p->p_ucred->cr_uid != vattr.va_uid && 1741 (error = suser(p->p_ucred, &p->p_acflag))) 1742 goto out; 1743 if (vp->v_usecount > 1 || (vp->v_flag & VALIASED)) 1744 vgoneall(vp); 1745 out: 1746 vrele(vp); 1747 return (error); 1748 } 1749 1750 /* 1751 * Convert a user file descriptor to a kernel file entry. 1752 */ 1753 getvnode(fdp, fdes, fpp) 1754 struct filedesc *fdp; 1755 struct file **fpp; 1756 int fdes; 1757 { 1758 struct file *fp; 1759 1760 if ((unsigned)fdes >= fdp->fd_nfiles || 1761 (fp = fdp->fd_ofiles[fdes]) == NULL) 1762 return (EBADF); 1763 if (fp->f_type != DTYPE_VNODE) 1764 return (EINVAL); 1765 *fpp = fp; 1766 return (0); 1767 } 1768