1 /* ffs_vnops.c 4.33 82/08/14 */ 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_error = readip1(ip, uap->buf, uap->count, 0, 0, 0); 539 out: 540 iput(ip); 541 u.u_r.r_val1 = uap->count - u.u_count; 542 } 543 544 chmod() 545 { 546 struct inode *ip; 547 struct a { 548 char *fname; 549 int fmode; 550 } *uap; 551 552 uap = (struct a *)u.u_ap; 553 if ((ip = owner(1)) == NULL) 554 return; 555 chmod1(ip, uap->fmode); 556 } 557 558 fchmod() 559 { 560 struct a { 561 int fd; 562 int fmode; 563 } *uap; 564 register struct inode *ip; 565 register struct file *fp; 566 567 uap = (struct a *)u.u_ap; 568 fp = getf(uap->fd); 569 if (fp == NULL) 570 return; 571 if (fp->f_type == DTYPE_SOCKET) { 572 u.u_error = EINVAL; 573 return; 574 } 575 ip = fp->f_inode; 576 ilock(ip); 577 if (u.u_uid != ip->i_uid && !suser()) { 578 iunlock(ip); 579 return; 580 } 581 chmod1(ip, uap->fmode); 582 } 583 584 chmod1(ip, mode) 585 register struct inode *ip; 586 register int mode; 587 { 588 ip->i_mode &= ~07777; 589 if (u.u_uid) { 590 mode &= ~ISVTX; 591 if (ip->i_gid >= NGRPS || 592 (u.u_grps[ip->i_gid/(sizeof(int)*8)] & 593 (1 << ip->i_gid%(sizeof(int)*8))) == 0) 594 mode &= ~ISGID; 595 #ifdef MUSH 596 if (u.u_quota->q_syflags & QF_UMASK && u.u_uid != 0 && 597 (ip->i_mode & IFMT) != IFCHR) 598 mode &= ~u.u_cmask; 599 #endif 600 } 601 ip->i_mode |= mode&07777; 602 ip->i_flag |= ICHG; 603 if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0) 604 xrele(ip); 605 iput(ip); 606 } 607 608 chown() 609 { 610 struct inode *ip; 611 struct a { 612 char *fname; 613 int uid; 614 int gid; 615 } *uap; 616 617 uap = (struct a *)u.u_ap; 618 if (!suser() || (ip = owner(0)) == NULL) 619 return; 620 chown1(ip, uap->uid, uap->gid); 621 } 622 623 fchown() 624 { 625 struct a { 626 int fd; 627 int uid; 628 int gid; 629 } *uap; 630 register struct inode *ip; 631 register struct file *fp; 632 633 uap = (struct a *)u.u_ap; 634 fp = getf(uap->fd); 635 if (fp == NULL) 636 return; 637 if (fp->f_type == DTYPE_SOCKET) { 638 u.u_error = EINVAL; 639 return; 640 } 641 ip = fp->f_inode; 642 ilock(ip); 643 if (!suser()) { 644 iunlock(ip); 645 return; 646 } 647 chown1(ip, uap->uid, uap->gid); 648 } 649 650 /* 651 * Perform chown operation on inode ip; 652 * inode must be locked prior to call. 653 */ 654 chown1(ip, uid, gid) 655 register struct inode *ip; 656 int uid, gid; 657 { 658 #ifdef QUOTA 659 register long change; 660 661 /* 662 * This doesn't allow for holes in files (which hopefully don't 663 * happen often in files that we chown), and is not accurate anyway 664 * (eg: it totally ignores 3 level indir blk files - but hopefully 665 * noone who can make a file that big will have a quota) 666 */ 667 if (ip->i_uid == uid) 668 change = 0; 669 else { 670 register struct fs *fs = ip->i_fs; 671 672 if (ip->i_size > (change = NDADDR * fs->fs_bsize)) { 673 register off_t size; 674 675 size = blkroundup(fs, ip->i_size) - change; 676 change += size; 677 change += fs->fs_bsize; 678 /* this assumes NIADDR <= 2 */ 679 if (size > NINDIR(fs) * fs->fs_bsize) 680 change += fs->fs_bsize; 681 } else 682 change = fragroundup(fs, ip->i_size); 683 change /= DEV_BSIZE; 684 } 685 chkdq(ip, -change, 1); 686 chkiq(ip->i_dev, ip, ip->i_uid, 1); 687 dqrele(ip->i_dquot); 688 #endif 689 /* 690 * keep uid/gid's in sane range -- no err, 691 * so chown(file, uid, -1) will do something useful 692 */ 693 if (uid >= 0 && uid <= 32767) /* should have a constant */ 694 ip->i_uid = uid; 695 if (gid >= 0 && gid <= 32767) /* same here */ 696 ip->i_gid = gid; 697 ip->i_flag |= ICHG; 698 if (u.u_ruid != 0) 699 ip->i_mode &= ~(ISUID|ISGID); 700 #ifdef QUOTA 701 ip->i_dquot = inoquota(ip); 702 chkdq(ip, change, 1); 703 chkiq(ip->i_dev, NULL, uid, 1); 704 #endif 705 iput(ip); 706 } 707 708 /* 709 * Set IUPD and IACC times on file. 710 * Can't set ICHG. 711 */ 712 utime() 713 { 714 register struct a { 715 char *fname; 716 time_t *tptr; 717 } *uap; 718 register struct inode *ip; 719 time_t tv[2]; 720 721 uap = (struct a *)u.u_ap; 722 if ((ip = owner(1)) == NULL) 723 return; 724 if (copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof(tv))) { 725 u.u_error = EFAULT; 726 } else { 727 ip->i_flag |= IACC|IUPD|ICHG; 728 iupdat(ip, &tv[0], &tv[1], 0); 729 } 730 iput(ip); 731 } 732 733 sync() 734 { 735 736 update(0); 737 } 738 739 flock() 740 { 741 struct a { 742 int fd; 743 int how; 744 } *uap; 745 register struct file *fp; 746 register int cmd, flags; 747 748 uap = (struct a *)u.u_ap; 749 fp = getf(uap->fd); 750 if (fp == NULL) 751 return; 752 if (fp->f_type == DTYPE_SOCKET) { /* XXX */ 753 u.u_error = EINVAL; 754 return; 755 } 756 cmd = uap->how; 757 flags = u.u_pofile[uap->fd] & (RDLOCK|WRLOCK); 758 if (cmd&FUNLOCK) { 759 if (flags == 0) { 760 u.u_error = EINVAL; 761 return; 762 } 763 funlocki(fp->f_inode, flags); 764 u.u_pofile[uap->fd] &= ~(RDLOCK|WRLOCK); 765 return; 766 } 767 /* 768 * No reason to write lock a file we've already 769 * write locked, similarly with a read lock. 770 */ 771 if ((flags&WRLOCK) && (cmd&FWRLOCK) || 772 (flags&RDLOCK) && (cmd&FRDLOCK)) 773 return; 774 u.u_pofile[uap->fd] = flocki(fp->f_inode, u.u_pofile[uap->fd], cmd); 775 } 776 777 truncate() 778 { 779 struct a { 780 char *fname; 781 int length; 782 } *uap; 783 struct inode *ip; 784 785 ip = namei(uchar, 0, 1); 786 if (ip == NULL) 787 return; 788 if (access(ip, IWRITE)) 789 goto bad; 790 if ((ip->i_mode&IFMT) == IFDIR) { 791 u.u_error = EISDIR; 792 goto bad; 793 } 794 itrunc(ip, uap->length); 795 return; 796 bad: 797 iput(ip); 798 } 799 800 ftruncate() 801 { 802 struct a { 803 int fd; 804 int length; 805 } *uap; 806 struct inode *ip; 807 struct file *fp; 808 809 fp = getf(uap->fd); 810 if (fp == NULL) 811 return; 812 if (fp->f_type == DTYPE_SOCKET) { 813 u.u_error = EINVAL; 814 return; 815 } 816 if ((fp->f_flag&FWRITE) == 0) { 817 u.u_error = EINVAL; 818 return; 819 } 820 ip = fp->f_inode; 821 ilock(ip); 822 itrunc(ip, uap->length); 823 } 824 825 rename() 826 { 827 struct a { 828 char *from; 829 char *to; 830 } *uap; 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