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