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