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