1 /* vfs_syscalls.c 4.32 82/08/10 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/dir.h" 6 #include "../h/user.h" 7 #include "../h/file.h" 8 #include "../h/stat.h" 9 #include "../h/inode.h" 10 #include "../h/fs.h" 11 #include "../h/buf.h" 12 #include "../h/proc.h" 13 #include "../h/inline.h" 14 /* no reason to inline expand these guys here */ 15 #undef ilock 16 #undef iunlock 17 #include "../h/quota.h" 18 #include "../h/descrip.h" 19 20 chdir() 21 { 22 23 chdirec(&u.u_cdir); 24 } 25 26 chroot() 27 { 28 29 if (suser()) 30 chdirec(&u.u_rdir); 31 } 32 33 chdirec(ipp) 34 register struct inode **ipp; 35 { 36 register struct inode *ip; 37 struct a { 38 char *fname; 39 }; 40 41 ip = namei(uchar, 0, 1); 42 if(ip == NULL) 43 return; 44 if((ip->i_mode&IFMT) != IFDIR) { 45 u.u_error = ENOTDIR; 46 goto bad; 47 } 48 if(access(ip, IEXEC)) 49 goto bad; 50 iunlock(ip); 51 if (*ipp) 52 irele(*ipp); 53 *ipp = ip; 54 return; 55 56 bad: 57 iput(ip); 58 } 59 60 /* 61 * Open system call. 62 */ 63 open() 64 { 65 register struct inode *ip; 66 register struct a { 67 char *fname; 68 int flags; 69 int mode; 70 } *uap; 71 int checkpermissions = 1; 72 73 uap = (struct a *)u.u_ap; 74 if (uap->flags&FCREATE) { 75 ip = namei(uchar, 1, 1); 76 if (ip == NULL) { 77 if (u.u_error) 78 return; 79 ip = maknode(uap->mode&07777&(~ISVTX)); 80 checkpermissions = 0; 81 uap->flags &= ~FTRUNCATE; 82 } 83 } else 84 ip = namei(uchar, 0, 1); 85 if (ip == NULL) 86 return; 87 open1(ip, ++uap->flags, checkpermissions); 88 } 89 90 #ifndef NOCOMPAT 91 /* 92 * Creat system call. 93 */ 94 ocreat() 95 { 96 register struct inode *ip; 97 register struct a { 98 char *fname; 99 int fmode; 100 } *uap; 101 102 uap = (struct a *)u.u_ap; 103 ip = namei(uchar, 1, 1); 104 if (ip == NULL) { 105 if (u.u_error) 106 return; 107 ip = maknode(uap->fmode&07777&(~ISVTX)); 108 if (ip == NULL) 109 return; 110 open1(ip, FWRITE, 0); 111 } else 112 open1(ip, FWRITE|FTRUNCATE, 0); 113 } 114 #endif 115 116 /* 117 * Common code for open and creat. 118 * Check permissions (if we haven't done so already), 119 * allocate an open file structure, and call 120 * the device open routine, if any. 121 */ 122 open1(ip, mode, checkpermissions) 123 register struct inode *ip; 124 register mode; 125 { 126 register struct file *fp; 127 int i, flags; 128 129 if (checkpermissions) { 130 if (mode&FREAD) 131 if (access(ip, IREAD)) 132 goto bad; 133 if (mode&FWRITE) { 134 if (access(ip, IWRITE)) 135 goto bad; 136 if ((ip->i_mode&IFMT) == IFDIR) { 137 u.u_error = EISDIR; 138 goto bad; 139 } 140 } 141 } 142 143 /* 144 * Check locking on inode. Release "inode lock" 145 * while doing so in case we block inside flocki. 146 */ 147 flags = 0; 148 if (mode&(FRDLOCK|FWRLOCK)) { 149 iunlock(ip); 150 flags = flocki(ip, 0, mode); 151 ilock(ip); 152 if (u.u_error) 153 goto bad; 154 } 155 if (mode&FTRUNCATE) 156 itrunc(ip, 0); 157 iunlock(ip); 158 if ((fp = falloc()) == NULL) 159 goto out; 160 fp->f_flag = mode & FMODES; 161 fp->f_type = DTYPE_FILE; 162 i = u.u_r.r_val1; 163 fp->f_inode = ip; 164 openi(ip, mode); 165 if (u.u_error == 0) { 166 u.u_pofile[i] = flags; 167 return; 168 } 169 u.u_ofile[i] = NULL; 170 fp->f_count--; 171 out: 172 irele(ip); 173 return; 174 bad: 175 iput(ip); 176 } 177 178 /* 179 * Mknod system call 180 */ 181 mknod() 182 { 183 register struct inode *ip; 184 register struct a { 185 char *fname; 186 int fmode; 187 int dev; 188 } *uap; 189 190 uap = (struct a *)u.u_ap; 191 if (suser()) { 192 ip = namei(uchar, 1, 0); 193 if (ip != NULL) { 194 u.u_error = EEXIST; 195 goto out; 196 } 197 } 198 if (u.u_error) 199 return; 200 ip = maknode(uap->fmode); 201 if (ip == NULL) 202 return; 203 if (uap->dev) { 204 /* 205 * Want to be able to use this to make badblock 206 * inodes, so don't truncate the dev number. 207 */ 208 ip->i_rdev = uap->dev; 209 ip->i_flag |= IACC|IUPD|ICHG; 210 } 211 212 out: 213 iput(ip); 214 } 215 216 /* 217 * link system call 218 */ 219 link() 220 { 221 register struct inode *ip, *xp; 222 register struct a { 223 char *target; 224 char *linkname; 225 } *uap; 226 227 uap = (struct a *)u.u_ap; 228 ip = namei(uchar, 0, 1); /* well, this routine is doomed anyhow */ 229 if (ip == NULL) 230 return; 231 if ((ip->i_mode&IFMT)==IFDIR && !suser()) { 232 iput(ip); 233 return; 234 } 235 ip->i_nlink++; 236 ip->i_flag |= ICHG; 237 iupdat(ip, &time, &time, 1); 238 iunlock(ip); 239 u.u_dirp = (caddr_t)uap->linkname; 240 xp = namei(uchar, 1, 0); 241 if (xp != NULL) { 242 u.u_error = EEXIST; 243 iput(xp); 244 goto out; 245 } 246 if (u.u_error) 247 goto out; 248 if (u.u_pdir->i_dev != ip->i_dev) { 249 iput(u.u_pdir); 250 u.u_error = EXDEV; 251 goto out; 252 } 253 direnter(ip); 254 out: 255 if (u.u_error) { 256 ip->i_nlink--; 257 ip->i_flag |= ICHG; 258 } 259 out1: 260 irele(ip); 261 } 262 263 /* 264 * symlink -- make a symbolic link 265 */ 266 symlink() 267 { 268 register struct a { 269 char *target; 270 char *linkname; 271 } *uap; 272 register struct inode *ip; 273 register char *tp; 274 register c, nc; 275 276 uap = (struct a *)u.u_ap; 277 tp = uap->target; 278 nc = 0; 279 while (c = fubyte(tp)) { 280 if (c < 0) { 281 u.u_error = EFAULT; 282 return; 283 } 284 tp++; 285 nc++; 286 } 287 u.u_dirp = uap->linkname; 288 ip = namei(uchar, 1, 0); 289 if (ip) { 290 iput(ip); 291 u.u_error = EEXIST; 292 return; 293 } 294 if (u.u_error) 295 return; 296 ip = maknode(IFLNK | 0777); 297 if (ip == NULL) 298 return; 299 u.u_base = uap->target; 300 u.u_count = nc; 301 u.u_offset = 0; 302 u.u_segflg = 0; 303 writei(ip); 304 iput(ip); 305 } 306 307 /* 308 * Unlink system call. 309 * Hard to avoid races here, especially 310 * in unlinking directories. 311 */ 312 unlink() 313 { 314 register struct inode *ip, *pp; 315 struct a { 316 char *fname; 317 }; 318 struct fs *fs; 319 struct buf *bp; 320 int lbn, bn, base; 321 int unlinkingdot = 0; 322 323 pp = namei(uchar, 2, 0); 324 if (pp == NULL) 325 return; 326 327 /* 328 * Check for unlink(".") 329 * to avoid hanging on the iget 330 */ 331 if (pp->i_number == u.u_dent.d_ino) { 332 ip = pp; 333 ip->i_count++; 334 unlinkingdot++; 335 } else 336 ip = iget(pp->i_dev, pp->i_fs, u.u_dent.d_ino); 337 if(ip == NULL) 338 goto out1; 339 if((ip->i_mode&IFMT)==IFDIR && !suser()) 340 goto out; 341 /* 342 * Don't unlink a mounted file. 343 */ 344 if (ip->i_dev != pp->i_dev) { 345 u.u_error = EBUSY; 346 goto out; 347 } 348 if (ip->i_flag&ITEXT) 349 xrele(ip); /* try once to free text */ 350 if (dirremove()) { 351 ip->i_nlink--; 352 ip->i_flag |= ICHG; 353 } 354 out: 355 if (unlinkingdot) 356 irele(ip); 357 else 358 iput(ip); 359 out1: 360 iput(pp); 361 } 362 363 /* 364 * Seek system call 365 */ 366 seek() 367 { 368 register struct file *fp; 369 register struct a { 370 int fd; 371 off_t off; 372 int sbase; 373 } *uap; 374 375 uap = (struct a *)u.u_ap; 376 fp = getf(uap->fd); 377 if (fp == NULL) 378 return; 379 if (fp->f_type == DTYPE_SOCKET) { 380 u.u_error = ESPIPE; 381 return; 382 } 383 if (uap->sbase == FSEEK_RELATIVE) 384 uap->off += fp->f_offset; 385 else if (uap->sbase == FSEEK_EOF) 386 uap->off += fp->f_inode->i_size; 387 fp->f_offset = uap->off; 388 u.u_r.r_off = uap->off; 389 } 390 391 /* 392 * Access system call 393 */ 394 saccess() 395 { 396 register svuid, svgid; 397 register struct inode *ip; 398 register struct a { 399 char *fname; 400 int fmode; 401 } *uap; 402 403 uap = (struct a *)u.u_ap; 404 svuid = u.u_uid; 405 svgid = u.u_gid; 406 u.u_uid = u.u_ruid; 407 u.u_gid = u.u_rgid; 408 ip = namei(uchar, 0, 1); 409 if (ip != NULL) { 410 if (uap->fmode&FACCESS_READ && access(ip, IREAD)) 411 goto done; 412 if (uap->fmode&FACCESS_WRITE && access(ip, IWRITE)) 413 goto done; 414 if (uap->fmode&FACCESS_EXECUTE && access(ip, IEXEC)) 415 goto done; 416 done: 417 iput(ip); 418 } 419 u.u_uid = svuid; 420 u.u_gid = svgid; 421 } 422 423 /* 424 * the fstat system call. 425 */ 426 fstat() 427 { 428 register struct file *fp; 429 register struct a { 430 int fd; 431 struct stat *sb; 432 } *uap; 433 434 uap = (struct a *)u.u_ap; 435 fp = getf(uap->fd); 436 if (fp == NULL) 437 return; 438 if (fp->f_type == DTYPE_SOCKET) 439 u.u_error = sostat(fp->f_socket, uap->sb); 440 else 441 stat1(fp->f_inode, uap->sb); 442 } 443 444 /* 445 * Stat system call. This version follows links. 446 */ 447 stat() 448 { 449 register struct inode *ip; 450 register struct a { 451 char *fname; 452 struct stat *sb; 453 } *uap; 454 455 uap = (struct a *)u.u_ap; 456 ip = namei(uchar, 0, 1); 457 if (ip == NULL) 458 return; 459 stat1(ip, uap->sb); 460 iput(ip); 461 } 462 463 /* 464 * Lstat system call. This version does not follow links. 465 */ 466 lstat() 467 { 468 register struct inode *ip; 469 register struct a { 470 char *fname; 471 struct stat *sb; 472 } *uap; 473 474 uap = (struct a *)u.u_ap; 475 ip = namei(uchar, 0, 0); 476 if (ip == NULL) 477 return; 478 stat1(ip, uap->sb); 479 iput(ip); 480 } 481 482 /* 483 * The basic routine for fstat and stat: 484 * get the inode and pass appropriate parts back. 485 */ 486 stat1(ip, ub) 487 register struct inode *ip; 488 struct stat *ub; 489 { 490 struct stat ds; 491 492 IUPDAT(ip, &time, &time, 0); 493 /* 494 * Copy from inode table 495 */ 496 ds.st_dev = ip->i_dev; 497 ds.st_ino = ip->i_number; 498 ds.st_mode = ip->i_mode; 499 ds.st_nlink = ip->i_nlink; 500 ds.st_uid = ip->i_uid; 501 ds.st_gid = ip->i_gid; 502 ds.st_rdev = (dev_t)ip->i_rdev; 503 ds.st_size = ip->i_size; 504 ds.st_atime = ip->i_atime; 505 ds.st_mtime = ip->i_mtime; 506 ds.st_ctime = ip->i_ctime; 507 /* this doesn't belong here */ 508 if ((ip->i_mode&IFMT) == IFBLK) 509 ds.st_blksize = BLKDEV_IOSIZE; 510 else if ((ip->i_mode&IFMT) == IFCHR) 511 ds.st_blksize = MAXBSIZE; 512 else 513 ds.st_blksize = ip->i_fs->fs_bsize; 514 if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0) 515 u.u_error = EFAULT; 516 } 517 518 /* 519 * Return target name of a symbolic link 520 */ 521 readlink() 522 { 523 register struct inode *ip; 524 register struct a { 525 char *name; 526 char *buf; 527 int count; 528 } *uap; 529 530 ip = namei(uchar, 0, 0); 531 if (ip == NULL) 532 return; 533 if ((ip->i_mode&IFMT) != IFLNK) { 534 u.u_error = ENXIO; 535 goto out; 536 } 537 uap = (struct a *)u.u_ap; 538 u.u_offset = 0; 539 u.u_base = uap->buf; 540 u.u_count = uap->count; 541 u.u_segflg = 0; 542 readi(ip); 543 out: 544 iput(ip); 545 u.u_r.r_val1 = uap->count - u.u_count; 546 } 547 548 chmod() 549 { 550 struct inode *ip; 551 struct a { 552 char *fname; 553 int fmode; 554 } *uap; 555 556 uap = (struct a *)u.u_ap; 557 if ((ip = owner(1)) == NULL) 558 return; 559 chmod1(ip, uap->fmode); 560 } 561 562 fchmod() 563 { 564 struct a { 565 int fd; 566 int fmode; 567 } *uap; 568 register struct inode *ip; 569 register struct file *fp; 570 571 uap = (struct a *)u.u_ap; 572 fp = getf(uap->fd); 573 if (fp == NULL) 574 return; 575 if (fp->f_type == DTYPE_SOCKET) { 576 u.u_error = EINVAL; 577 return; 578 } 579 ip = fp->f_inode; 580 ilock(ip); 581 if (u.u_uid != ip->i_uid && !suser()) { 582 iunlock(ip); 583 return; 584 } 585 chmod1(ip, uap->fmode); 586 } 587 588 chmod1(ip, mode) 589 register struct inode *ip; 590 register int mode; 591 { 592 ip->i_mode &= ~07777; 593 if (u.u_uid) { 594 mode &= ~ISVTX; 595 if (ip->i_gid >= NGRPS || 596 (u.u_grps[ip->i_gid/(sizeof(int)*8)] & 597 (1 << ip->i_gid%(sizeof(int)*8))) == 0) 598 mode &= ~ISGID; 599 #ifdef MUSH 600 if (u.u_quota->q_syflags & QF_UMASK && u.u_uid != 0 && 601 (ip->i_mode & IFMT) != IFCHR) 602 mode &= ~u.u_cmask; 603 #endif 604 } 605 ip->i_mode |= mode&07777; 606 ip->i_flag |= ICHG; 607 if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0) 608 xrele(ip); 609 iput(ip); 610 } 611 612 chown() 613 { 614 struct inode *ip; 615 struct a { 616 char *fname; 617 int uid; 618 int gid; 619 } *uap; 620 621 uap = (struct a *)u.u_ap; 622 if (!suser() || (ip = owner(0)) == NULL) 623 return; 624 chown1(ip, uap->uid, uap->gid); 625 } 626 627 fchown() 628 { 629 struct a { 630 int fd; 631 int uid; 632 int gid; 633 } *uap; 634 register struct inode *ip; 635 register struct file *fp; 636 637 uap = (struct a *)u.u_ap; 638 fp = getf(uap->fd); 639 if (fp == NULL) 640 return; 641 if (fp->f_type == DTYPE_SOCKET) { 642 u.u_error = EINVAL; 643 return; 644 } 645 ip = fp->f_inode; 646 ilock(ip); 647 if (!suser()) { 648 iunlock(ip); 649 return; 650 } 651 chown1(ip, uap->uid, uap->gid); 652 } 653 654 /* 655 * Perform chown operation on inode ip; 656 * inode must be locked prior to call. 657 */ 658 chown1(ip, uid, gid) 659 register struct inode *ip; 660 int uid, gid; 661 { 662 #ifdef QUOTA 663 register long change; 664 665 /* 666 * This doesn't allow for holes in files (which hopefully don't 667 * happen often in files that we chown), and is not accurate anyway 668 * (eg: it totally ignores 3 level indir blk files - but hopefully 669 * noone who can make a file that big will have a quota) 670 */ 671 if (ip->i_uid == uid) 672 change = 0; 673 else { 674 register struct fs *fs = ip->i_fs; 675 676 if (ip->i_size > (change = NDADDR * fs->fs_bsize)) { 677 register off_t size; 678 679 size = blkroundup(fs, ip->i_size) - change; 680 change += size; 681 change += fs->fs_bsize; 682 /* this assumes NIADDR <= 2 */ 683 if (size > NINDIR(fs) * fs->fs_bsize) 684 change += fs->fs_bsize; 685 } else 686 change = fragroundup(fs, ip->i_size); 687 change /= DEV_BSIZE; 688 } 689 chkdq(ip, -change, 1); 690 chkiq(ip->i_dev, ip, ip->i_uid, 1); 691 dqrele(ip->i_dquot); 692 #endif 693 /* 694 * keep uid/gid's in sane range -- no err, 695 * so chown(file, uid, -1) will do something useful 696 */ 697 if (uid >= 0 && uid <= 32767) /* should have a constant */ 698 ip->i_uid = uid; 699 if (gid >= 0 && gid <= 32767) /* same here */ 700 ip->i_gid = gid; 701 ip->i_flag |= ICHG; 702 if (u.u_ruid != 0) 703 ip->i_mode &= ~(ISUID|ISGID); 704 #ifdef QUOTA 705 ip->i_dquot = inoquota(ip); 706 chkdq(ip, change, 1); 707 chkiq(ip->i_dev, NULL, uid, 1); 708 #endif 709 iput(ip); 710 } 711 712 /* 713 * Set IUPD and IACC times on file. 714 * Can't set ICHG. 715 */ 716 utime() 717 { 718 register struct a { 719 char *fname; 720 time_t *tptr; 721 } *uap; 722 register struct inode *ip; 723 time_t tv[2]; 724 725 uap = (struct a *)u.u_ap; 726 if ((ip = owner(1)) == NULL) 727 return; 728 if (copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof(tv))) { 729 u.u_error = EFAULT; 730 } else { 731 ip->i_flag |= IACC|IUPD|ICHG; 732 iupdat(ip, &tv[0], &tv[1], 0); 733 } 734 iput(ip); 735 } 736 737 sync() 738 { 739 740 update(0); 741 } 742 743 flock() 744 { 745 struct a { 746 int fd; 747 int how; 748 } *uap; 749 register struct file *fp; 750 register int cmd, flags; 751 752 uap = (struct a *)u.u_ap; 753 fp = getf(uap->fd); 754 if (fp == NULL) 755 return; 756 if (fp->f_type == DTYPE_SOCKET) { /* XXX */ 757 u.u_error = EINVAL; 758 return; 759 } 760 cmd = uap->how; 761 flags = u.u_pofile[uap->fd] & (RDLOCK|WRLOCK); 762 if (cmd&FUNLOCK) { 763 if (flags == 0) { 764 u.u_error = EINVAL; 765 return; 766 } 767 funlocki(fp->f_inode, flags); 768 u.u_pofile[uap->fd] &= ~(RDLOCK|WRLOCK); 769 return; 770 } 771 /* 772 * No reason to write lock a file we've already 773 * write locked, similarly with a read lock. 774 */ 775 if ((flags&WRLOCK) && (cmd&FWRLOCK) || 776 (flags&RDLOCK) && (cmd&FRDLOCK)) 777 return; 778 u.u_pofile[uap->fd] = flocki(fp->f_inode, u.u_pofile[uap->fd], cmd); 779 } 780 781 truncate() 782 { 783 struct a { 784 char *fname; 785 int length; 786 } *uap; 787 struct inode *ip; 788 789 ip = namei(uchar, 0, 1); 790 if (ip == NULL) 791 return; 792 if (access(ip, IWRITE)) 793 goto bad; 794 if ((ip->i_mode&IFMT) == IFDIR) { 795 u.u_error = EISDIR; 796 goto bad; 797 } 798 itrunc(ip, uap->length); 799 return; 800 bad: 801 iput(ip); 802 } 803 804 ftruncate() 805 { 806 struct a { 807 int fd; 808 int length; 809 } *uap; 810 struct inode *ip; 811 struct file *fp; 812 813 fp = getf(uap->fd); 814 if (fp == NULL) 815 return; 816 if (fp->f_type == DTYPE_SOCKET) { 817 u.u_error = EINVAL; 818 return; 819 } 820 if ((fp->f_flag&FWRITE) == 0) { 821 u.u_error = EINVAL; 822 return; 823 } 824 ip = fp->f_inode; 825 ilock(ip); 826 itrunc(ip, uap->length); 827 } 828 829 rename() 830 { 831 struct a { 832 char *from; 833 char *to; 834 } *uap; 835 836 } 837 838 /* 839 * Make a new file. 840 */ 841 struct inode * 842 maknode(mode) 843 int mode; 844 { 845 register struct inode *ip; 846 ino_t ipref; 847 848 if ((mode & IFMT) == IFDIR) 849 ipref = dirpref(u.u_pdir->i_fs); 850 else 851 ipref = u.u_pdir->i_number; 852 ip = ialloc(u.u_pdir, ipref, mode); 853 if (ip == NULL) { 854 iput(u.u_pdir); 855 return (NULL); 856 } 857 #ifdef QUOTA 858 if (ip->i_dquot != NODQUOT) 859 panic("maknode: dquot"); 860 #endif 861 ip->i_flag |= IACC|IUPD|ICHG; 862 if ((mode & IFMT) == 0) 863 mode |= IFREG; 864 ip->i_mode = mode & ~u.u_cmask; 865 ip->i_nlink = 1; 866 ip->i_uid = u.u_uid; 867 ip->i_gid = u.u_pdir->i_gid; 868 #ifdef QUOTA 869 ip->i_dquot = inoquota(ip); 870 #endif 871 872 /* 873 * Make sure inode goes to disk before directory entry. 874 */ 875 iupdat(ip, &time, &time, 1); 876 direnter(ip); 877 if (u.u_error) { 878 /* 879 * write error occurred trying to update directory 880 * so must deallocate the inode 881 */ 882 ip->i_nlink = 0; 883 ip->i_flag |= ICHG; 884 iput(ip); 885 return (NULL); 886 } 887 return (ip); 888 } 889