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