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