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