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