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