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