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