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