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