1 /* vfs_syscalls.c 4.35 82/08/24 */ 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 register int *gp; 583 584 ip->i_mode &= ~07777; 585 if (u.u_uid) { 586 mode &= ~ISVTX; 587 for (gp = u.u_groups; gp < &u.u_groups[NGROUPS]; gp++) 588 if (*gp == ip->i_gid) 589 goto ok; 590 mode &= ~ISGID; 591 ok: 592 ; 593 #ifdef MUSH 594 if (u.u_quota->q_syflags & QF_UMASK && u.u_uid != 0 && 595 (ip->i_mode & IFMT) != IFCHR) 596 mode &= ~u.u_cmask; 597 #endif 598 } 599 ip->i_mode |= mode&07777; 600 ip->i_flag |= ICHG; 601 if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0) 602 xrele(ip); 603 iput(ip); 604 } 605 606 chown() 607 { 608 struct inode *ip; 609 struct a { 610 char *fname; 611 int uid; 612 int gid; 613 } *uap; 614 615 uap = (struct a *)u.u_ap; 616 if (!suser() || (ip = owner(0)) == NULL) 617 return; 618 chown1(ip, uap->uid, uap->gid); 619 } 620 621 fchown() 622 { 623 struct a { 624 int fd; 625 int uid; 626 int gid; 627 } *uap; 628 register struct inode *ip; 629 register struct file *fp; 630 631 uap = (struct a *)u.u_ap; 632 fp = getf(uap->fd); 633 if (fp == NULL) 634 return; 635 if (fp->f_type == DTYPE_SOCKET) { 636 u.u_error = EINVAL; 637 return; 638 } 639 ip = fp->f_inode; 640 ilock(ip); 641 if (!suser()) { 642 iunlock(ip); 643 return; 644 } 645 chown1(ip, uap->uid, uap->gid); 646 } 647 648 /* 649 * Perform chown operation on inode ip; 650 * inode must be locked prior to call. 651 */ 652 chown1(ip, uid, gid) 653 register struct inode *ip; 654 int uid, gid; 655 { 656 #ifdef QUOTA 657 register long change; 658 659 /* 660 * This doesn't allow for holes in files (which hopefully don't 661 * happen often in files that we chown), and is not accurate anyway 662 * (eg: it totally ignores 3 level indir blk files - but hopefully 663 * noone who can make a file that big will have a quota) 664 */ 665 if (ip->i_uid == uid) 666 change = 0; 667 else { 668 register struct fs *fs = ip->i_fs; 669 670 if (ip->i_size > (change = NDADDR * fs->fs_bsize)) { 671 register off_t size; 672 673 size = blkroundup(fs, ip->i_size) - change; 674 change += size; 675 change += fs->fs_bsize; 676 /* this assumes NIADDR <= 2 */ 677 if (size > NINDIR(fs) * fs->fs_bsize) 678 change += fs->fs_bsize; 679 } else 680 change = fragroundup(fs, ip->i_size); 681 change /= DEV_BSIZE; 682 } 683 chkdq(ip, -change, 1); 684 chkiq(ip->i_dev, ip, ip->i_uid, 1); 685 dqrele(ip->i_dquot); 686 #endif 687 /* 688 * keep uid/gid's in sane range -- no err, 689 * so chown(file, uid, -1) will do something useful 690 */ 691 if (uid >= 0 && uid <= 32767) /* should have a constant */ 692 ip->i_uid = uid; 693 if (gid >= 0 && gid <= 32767) /* same here */ 694 ip->i_gid = gid; 695 ip->i_flag |= ICHG; 696 if (u.u_ruid != 0) 697 ip->i_mode &= ~(ISUID|ISGID); 698 #ifdef QUOTA 699 ip->i_dquot = inoquota(ip); 700 chkdq(ip, change, 1); 701 chkiq(ip->i_dev, NULL, uid, 1); 702 #endif 703 iput(ip); 704 } 705 706 /* 707 * Set IUPD and IACC times on file. 708 * Can't set ICHG. 709 */ 710 utime() 711 { 712 register struct a { 713 char *fname; 714 time_t *tptr; 715 } *uap; 716 register struct inode *ip; 717 time_t tv[2]; 718 719 uap = (struct a *)u.u_ap; 720 if ((ip = owner(1)) == NULL) 721 return; 722 if (copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof(tv))) { 723 u.u_error = EFAULT; 724 } else { 725 ip->i_flag |= IACC|IUPD|ICHG; 726 iupdat(ip, &tv[0], &tv[1], 0); 727 } 728 iput(ip); 729 } 730 731 sync() 732 { 733 734 update(0); 735 } 736 737 flock() 738 { 739 struct a { 740 int fd; 741 int how; 742 } *uap; 743 register struct file *fp; 744 register int cmd, flags; 745 746 uap = (struct a *)u.u_ap; 747 fp = getf(uap->fd); 748 if (fp == NULL) 749 return; 750 if (fp->f_type == DTYPE_SOCKET) { /* XXX */ 751 u.u_error = EINVAL; 752 return; 753 } 754 cmd = uap->how; 755 flags = u.u_pofile[uap->fd] & (RDLOCK|WRLOCK); 756 if (cmd&FUNLOCK) { 757 if (flags == 0) { 758 u.u_error = EINVAL; 759 return; 760 } 761 funlocki(fp->f_inode, flags); 762 u.u_pofile[uap->fd] &= ~(RDLOCK|WRLOCK); 763 return; 764 } 765 /* 766 * No reason to write lock a file we've already 767 * write locked, similarly with a read lock. 768 */ 769 if ((flags&WRLOCK) && (cmd&FWRLOCK) || 770 (flags&RDLOCK) && (cmd&FRDLOCK)) 771 return; 772 u.u_pofile[uap->fd] = flocki(fp->f_inode, u.u_pofile[uap->fd], cmd); 773 } 774 775 truncate() 776 { 777 struct a { 778 char *fname; 779 int length; 780 } *uap = (struct a *)u.u_ap; 781 struct inode *ip; 782 783 ip = namei(uchar, 0, 1); 784 if (ip == NULL) 785 return; 786 if (access(ip, IWRITE)) 787 goto bad; 788 if ((ip->i_mode&IFMT) == IFDIR) { 789 u.u_error = EISDIR; 790 goto bad; 791 } 792 itrunc(ip, uap->length); 793 return; 794 bad: 795 iput(ip); 796 } 797 798 ftruncate() 799 { 800 struct a { 801 int fd; 802 int length; 803 } *uap = (struct a *)u.u_ap; 804 struct inode *ip; 805 struct file *fp; 806 807 fp = getf(uap->fd); 808 if (fp == NULL) 809 return; 810 if (fp->f_type == DTYPE_SOCKET) { 811 u.u_error = EINVAL; 812 return; 813 } 814 if ((fp->f_flag&FWRITE) == 0) { 815 u.u_error = EINVAL; 816 return; 817 } 818 ip = fp->f_inode; 819 ilock(ip); 820 itrunc(ip, uap->length); 821 } 822 823 rename() 824 { 825 #ifdef notdef 826 struct a { 827 char *from; 828 char *to; 829 } *uap; 830 #endif 831 832 } 833 834 /* 835 * Make a new file. 836 */ 837 struct inode * 838 maknode(mode) 839 int mode; 840 { 841 register struct inode *ip; 842 ino_t ipref; 843 844 if ((mode & IFMT) == IFDIR) 845 ipref = dirpref(u.u_pdir->i_fs); 846 else 847 ipref = u.u_pdir->i_number; 848 ip = ialloc(u.u_pdir, ipref, mode); 849 if (ip == NULL) { 850 iput(u.u_pdir); 851 return (NULL); 852 } 853 #ifdef QUOTA 854 if (ip->i_dquot != NODQUOT) 855 panic("maknode: dquot"); 856 #endif 857 ip->i_flag |= IACC|IUPD|ICHG; 858 if ((mode & IFMT) == 0) 859 mode |= IFREG; 860 ip->i_mode = mode & ~u.u_cmask; 861 ip->i_nlink = 1; 862 ip->i_uid = u.u_uid; 863 ip->i_gid = u.u_pdir->i_gid; 864 #ifdef QUOTA 865 ip->i_dquot = inoquota(ip); 866 #endif 867 868 /* 869 * Make sure inode goes to disk before directory entry. 870 */ 871 iupdat(ip, &time, &time, 1); 872 direnter(ip); 873 if (u.u_error) { 874 /* 875 * write error occurred trying to update directory 876 * so must deallocate the inode 877 */ 878 ip->i_nlink = 0; 879 ip->i_flag |= ICHG; 880 iput(ip); 881 return (NULL); 882 } 883 return (ip); 884 } 885