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