1 /* lfs_vnops.c 6.2 83/09/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/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/uio.h" 16 #include "../h/socket.h" 17 #include "../h/socketvar.h" 18 #include "../h/nami.h" 19 #include "../h/mount.h" 20 21 extern struct fileops inodeops; 22 struct file *getinode(); 23 24 /* 25 * Change current working directory (``.''). 26 */ 27 chdir() 28 { 29 30 chdirec(&u.u_cdir); 31 } 32 33 /* 34 * Change notion of root (``/'') directory. 35 */ 36 chroot() 37 { 38 39 if (suser()) 40 chdirec(&u.u_rdir); 41 } 42 43 /* 44 * Common routine for chroot and chdir. 45 */ 46 chdirec(ipp) 47 register struct inode **ipp; 48 { 49 register struct inode *ip; 50 struct a { 51 char *fname; 52 }; 53 54 ip = namei(uchar, LOOKUP, 1); 55 if (ip == NULL) 56 return; 57 if ((ip->i_mode&IFMT) != IFDIR) { 58 u.u_error = ENOTDIR; 59 goto bad; 60 } 61 if (access(ip, IEXEC)) 62 goto bad; 63 iunlock(ip); 64 if (*ipp) 65 irele(*ipp); 66 *ipp = ip; 67 return; 68 69 bad: 70 iput(ip); 71 } 72 73 /* 74 * Open system call. 75 */ 76 open() 77 { 78 struct a { 79 char *fname; 80 int mode; 81 int crtmode; 82 } *uap = (struct a *) u.u_ap; 83 84 copen(uap->mode-FOPEN, uap->crtmode); 85 } 86 87 /* 88 * Creat system call. 89 */ 90 creat() 91 { 92 struct a { 93 char *fname; 94 int fmode; 95 } *uap = (struct a *)u.u_ap; 96 97 copen(FWRITE|FCREAT|FTRUNC, uap->fmode); 98 } 99 100 /* 101 * Common code for open and creat. 102 * Check permissions, allocate an open file structure, 103 * and call the device open routine if any. 104 */ 105 copen(mode, arg) 106 register int mode; 107 int arg; 108 { 109 register struct inode *ip; 110 register struct file *fp; 111 int i; 112 113 #ifdef notdef 114 if ((mode&(FREAD|FWRITE)) == 0) { 115 u.u_error = EINVAL; 116 return; 117 } 118 #endif 119 if (mode&FCREAT) { 120 ip = namei(uchar, CREATE, 1); 121 if (ip == NULL) { 122 if (u.u_error) 123 return; 124 ip = maknode(arg&07777&(~ISVTX)); 125 if (ip == NULL) 126 return; 127 mode &= ~FTRUNC; 128 } else { 129 if (mode&FEXCL) { 130 u.u_error = EEXIST; 131 iput(ip); 132 return; 133 } 134 mode &= ~FCREAT; 135 } 136 } else { 137 ip = namei(uchar, LOOKUP, 1); 138 if (ip == NULL) 139 return; 140 } 141 if ((ip->i_mode & IFMT) == IFSOCK) { 142 u.u_error = EOPNOTSUPP; 143 goto bad; 144 } 145 if ((mode&FCREAT) == 0) { 146 if (mode&FREAD) 147 if (access(ip, IREAD)) 148 goto bad; 149 if (mode&FWRITE) { 150 if (access(ip, IWRITE)) 151 goto bad; 152 if ((ip->i_mode&IFMT) == IFDIR) { 153 u.u_error = EISDIR; 154 goto bad; 155 } 156 } 157 } 158 fp = falloc(); 159 if (fp == NULL) 160 goto bad; 161 if (mode&FTRUNC) 162 itrunc(ip, (u_long)0); 163 iunlock(ip); 164 fp->f_flag = mode&FMASK; 165 fp->f_type = DTYPE_INODE; 166 fp->f_ops = &inodeops; 167 fp->f_data = (caddr_t)ip; 168 i = u.u_r.r_val1; 169 #ifdef notdef 170 if (setjmp(&u.u_qsave)) { 171 if (u.u_error == 0) 172 u.u_error = EINTR; 173 u.u_ofile[i] = NULL; 174 closef(fp); 175 return; 176 } 177 #endif 178 u.u_error = openi(ip, mode); 179 if (u.u_error == 0) 180 return; 181 u.u_ofile[i] = NULL; 182 fp->f_count--; 183 irele(ip); 184 return; 185 bad: 186 iput(ip); 187 } 188 189 /* 190 * Mknod system call 191 */ 192 mknod() 193 { 194 register struct inode *ip; 195 register struct a { 196 char *fname; 197 int fmode; 198 int dev; 199 } *uap; 200 201 uap = (struct a *)u.u_ap; 202 if (!suser()) 203 return; 204 ip = namei(uchar, CREATE, 0); 205 if (ip != NULL) { 206 u.u_error = EEXIST; 207 goto out; 208 } 209 if (u.u_error) 210 return; 211 ip = maknode(uap->fmode); 212 if (ip == NULL) 213 return; 214 switch (ip->i_mode & IFMT) { 215 216 case IFMT: /* used by badsect to flag bad sectors */ 217 case IFCHR: 218 case IFBLK: 219 if (uap->dev) { 220 /* 221 * Want to be able to use this to make badblock 222 * inodes, so don't truncate the dev number. 223 */ 224 ip->i_rdev = uap->dev; 225 ip->i_flag |= IACC|IUPD|ICHG; 226 } 227 } 228 229 out: 230 iput(ip); 231 } 232 233 /* 234 * link system call 235 */ 236 link() 237 { 238 register struct inode *ip, *xp; 239 register struct a { 240 char *target; 241 char *linkname; 242 } *uap; 243 244 uap = (struct a *)u.u_ap; 245 ip = namei(uchar, LOOKUP, 1); /* well, this routine is doomed anyhow */ 246 if (ip == NULL) 247 return; 248 if ((ip->i_mode&IFMT) == IFDIR && !suser()) { 249 iput(ip); 250 return; 251 } 252 ip->i_nlink++; 253 ip->i_flag |= ICHG; 254 iupdat(ip, &time, &time, 1); 255 iunlock(ip); 256 u.u_dirp = (caddr_t)uap->linkname; 257 xp = namei(uchar, CREATE, 0); 258 if (xp != NULL) { 259 u.u_error = EEXIST; 260 iput(xp); 261 goto out; 262 } 263 if (u.u_error) 264 goto out; 265 if (u.u_pdir->i_dev != ip->i_dev) { 266 iput(u.u_pdir); 267 u.u_error = EXDEV; 268 goto out; 269 } 270 u.u_error = direnter(ip); 271 out: 272 if (u.u_error) { 273 ip->i_nlink--; 274 ip->i_flag |= ICHG; 275 } 276 irele(ip); 277 } 278 279 /* 280 * symlink -- make a symbolic link 281 */ 282 symlink() 283 { 284 register struct a { 285 char *target; 286 char *linkname; 287 } *uap; 288 register struct inode *ip; 289 register char *tp; 290 register c, nc; 291 292 uap = (struct a *)u.u_ap; 293 tp = uap->target; 294 nc = 0; 295 while (c = fubyte(tp)) { 296 if (c < 0) { 297 u.u_error = EFAULT; 298 return; 299 } 300 tp++; 301 nc++; 302 } 303 u.u_dirp = uap->linkname; 304 ip = namei(uchar, CREATE, 0); 305 if (ip) { 306 iput(ip); 307 u.u_error = EEXIST; 308 return; 309 } 310 if (u.u_error) 311 return; 312 ip = maknode(IFLNK | 0777); 313 if (ip == NULL) 314 return; 315 u.u_error = rdwri(UIO_WRITE, ip, uap->target, nc, 0, 0, (int *)0); 316 /* handle u.u_error != 0 */ 317 iput(ip); 318 } 319 320 /* 321 * Unlink system call. 322 * Hard to avoid races here, especially 323 * in unlinking directories. 324 */ 325 unlink() 326 { 327 struct a { 328 char *fname; 329 }; 330 register struct inode *ip, *dp; 331 332 ip = namei(uchar, DELETE | LOCKPARENT, 0); 333 if (ip == NULL) 334 return; 335 dp = u.u_pdir; 336 if ((ip->i_mode&IFMT) == IFDIR && !suser()) 337 goto out; 338 /* 339 * Don't unlink a mounted file. 340 */ 341 if (ip->i_dev != dp->i_dev) { 342 u.u_error = EBUSY; 343 goto out; 344 } 345 if (ip->i_flag&ITEXT) 346 xrele(ip); /* try once to free text */ 347 if (dirremove()) { 348 ip->i_nlink--; 349 ip->i_flag |= ICHG; 350 } 351 out: 352 if (dp == ip) 353 irele(ip); 354 else 355 iput(ip); 356 iput(dp); 357 } 358 359 /* 360 * Seek system call 361 */ 362 lseek() 363 { 364 register struct file *fp; 365 register struct a { 366 int fd; 367 off_t off; 368 int sbase; 369 } *uap; 370 371 uap = (struct a *)u.u_ap; 372 fp = getinode(uap->fd); 373 if (fp == NULL) 374 return; 375 switch (uap->sbase) { 376 377 case L_INCR: 378 fp->f_offset += uap->off; 379 break; 380 381 case L_XTND: 382 fp->f_offset = uap->off + ((struct inode *)fp->f_data)->i_size; 383 break; 384 385 case L_SET: 386 fp->f_offset = uap->off; 387 break; 388 389 default: 390 u.u_error = EINVAL; 391 return; 392 } 393 u.u_r.r_off = fp->f_offset; 394 } 395 396 /* 397 * Access system call 398 */ 399 saccess() 400 { 401 register svuid, svgid; 402 register struct inode *ip; 403 register struct a { 404 char *fname; 405 int fmode; 406 } *uap; 407 408 uap = (struct a *)u.u_ap; 409 svuid = u.u_uid; 410 svgid = u.u_gid; 411 u.u_uid = u.u_ruid; 412 u.u_gid = u.u_rgid; 413 ip = namei(uchar, LOOKUP, 1); 414 if (ip != NULL) { 415 if ((uap->fmode&R_OK) && access(ip, IREAD)) 416 goto done; 417 if ((uap->fmode&W_OK) && access(ip, IWRITE)) 418 goto done; 419 if ((uap->fmode&X_OK) && access(ip, IEXEC)) 420 goto done; 421 done: 422 iput(ip); 423 } 424 u.u_uid = svuid; 425 u.u_gid = svgid; 426 } 427 428 /* 429 * Stat system call. This version follows links. 430 */ 431 stat() 432 { 433 434 stat1(1); 435 } 436 437 /* 438 * Lstat system call. This version does not follow links. 439 */ 440 lstat() 441 { 442 443 stat1(0); 444 } 445 446 stat1(follow) 447 int follow; 448 { 449 register struct inode *ip; 450 register struct a { 451 char *fname; 452 struct stat *ub; 453 } *uap; 454 struct stat sb; 455 456 uap = (struct a *)u.u_ap; 457 ip = namei(uchar, LOOKUP, follow); 458 if (ip == NULL) 459 return; 460 (void) ino_stat(ip, &sb); 461 iput(ip); 462 u.u_error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); 463 } 464 465 /* 466 * Return target name of a symbolic link 467 */ 468 readlink() 469 { 470 register struct inode *ip; 471 register struct a { 472 char *name; 473 char *buf; 474 int count; 475 } *uap = (struct a *)u.u_ap; 476 int resid; 477 478 ip = namei(uchar, LOOKUP, 0); 479 if (ip == NULL) 480 return; 481 if ((ip->i_mode&IFMT) != IFLNK) { 482 u.u_error = ENXIO; 483 goto out; 484 } 485 u.u_error = rdwri(UIO_READ, ip, uap->buf, uap->count, 0, 0, &resid); 486 out: 487 iput(ip); 488 u.u_r.r_val1 = uap->count - resid; 489 } 490 491 /* 492 * Change mode of a file given path name. 493 */ 494 chmod() 495 { 496 struct inode *ip; 497 struct a { 498 char *fname; 499 int fmode; 500 } *uap; 501 502 uap = (struct a *)u.u_ap; 503 if ((ip = owner(1)) == NULL) 504 return; 505 chmod1(ip, uap->fmode); 506 iput(ip); 507 } 508 509 /* 510 * Change mode of a file given a file descriptor. 511 */ 512 fchmod() 513 { 514 struct a { 515 int fd; 516 int fmode; 517 } *uap; 518 register struct inode *ip; 519 register struct file *fp; 520 521 uap = (struct a *)u.u_ap; 522 fp = getinode(uap->fd); 523 if (fp == NULL) 524 return; 525 ip = (struct inode *)fp->f_data; 526 if (u.u_uid != ip->i_uid && !suser()) 527 return; 528 ilock(ip); 529 chmod1(ip, uap->fmode); 530 iunlock(ip); 531 } 532 533 /* 534 * Change the mode on a file. 535 * Inode must be locked before calling. 536 */ 537 chmod1(ip, mode) 538 register struct inode *ip; 539 register int mode; 540 { 541 542 ip->i_mode &= ~07777; 543 if (u.u_uid) { 544 mode &= ~ISVTX; 545 if (!groupmember(ip->i_gid)) 546 mode &= ~ISGID; 547 } 548 ip->i_mode |= mode&07777; 549 ip->i_flag |= ICHG; 550 if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0) 551 xrele(ip); 552 } 553 554 /* 555 * Set ownership given a path name. 556 */ 557 chown() 558 { 559 struct inode *ip; 560 struct a { 561 char *fname; 562 int uid; 563 int gid; 564 } *uap; 565 566 uap = (struct a *)u.u_ap; 567 if (!suser() || (ip = owner(0)) == NULL) 568 return; 569 u.u_error = chown1(ip, uap->uid, uap->gid); 570 iput(ip); 571 } 572 573 /* 574 * Set ownership given a file descriptor. 575 */ 576 fchown() 577 { 578 struct a { 579 int fd; 580 int uid; 581 int gid; 582 } *uap; 583 register struct inode *ip; 584 register struct file *fp; 585 586 uap = (struct a *)u.u_ap; 587 fp = getinode(uap->fd); 588 if (fp == NULL) 589 return; 590 ip = (struct inode *)fp->f_data; 591 if (!suser()) 592 return; 593 ilock(ip); 594 u.u_error = chown1(ip, uap->uid, uap->gid); 595 iunlock(ip); 596 } 597 598 /* 599 * Perform chown operation on inode ip; 600 * inode must be locked prior to call. 601 */ 602 chown1(ip, uid, gid) 603 register struct inode *ip; 604 int uid, gid; 605 { 606 #ifdef QUOTA 607 register long change; 608 #endif 609 610 if (uid == -1) 611 uid = ip->i_uid; 612 if (gid == -1) 613 gid = ip->i_gid; 614 #ifdef QUOTA 615 if (ip->i_uid == uid) /* this just speeds things a little */ 616 change = 0; 617 else 618 change = ip->i_blocks; 619 (void) chkdq(ip, -change, 1); 620 (void) chkiq(ip->i_dev, ip, ip->i_uid, 1); 621 dqrele(ip->i_dquot); 622 #endif 623 ip->i_uid = uid; 624 ip->i_gid = gid; 625 ip->i_flag |= ICHG; 626 if (u.u_ruid != 0) 627 ip->i_mode &= ~(ISUID|ISGID); 628 #ifdef QUOTA 629 ip->i_dquot = inoquota(ip); 630 (void) chkdq(ip, change, 1); 631 (void) chkiq(ip->i_dev, (struct inode *)NULL, uid, 1); 632 return (u.u_error); /* should == 0 ALWAYS !! */ 633 #else 634 return (0); 635 #endif 636 } 637 638 utimes() 639 { 640 register struct a { 641 char *fname; 642 struct timeval *tptr; 643 } *uap = (struct a *)u.u_ap; 644 register struct inode *ip; 645 struct timeval tv[2]; 646 647 if ((ip = owner(1)) == NULL) 648 return; 649 u.u_error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)); 650 if (u.u_error == 0) { 651 ip->i_flag |= IACC|IUPD|ICHG; 652 iupdat(ip, &tv[0], &tv[1], 0); 653 } 654 iput(ip); 655 } 656 657 /* 658 * Flush any pending I/O. 659 */ 660 sync() 661 { 662 663 update(); 664 } 665 666 /* 667 * Truncate a file given its path name. 668 */ 669 truncate() 670 { 671 struct a { 672 char *fname; 673 u_long length; 674 } *uap = (struct a *)u.u_ap; 675 struct inode *ip; 676 677 ip = namei(uchar, LOOKUP, 1); 678 if (ip == NULL) 679 return; 680 if (access(ip, IWRITE)) 681 goto bad; 682 if ((ip->i_mode&IFMT) == IFDIR) { 683 u.u_error = EISDIR; 684 goto bad; 685 } 686 itrunc(ip, uap->length); 687 bad: 688 iput(ip); 689 } 690 691 /* 692 * Truncate a file given a file descriptor. 693 */ 694 ftruncate() 695 { 696 struct a { 697 int fd; 698 u_long length; 699 } *uap = (struct a *)u.u_ap; 700 struct inode *ip; 701 struct file *fp; 702 703 fp = getinode(uap->fd); 704 if (fp == NULL) 705 return; 706 if ((fp->f_flag&FWRITE) == 0) { 707 u.u_error = EINVAL; 708 return; 709 } 710 ip = (struct inode *)fp->f_data; 711 ilock(ip); 712 itrunc(ip, uap->length); 713 iunlock(ip); 714 } 715 716 /* 717 * Synch an open file. 718 */ 719 fsync() 720 { 721 struct a { 722 int fd; 723 } *uap = (struct a *)u.u_ap; 724 struct inode *ip; 725 struct file *fp; 726 727 fp = getinode(uap->fd); 728 if (fp == NULL) 729 return; 730 ip = (struct inode *)fp->f_data; 731 ilock(ip); 732 syncip(ip); 733 iunlock(ip); 734 } 735 736 /* 737 * Rename system call. 738 * rename("foo", "bar"); 739 * is essentially 740 * unlink("bar"); 741 * link("foo", "bar"); 742 * unlink("foo"); 743 * but ``atomically''. Can't do full commit without saving state in the 744 * inode on disk which isn't feasible at this time. Best we can do is 745 * always guarantee the target exists. 746 * 747 * Basic algorithm is: 748 * 749 * 1) Bump link count on source while we're linking it to the 750 * target. This also insure the inode won't be deleted out 751 * from underneath us while we work. 752 * 2) Link source to destination. If destination already exists, 753 * delete it first. 754 * 3) Unlink source reference to inode if still around. 755 * 4) If a directory was moved and the parent of the destination 756 * is different from the source, patch the ".." entry in the 757 * directory. 758 * 759 * Source and destination must either both be directories, or both 760 * not be directories. If target is a directory, it must be empty. 761 */ 762 rename() 763 { 764 struct a { 765 char *from; 766 char *to; 767 } *uap; 768 register struct inode *ip, *xp, *dp; 769 int oldparent, parentdifferent, doingdirectory; 770 int error = 0; 771 772 uap = (struct a *)u.u_ap; 773 ip = namei(uchar, DELETE | LOCKPARENT, 0); 774 if (ip == NULL) 775 return; 776 dp = u.u_pdir; 777 oldparent = 0, doingdirectory = 0; 778 if ((ip->i_mode&IFMT) == IFDIR) { 779 register struct direct *d; 780 781 d = &u.u_dent; 782 /* 783 * Avoid ".", "..", and aliases of "." for obvious reasons. 784 */ 785 if ((d->d_namlen == 1 && d->d_name[0] == '.') || 786 (d->d_namlen == 2 && bcmp(d->d_name, "..", 2) == 0) || 787 (dp == ip)) { 788 iput(dp); 789 if (dp == ip) 790 irele(ip); 791 else 792 iput(ip); 793 u.u_error = EINVAL; 794 return; 795 } 796 oldparent = dp->i_number; 797 doingdirectory++; 798 } 799 iput(dp); 800 801 /* 802 * 1) Bump link count while we're moving stuff 803 * around. If we crash somewhere before 804 * completing our work, the link count 805 * may be wrong, but correctable. 806 */ 807 ip->i_nlink++; 808 ip->i_flag |= ICHG; 809 iupdat(ip, &time, &time, 1); 810 iunlock(ip); 811 812 /* 813 * When the target exists, both the directory 814 * and target inodes are returned locked. 815 */ 816 u.u_dirp = (caddr_t)uap->to; 817 xp = namei(uchar, CREATE | LOCKPARENT, 0); 818 if (u.u_error) { 819 error = u.u_error; 820 goto out; 821 } 822 dp = u.u_pdir; 823 /* 824 * If ".." must be changed (ie the directory gets a new 825 * parent) then the source directory must not be in the 826 * directory heirarchy above the target, as this would 827 * orphan everything below the source directory. Also 828 * the user must have write permission in the source so 829 * as to be able to change "..". We must repeat the call 830 * to namei, as the parent directory is unlocked by the 831 * call to checkpath(). 832 */ 833 parentdifferent = oldparent != dp->i_number; 834 if (doingdirectory && parentdifferent) { 835 if (access(ip, IWRITE)) 836 goto bad; 837 do { 838 dp = u.u_pdir; 839 if (xp != NULL) 840 iput(xp); 841 u.u_error = checkpath(ip, dp); 842 if (u.u_error) 843 goto out; 844 u.u_dirp = (caddr_t)uap->to; 845 xp = namei(uchar, CREATE | LOCKPARENT, 0); 846 if (u.u_error) { 847 error = u.u_error; 848 goto out; 849 } 850 } while (dp != u.u_pdir); 851 } 852 /* 853 * 2) If target doesn't exist, link the target 854 * to the source and unlink the source. 855 * Otherwise, rewrite the target directory 856 * entry to reference the source inode and 857 * expunge the original entry's existence. 858 */ 859 if (xp == NULL) { 860 if (dp->i_dev != ip->i_dev) { 861 error = EXDEV; 862 goto bad; 863 } 864 /* 865 * Account for ".." in directory. 866 * When source and destination have the 867 * same parent we don't fool with the 868 * link count -- this isn't required 869 * because we do a similar check below. 870 */ 871 if (doingdirectory && parentdifferent) { 872 dp->i_nlink++; 873 dp->i_flag |= ICHG; 874 iupdat(dp, &time, &time, 1); 875 } 876 error = direnter(ip); 877 if (error) 878 goto out; 879 } else { 880 if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev) { 881 error = EXDEV; 882 goto bad; 883 } 884 /* 885 * Short circuit rename(foo, foo). 886 */ 887 if (xp->i_number == ip->i_number) 888 goto bad; 889 /* 890 * Target must be empty if a directory 891 * and have no links to it. 892 * Also, insure source and target are 893 * compatible (both directories, or both 894 * not directories). 895 */ 896 if ((xp->i_mode&IFMT) == IFDIR) { 897 if (!dirempty(xp) || xp->i_nlink > 2) { 898 error = ENOTEMPTY; 899 goto bad; 900 } 901 if (!doingdirectory) { 902 error = ENOTDIR; 903 goto bad; 904 } 905 } else if (doingdirectory) { 906 error = EISDIR; 907 goto bad; 908 } 909 dirrewrite(dp, ip); 910 if (u.u_error) { 911 error = u.u_error; 912 goto bad1; 913 } 914 /* 915 * Adjust the link count of the target to 916 * reflect the dirrewrite above. If this is 917 * a directory it is empty and there are 918 * no links to it, so we can squash the inode and 919 * any space associated with it. We disallowed 920 * renaming over top of a directory with links to 921 * it above, as we've no way to determine if 922 * we've got a link or the directory itself, and 923 * if we get a link, then ".." will be screwed up. 924 */ 925 xp->i_nlink--; 926 if (doingdirectory) { 927 if (--xp->i_nlink != 0) 928 panic("rename: linked directory"); 929 itrunc(xp, (u_long)0); 930 } 931 xp->i_flag |= ICHG; 932 iput(xp); 933 xp = NULL; 934 } 935 936 /* 937 * 3) Unlink the source. 938 */ 939 u.u_dirp = uap->from; 940 dp = namei(uchar, DELETE, 0); 941 /* 942 * Insure directory entry still exists and 943 * has not changed since the start of all 944 * this. If either has occured, forget about 945 * about deleting the original entry and just 946 * adjust the link count in the inode. 947 */ 948 if (dp == NULL || u.u_dent.d_ino != ip->i_number) { 949 ip->i_nlink--; 950 ip->i_flag |= ICHG; 951 } else { 952 /* 953 * If source is a directory, must adjust 954 * link count of parent directory also. 955 * If target didn't exist and source and 956 * target have the same parent, then we 957 * needn't touch the link count, it all 958 * balances out in the end. Otherwise, we 959 * must do so to reflect deletion of ".." 960 * done above. 961 */ 962 if (doingdirectory && (xp != NULL || parentdifferent)) { 963 dp->i_nlink--; 964 dp->i_flag |= ICHG; 965 } 966 if (dirremove()) { 967 ip->i_nlink--; 968 ip->i_flag |= ICHG; 969 } 970 if (error == 0) /* conservative */ 971 error = u.u_error; 972 } 973 irele(ip); 974 if (dp) 975 iput(dp); 976 977 /* 978 * 4) Renaming a directory with the parent 979 * different requires ".." to be rewritten. 980 * The window is still there for ".." to 981 * be inconsistent, but this is unavoidable, 982 * and a lot shorter than when it was done 983 * in a user process. 984 */ 985 if (doingdirectory && parentdifferent && error == 0) { 986 struct dirtemplate dirbuf; 987 988 u.u_dirp = uap->to; 989 ip = namei(uchar, LOOKUP | LOCKPARENT, 0); 990 if (ip == NULL) { 991 printf("rename: .. went away\n"); 992 return; 993 } 994 dp = u.u_pdir; 995 if ((ip->i_mode&IFMT) != IFDIR) { 996 printf("rename: .. not a directory\n"); 997 goto stuck; 998 } 999 error = rdwri(UIO_READ, ip, (caddr_t)&dirbuf, 1000 sizeof (struct dirtemplate), (off_t)0, 1, (int *)0); 1001 if (error == 0) { 1002 dirbuf.dotdot_ino = dp->i_number; 1003 (void) rdwri(UIO_WRITE, ip, (caddr_t)&dirbuf, 1004 sizeof (struct dirtemplate), (off_t)0, 1, (int *)0); 1005 } 1006 stuck: 1007 irele(dp); 1008 iput(ip); 1009 } 1010 goto done; 1011 1012 bad: 1013 iput(dp); 1014 bad1: 1015 if (xp) 1016 iput(xp); 1017 out: 1018 ip->i_nlink--; 1019 ip->i_flag |= ICHG; 1020 irele(ip); 1021 done: 1022 if (error) 1023 u.u_error = error; 1024 } 1025 1026 /* 1027 * Make a new file. 1028 */ 1029 struct inode * 1030 maknode(mode) 1031 int mode; 1032 { 1033 register struct inode *ip; 1034 ino_t ipref; 1035 1036 if ((mode & IFMT) == IFDIR) 1037 ipref = dirpref(u.u_pdir->i_fs); 1038 else 1039 ipref = u.u_pdir->i_number; 1040 ip = ialloc(u.u_pdir, ipref, mode); 1041 if (ip == NULL) { 1042 iput(u.u_pdir); 1043 return (NULL); 1044 } 1045 #ifdef QUOTA 1046 if (ip->i_dquot != NODQUOT) 1047 panic("maknode: dquot"); 1048 #endif 1049 ip->i_flag |= IACC|IUPD|ICHG; 1050 if ((mode & IFMT) == 0) 1051 mode |= IFREG; 1052 ip->i_mode = mode & ~u.u_cmask; 1053 ip->i_nlink = 1; 1054 ip->i_uid = u.u_uid; 1055 ip->i_gid = u.u_pdir->i_gid; 1056 if (ip->i_mode & ISGID && !groupmember(ip->i_gid)) 1057 ip->i_mode &= ~ISGID; 1058 #ifdef QUOTA 1059 ip->i_dquot = inoquota(ip); 1060 #endif 1061 1062 /* 1063 * Make sure inode goes to disk before directory entry. 1064 */ 1065 iupdat(ip, &time, &time, 1); 1066 u.u_error = direnter(ip); 1067 if (u.u_error) { 1068 /* 1069 * Write error occurred trying to update directory 1070 * so must deallocate the inode. 1071 */ 1072 ip->i_nlink = 0; 1073 ip->i_flag |= ICHG; 1074 iput(ip); 1075 return (NULL); 1076 } 1077 return (ip); 1078 } 1079 1080 /* 1081 * A virgin directory (no blushing please). 1082 */ 1083 struct dirtemplate mastertemplate = { 1084 0, 12, 1, ".", 1085 0, DIRBLKSIZ - 12, 2, ".." 1086 }; 1087 1088 /* 1089 * Mkdir system call 1090 */ 1091 mkdir() 1092 { 1093 struct a { 1094 char *name; 1095 int dmode; 1096 } *uap; 1097 register struct inode *ip, *dp; 1098 struct dirtemplate dirtemplate; 1099 1100 uap = (struct a *)u.u_ap; 1101 ip = namei(uchar, CREATE, 0); 1102 if (u.u_error) 1103 return; 1104 if (ip != NULL) { 1105 iput(ip); 1106 u.u_error = EEXIST; 1107 return; 1108 } 1109 dp = u.u_pdir; 1110 uap->dmode &= 0777; 1111 uap->dmode |= IFDIR; 1112 /* 1113 * Must simulate part of maknode here 1114 * in order to acquire the inode, but 1115 * not have it entered in the parent 1116 * directory. The entry is made later 1117 * after writing "." and ".." entries out. 1118 */ 1119 ip = ialloc(dp, dirpref(dp->i_fs), uap->dmode); 1120 if (ip == NULL) { 1121 iput(dp); 1122 return; 1123 } 1124 #ifdef QUOTA 1125 if (ip->i_dquot != NODQUOT) 1126 panic("mkdir: dquot"); 1127 #endif 1128 ip->i_flag |= IACC|IUPD|ICHG; 1129 ip->i_mode = uap->dmode & ~u.u_cmask; 1130 ip->i_nlink = 2; 1131 ip->i_uid = u.u_uid; 1132 ip->i_gid = dp->i_gid; 1133 #ifdef QUOTA 1134 ip->i_dquot = inoquota(ip); 1135 #endif 1136 iupdat(ip, &time, &time, 1); 1137 1138 /* 1139 * Bump link count in parent directory 1140 * to reflect work done below. Should 1141 * be done before reference is created 1142 * so reparation is possible if we crash. 1143 */ 1144 dp->i_nlink++; 1145 dp->i_flag |= ICHG; 1146 iupdat(dp, &time, &time, 1); 1147 1148 /* 1149 * Initialize directory with "." 1150 * and ".." from static template. 1151 */ 1152 dirtemplate = mastertemplate; 1153 dirtemplate.dot_ino = ip->i_number; 1154 dirtemplate.dotdot_ino = dp->i_number; 1155 u.u_error = rdwri(UIO_WRITE, ip, (caddr_t)&dirtemplate, 1156 sizeof (dirtemplate), (off_t)0, 1, (int *)0); 1157 if (u.u_error) { 1158 dp->i_nlink--; 1159 dp->i_flag |= ICHG; 1160 goto bad; 1161 } 1162 /* 1163 * Directory all set up, now 1164 * install the entry for it in 1165 * the parent directory. 1166 */ 1167 u.u_error = direnter(ip); 1168 dp = NULL; 1169 if (u.u_error) { 1170 u.u_dirp = uap->name; 1171 dp = namei(uchar, LOOKUP, 0); 1172 if (dp) { 1173 dp->i_nlink--; 1174 dp->i_flag |= ICHG; 1175 } 1176 } 1177 bad: 1178 /* 1179 * No need to do an explicit itrunc here, 1180 * irele will do this for us because we set 1181 * the link count to 0. 1182 */ 1183 if (u.u_error) { 1184 ip->i_nlink = 0; 1185 ip->i_flag |= ICHG; 1186 } 1187 if (dp) 1188 iput(dp); 1189 iput(ip); 1190 } 1191 1192 /* 1193 * Rmdir system call. 1194 */ 1195 rmdir() 1196 { 1197 struct a { 1198 char *name; 1199 }; 1200 register struct inode *ip, *dp; 1201 1202 ip = namei(uchar, DELETE | LOCKPARENT, 0); 1203 if (ip == NULL) 1204 return; 1205 dp = u.u_pdir; 1206 /* 1207 * No rmdir "." please. 1208 */ 1209 if (dp == ip) { 1210 irele(dp); 1211 iput(ip); 1212 u.u_error = EINVAL; 1213 return; 1214 } 1215 if ((ip->i_mode&IFMT) != IFDIR) { 1216 u.u_error = ENOTDIR; 1217 goto out; 1218 } 1219 /* 1220 * Don't remove a mounted on directory. 1221 */ 1222 if (ip->i_dev != dp->i_dev) { 1223 u.u_error = EBUSY; 1224 goto out; 1225 } 1226 /* 1227 * Verify the directory is empty (and valid). 1228 * (Rmdir ".." won't be valid since 1229 * ".." will contain a reference to 1230 * the current directory and thus be 1231 * non-empty.) 1232 */ 1233 if (ip->i_nlink != 2 || !dirempty(ip)) { 1234 u.u_error = ENOTEMPTY; 1235 goto out; 1236 } 1237 /* 1238 * Delete reference to directory before purging 1239 * inode. If we crash in between, the directory 1240 * will be reattached to lost+found, 1241 */ 1242 if (dirremove() == 0) 1243 goto out; 1244 dp->i_nlink--; 1245 dp->i_flag |= ICHG; 1246 iput(dp); 1247 dp = NULL; 1248 /* 1249 * Truncate inode. The only stuff left 1250 * in the directory is "." and "..". The 1251 * "." reference is inconsequential since 1252 * we're quashing it. The ".." reference 1253 * has already been adjusted above. We've 1254 * removed the "." reference and the reference 1255 * in the parent directory, but there may be 1256 * other hard links so decrement by 2 and 1257 * worry about them later. 1258 */ 1259 ip->i_nlink -= 2; 1260 itrunc(ip, (u_long)0); 1261 out: 1262 if (dp) 1263 iput(dp); 1264 iput(ip); 1265 } 1266 1267 struct file * 1268 getinode(fdes) 1269 int fdes; 1270 { 1271 register struct file *fp; 1272 1273 fp = getf(fdes); 1274 if (fp == 0) 1275 return (0); 1276 if (fp->f_type != DTYPE_INODE) { 1277 u.u_error = EINVAL; 1278 return (0); 1279 } 1280 return (fp); 1281 } 1282 1283 /* 1284 * mode mask for creation of files 1285 */ 1286 umask() 1287 { 1288 register struct a { 1289 int mask; 1290 } *uap; 1291 1292 uap = (struct a *)u.u_ap; 1293 u.u_r.r_val1 = u.u_cmask; 1294 u.u_cmask = uap->mask & 07777; 1295 } 1296