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