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