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