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