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