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