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