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