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