1 /* ffs_vnops.c 4.41 82/10/19 */ 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 #include "../h/socketvar.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 u.u_error = 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 irele(ip); 260 } 261 262 /* 263 * symlink -- make a symbolic link 264 */ 265 symlink() 266 { 267 register struct a { 268 char *target; 269 char *linkname; 270 } *uap; 271 register struct inode *ip; 272 register char *tp; 273 register c, nc; 274 275 uap = (struct a *)u.u_ap; 276 tp = uap->target; 277 nc = 0; 278 while (c = fubyte(tp)) { 279 if (c < 0) { 280 u.u_error = EFAULT; 281 return; 282 } 283 tp++; 284 nc++; 285 } 286 u.u_dirp = uap->linkname; 287 ip = namei(uchar, 1, 0); 288 if (ip) { 289 iput(ip); 290 u.u_error = EEXIST; 291 return; 292 } 293 if (u.u_error) 294 return; 295 ip = maknode(IFLNK | 0777); 296 if (ip == NULL) 297 return; 298 u.u_error = rdwri(UIO_WRITE, ip, uap->target, nc, 0, 0, (int *)0); 299 iput(ip); 300 } 301 302 /* 303 * Unlink system call. 304 * Hard to avoid races here, especially 305 * in unlinking directories. 306 */ 307 unlink() 308 { 309 register struct inode *ip, *pp; 310 struct a { 311 char *fname; 312 }; 313 int unlinkingdot = 0; 314 315 pp = namei(uchar, 2, 0); 316 if (pp == NULL) 317 return; 318 319 /* 320 * Check for unlink(".") 321 * to avoid hanging on the iget 322 */ 323 if (pp->i_number == u.u_dent.d_ino) { 324 ip = pp; 325 ip->i_count++; 326 unlinkingdot++; 327 } else 328 ip = iget(pp->i_dev, pp->i_fs, u.u_dent.d_ino); 329 if(ip == NULL) 330 goto out1; 331 if((ip->i_mode&IFMT)==IFDIR && !suser()) 332 goto out; 333 /* 334 * Don't unlink a mounted file. 335 */ 336 if (ip->i_dev != pp->i_dev) { 337 u.u_error = EBUSY; 338 goto out; 339 } 340 if (ip->i_flag&ITEXT) 341 xrele(ip); /* try once to free text */ 342 if (dirremove()) { 343 ip->i_nlink--; 344 ip->i_flag |= ICHG; 345 } 346 out: 347 if (unlinkingdot) 348 irele(ip); 349 else 350 iput(ip); 351 out1: 352 iput(pp); 353 } 354 355 /* 356 * Seek system call 357 */ 358 lseek() 359 { 360 register struct file *fp; 361 register struct a { 362 int fd; 363 off_t off; 364 int sbase; 365 } *uap; 366 367 uap = (struct a *)u.u_ap; 368 fp = getf(uap->fd); 369 if (fp == NULL) 370 return; 371 if (fp->f_type == DTYPE_SOCKET) { 372 u.u_error = ESPIPE; 373 return; 374 } 375 if (uap->sbase == FSEEK_RELATIVE) 376 uap->off += fp->f_offset; 377 else if (uap->sbase == FSEEK_EOF) 378 uap->off += fp->f_inode->i_size; 379 fp->f_offset = uap->off; 380 u.u_r.r_off = uap->off; 381 } 382 383 /* 384 * Access system call 385 */ 386 saccess() 387 { 388 register svuid, svgid; 389 register struct inode *ip; 390 register struct a { 391 char *fname; 392 int fmode; 393 } *uap; 394 395 uap = (struct a *)u.u_ap; 396 svuid = u.u_uid; 397 svgid = u.u_gid; 398 u.u_uid = u.u_ruid; 399 u.u_gid = u.u_rgid; 400 ip = namei(uchar, 0, 1); 401 if (ip != NULL) { 402 if (uap->fmode&FACCESS_READ && access(ip, IREAD)) 403 goto done; 404 if (uap->fmode&FACCESS_WRITE && access(ip, IWRITE)) 405 goto done; 406 if (uap->fmode&FACCESS_EXECUTE && access(ip, IEXEC)) 407 goto done; 408 done: 409 iput(ip); 410 } 411 u.u_uid = svuid; 412 u.u_gid = svgid; 413 } 414 415 /* 416 * the fstat system call. 417 */ 418 fstat() 419 { 420 register struct file *fp; 421 register struct a { 422 int fd; 423 struct stat *sb; 424 } *uap; 425 426 uap = (struct a *)u.u_ap; 427 fp = getf(uap->fd); 428 if (fp == NULL) 429 return; 430 if (fp->f_type == DTYPE_SOCKET) 431 u.u_error = sostat(fp->f_socket, uap->sb); 432 else 433 stat1(fp->f_inode, uap->sb); 434 } 435 436 /* 437 * Stat system call. This version follows links. 438 */ 439 stat() 440 { 441 register struct inode *ip; 442 register struct a { 443 char *fname; 444 struct stat *sb; 445 } *uap; 446 447 uap = (struct a *)u.u_ap; 448 ip = namei(uchar, 0, 1); 449 if (ip == NULL) 450 return; 451 stat1(ip, uap->sb); 452 iput(ip); 453 } 454 455 /* 456 * Lstat system call. This version does not follow links. 457 */ 458 lstat() 459 { 460 register struct inode *ip; 461 register struct a { 462 char *fname; 463 struct stat *sb; 464 } *uap; 465 466 uap = (struct a *)u.u_ap; 467 ip = namei(uchar, 0, 0); 468 if (ip == NULL) 469 return; 470 stat1(ip, uap->sb); 471 iput(ip); 472 } 473 474 /* 475 * The basic routine for fstat and stat: 476 * get the inode and pass appropriate parts back. 477 */ 478 stat1(ip, ub) 479 register struct inode *ip; 480 struct stat *ub; 481 { 482 struct stat ds; 483 484 IUPDAT(ip, &time, &time, 0); 485 /* 486 * Copy from inode table 487 */ 488 ds.st_dev = ip->i_dev; 489 ds.st_ino = ip->i_number; 490 ds.st_mode = ip->i_mode; 491 ds.st_nlink = ip->i_nlink; 492 ds.st_uid = ip->i_uid; 493 ds.st_gid = ip->i_gid; 494 ds.st_rdev = (dev_t)ip->i_rdev; 495 ds.st_size = ip->i_size; 496 ds.st_atime = ip->i_atime; 497 ds.st_mtime = ip->i_mtime; 498 ds.st_ctime = ip->i_ctime; 499 /* this doesn't belong here */ 500 if ((ip->i_mode&IFMT) == IFBLK) 501 ds.st_blksize = BLKDEV_IOSIZE; 502 else if ((ip->i_mode&IFMT) == IFCHR) 503 ds.st_blksize = MAXBSIZE; 504 else 505 ds.st_blksize = ip->i_fs->fs_bsize; 506 if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0) 507 u.u_error = EFAULT; 508 } 509 510 /* 511 * Return target name of a symbolic link 512 */ 513 readlink() 514 { 515 register struct inode *ip; 516 register struct a { 517 char *name; 518 char *buf; 519 int count; 520 } *uap = (struct a *)u.u_ap; 521 int resid; 522 523 ip = namei(uchar, 0, 0); 524 if (ip == NULL) 525 return; 526 if ((ip->i_mode&IFMT) != IFLNK) { 527 u.u_error = ENXIO; 528 goto out; 529 } 530 u.u_error = rdwri(UIO_READ, ip, uap->buf, uap->count, 0, 0, &resid); 531 out: 532 iput(ip); 533 u.u_r.r_val1 = uap->count - resid; 534 } 535 536 chmod() 537 { 538 struct inode *ip; 539 struct a { 540 char *fname; 541 int fmode; 542 } *uap; 543 544 uap = (struct a *)u.u_ap; 545 if ((ip = owner(1)) == NULL) 546 return; 547 chmod1(ip, uap->fmode); 548 } 549 550 fchmod() 551 { 552 struct a { 553 int fd; 554 int fmode; 555 } *uap; 556 register struct inode *ip; 557 register struct file *fp; 558 559 uap = (struct a *)u.u_ap; 560 fp = getf(uap->fd); 561 if (fp == NULL) 562 return; 563 if (fp->f_type == DTYPE_SOCKET) { 564 u.u_error = EINVAL; 565 return; 566 } 567 ip = fp->f_inode; 568 ilock(ip); 569 if (u.u_uid != ip->i_uid && !suser()) { 570 iunlock(ip); 571 return; 572 } 573 chmod1(ip, uap->fmode); 574 } 575 576 chmod1(ip, mode) 577 register struct inode *ip; 578 register int mode; 579 { 580 register int *gp; 581 582 ip->i_mode &= ~07777; 583 if (u.u_uid) { 584 mode &= ~ISVTX; 585 for (gp = u.u_groups; gp < &u.u_groups[NGROUPS]; gp++) 586 if (*gp == ip->i_gid) 587 goto ok; 588 mode &= ~ISGID; 589 ok: 590 ; 591 #ifdef MUSH 592 if (u.u_quota->q_syflags & QF_UMASK && u.u_uid != 0 && 593 (ip->i_mode & IFMT) != IFCHR) 594 mode &= ~u.u_cmask; 595 #endif 596 } 597 ip->i_mode |= mode&07777; 598 ip->i_flag |= ICHG; 599 if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0) 600 xrele(ip); 601 iput(ip); 602 } 603 604 chown() 605 { 606 struct inode *ip; 607 struct a { 608 char *fname; 609 int uid; 610 int gid; 611 } *uap; 612 613 uap = (struct a *)u.u_ap; 614 if (!suser() || (ip = owner(0)) == NULL) 615 return; 616 chown1(ip, uap->uid, uap->gid); 617 } 618 619 fchown() 620 { 621 struct a { 622 int fd; 623 int uid; 624 int gid; 625 } *uap; 626 register struct inode *ip; 627 register struct file *fp; 628 629 uap = (struct a *)u.u_ap; 630 fp = getf(uap->fd); 631 if (fp == NULL) 632 return; 633 if (fp->f_type == DTYPE_SOCKET) { 634 u.u_error = EINVAL; 635 return; 636 } 637 ip = fp->f_inode; 638 ilock(ip); 639 if (!suser()) { 640 iunlock(ip); 641 return; 642 } 643 chown1(ip, uap->uid, uap->gid); 644 } 645 646 /* 647 * Perform chown operation on inode ip; 648 * inode must be locked prior to call. 649 */ 650 chown1(ip, uid, gid) 651 register struct inode *ip; 652 int uid, gid; 653 { 654 #ifdef QUOTA 655 register long change; 656 657 /* 658 * This doesn't allow for holes in files (which hopefully don't 659 * happen often in files that we chown), and is not accurate anyway 660 * (eg: it totally ignores 3 level indir blk files - but hopefully 661 * noone who can make a file that big will have a quota) 662 */ 663 if (ip->i_uid == uid) 664 change = 0; 665 else { 666 register struct fs *fs = ip->i_fs; 667 668 if (ip->i_size > (change = NDADDR * fs->fs_bsize)) { 669 register off_t size; 670 671 size = blkroundup(fs, ip->i_size) - change; 672 change += size; 673 change += fs->fs_bsize; 674 /* this assumes NIADDR <= 2 */ 675 if (size > NINDIR(fs) * fs->fs_bsize) 676 change += fs->fs_bsize; 677 } else 678 change = fragroundup(fs, ip->i_size); 679 change /= DEV_BSIZE; 680 } 681 chkdq(ip, -change, 1); 682 chkiq(ip->i_dev, ip, ip->i_uid, 1); 683 dqrele(ip->i_dquot); 684 #endif 685 /* 686 * keep uid/gid's in sane range -- no err, 687 * so chown(file, uid, -1) will do something useful 688 */ 689 if (uid >= 0 && uid <= 32767) /* should have a constant */ 690 ip->i_uid = uid; 691 if (gid >= 0 && gid <= 32767) /* same here */ 692 ip->i_gid = gid; 693 ip->i_flag |= ICHG; 694 if (u.u_ruid != 0) 695 ip->i_mode &= ~(ISUID|ISGID); 696 #ifdef QUOTA 697 ip->i_dquot = inoquota(ip); 698 chkdq(ip, change, 1); 699 chkiq(ip->i_dev, NULL, uid, 1); 700 #endif 701 iput(ip); 702 } 703 704 /* 705 * Set IUPD and IACC times on file. 706 * Can't set ICHG. 707 */ 708 outime() 709 { 710 register struct a { 711 char *fname; 712 time_t *tptr; 713 } *uap; 714 register struct inode *ip; 715 time_t tv[2]; 716 struct timeval tv0, tv1; 717 718 uap = (struct a *)u.u_ap; 719 if ((ip = owner(1)) == NULL) 720 return; 721 if (copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof(tv))) { 722 u.u_error = EFAULT; 723 } else { 724 ip->i_flag |= IACC|IUPD|ICHG; 725 tv0.tv_sec = tv[0]; tv0.tv_usec = 0; 726 tv1.tv_sec = tv[1]; tv1.tv_usec = 0; 727 iupdat(ip, &tv0, &tv1, 0); 728 } 729 iput(ip); 730 } 731 732 sync() 733 { 734 735 update(); 736 } 737 738 flock() 739 { 740 struct a { 741 int fd; 742 int how; 743 } *uap; 744 register struct file *fp; 745 register int cmd, flags; 746 747 uap = (struct a *)u.u_ap; 748 fp = getf(uap->fd); 749 if (fp == NULL) 750 return; 751 if (fp->f_type == DTYPE_SOCKET) { /* XXX */ 752 u.u_error = EINVAL; 753 return; 754 } 755 cmd = uap->how; 756 flags = u.u_pofile[uap->fd] & (RDLOCK|WRLOCK); 757 if (cmd&FUNLOCK) { 758 if (flags == 0) { 759 u.u_error = EINVAL; 760 return; 761 } 762 funlocki(fp->f_inode, flags); 763 u.u_pofile[uap->fd] &= ~(RDLOCK|WRLOCK); 764 return; 765 } 766 /* 767 * No reason to write lock a file we've already 768 * write locked, similarly with a read lock. 769 */ 770 if ((flags&WRLOCK) && (cmd&FWRLOCK) || 771 (flags&RDLOCK) && (cmd&FRDLOCK)) 772 return; 773 u.u_pofile[uap->fd] = flocki(fp->f_inode, u.u_pofile[uap->fd], cmd); 774 } 775 776 truncate() 777 { 778 struct a { 779 char *fname; 780 int length; 781 } *uap = (struct a *)u.u_ap; 782 struct inode *ip; 783 784 ip = namei(uchar, 0, 1); 785 if (ip == NULL) 786 return; 787 if (access(ip, IWRITE)) 788 goto bad; 789 if ((ip->i_mode&IFMT) == IFDIR) { 790 u.u_error = EISDIR; 791 goto bad; 792 } 793 itrunc(ip, uap->length); 794 return; 795 bad: 796 iput(ip); 797 } 798 799 ftruncate() 800 { 801 struct a { 802 int fd; 803 int length; 804 } *uap = (struct a *)u.u_ap; 805 struct inode *ip; 806 struct file *fp; 807 808 fp = getf(uap->fd); 809 if (fp == NULL) 810 return; 811 if (fp->f_type == DTYPE_SOCKET) { 812 u.u_error = EINVAL; 813 return; 814 } 815 if ((fp->f_flag&FWRITE) == 0) { 816 u.u_error = EINVAL; 817 return; 818 } 819 ip = fp->f_inode; 820 ilock(ip); 821 itrunc(ip, uap->length); 822 } 823 824 rename() 825 { 826 #ifdef notdef 827 struct a { 828 char *from; 829 char *to; 830 } *uap; 831 #endif 832 833 } 834 835 /* 836 * Make a new file. 837 */ 838 struct inode * 839 maknode(mode) 840 int mode; 841 { 842 register struct inode *ip; 843 ino_t ipref; 844 845 if ((mode & IFMT) == IFDIR) 846 ipref = dirpref(u.u_pdir->i_fs); 847 else 848 ipref = u.u_pdir->i_number; 849 ip = ialloc(u.u_pdir, ipref, mode); 850 if (ip == NULL) { 851 iput(u.u_pdir); 852 return (NULL); 853 } 854 #ifdef QUOTA 855 if (ip->i_dquot != NODQUOT) 856 panic("maknode: dquot"); 857 #endif 858 ip->i_flag |= IACC|IUPD|ICHG; 859 if ((mode & IFMT) == 0) 860 mode |= IFREG; 861 ip->i_mode = mode & ~u.u_cmask; 862 ip->i_nlink = 1; 863 ip->i_uid = u.u_uid; 864 ip->i_gid = u.u_pdir->i_gid; 865 #ifdef QUOTA 866 ip->i_dquot = inoquota(ip); 867 #endif 868 869 /* 870 * Make sure inode goes to disk before directory entry. 871 */ 872 iupdat(ip, &time, &time, 1); 873 direnter(ip); 874 if (u.u_error) { 875 /* 876 * write error occurred trying to update directory 877 * so must deallocate the inode 878 */ 879 ip->i_nlink = 0; 880 ip->i_flag |= ICHG; 881 iput(ip); 882 return (NULL); 883 } 884 return (ip); 885 } 886