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