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