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