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