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