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