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