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