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