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