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