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