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