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