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