1 /* lfs_vnops.c 6.10 84/07/04 */ 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 GETF(fp, uap->fd); 371 if (fp->f_type != DTYPE_INODE) { 372 u.u_error = ESPIPE; 373 return; 374 } 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 struct inode *zp; 770 int oldparent, parentdifferent, doingdirectory; 771 int error = 0; 772 773 uap = (struct a *)u.u_ap; 774 ip = namei(uchar, DELETE | LOCKPARENT, 0); 775 if (ip == NULL) 776 return; 777 dp = u.u_pdir; 778 oldparent = 0, doingdirectory = 0; 779 if ((ip->i_mode&IFMT) == IFDIR) { 780 register struct direct *d; 781 782 d = &u.u_dent; 783 /* 784 * Avoid ".", "..", and aliases of "." for obvious reasons. 785 */ 786 if ((d->d_namlen == 1 && d->d_name[0] == '.') || 787 (d->d_namlen == 2 && bcmp(d->d_name, "..", 2) == 0) || 788 (dp == ip)) { 789 iput(dp); 790 if (dp == ip) 791 irele(ip); 792 else 793 iput(ip); 794 u.u_error = EINVAL; 795 return; 796 } 797 oldparent = dp->i_number; 798 doingdirectory++; 799 } 800 iput(dp); 801 802 /* 803 * 1) Bump link count while we're moving stuff 804 * around. If we crash somewhere before 805 * completing our work, the link count 806 * may be wrong, but correctable. 807 */ 808 ip->i_nlink++; 809 ip->i_flag |= ICHG; 810 iupdat(ip, &time, &time, 1); 811 IUNLOCK(ip); 812 813 /* 814 * When the target exists, both the directory 815 * and target inodes are returned locked. 816 */ 817 u.u_dirp = (caddr_t)uap->to; 818 xp = namei(uchar, CREATE | LOCKPARENT | NOCACHE, 0); 819 if (u.u_error) { 820 error = u.u_error; 821 goto out; 822 } 823 dp = u.u_pdir; 824 /* 825 * If ".." must be changed (ie the directory gets a new 826 * parent) then the source directory must not be in the 827 * directory heirarchy above the target, as this would 828 * orphan everything below the source directory. Also 829 * the user must have write permission in the source so 830 * as to be able to change "..". We must repeat the call 831 * to namei, as the parent directory is unlocked by the 832 * call to checkpath(). 833 */ 834 parentdifferent = oldparent != dp->i_number; 835 if (doingdirectory && parentdifferent) { 836 if (access(ip, IWRITE)) 837 goto bad; 838 do { 839 dp = u.u_pdir; 840 if (xp != NULL) 841 iput(xp); 842 u.u_error = checkpath(ip, dp); 843 if (u.u_error) 844 goto out; 845 u.u_dirp = (caddr_t)uap->to; 846 xp = namei(uchar, CREATE | LOCKPARENT | NOCACHE, 0); 847 if (u.u_error) { 848 error = u.u_error; 849 goto out; 850 } 851 } while (dp != u.u_pdir); 852 } 853 /* 854 * 2) If target doesn't exist, link the target 855 * to the source and unlink the source. 856 * Otherwise, rewrite the target directory 857 * entry to reference the source inode and 858 * expunge the original entry's existence. 859 */ 860 if (xp == NULL) { 861 if (dp->i_dev != ip->i_dev) { 862 error = EXDEV; 863 goto bad; 864 } 865 /* 866 * Account for ".." in directory. 867 * When source and destination have the 868 * same parent we don't fool with the 869 * link count -- this isn't required 870 * because we do a similar check below. 871 */ 872 if (doingdirectory && parentdifferent) { 873 dp->i_nlink++; 874 dp->i_flag |= ICHG; 875 iupdat(dp, &time, &time, 1); 876 } 877 error = direnter(ip); 878 if (error) 879 goto out; 880 } else { 881 if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev) { 882 error = EXDEV; 883 goto bad; 884 } 885 /* 886 * Short circuit rename(foo, foo). 887 */ 888 if (xp->i_number == ip->i_number) 889 goto bad; 890 /* 891 * Target must be empty if a directory 892 * and have no links to it. 893 * Also, insure source and target are 894 * compatible (both directories, or both 895 * not directories). 896 */ 897 if ((xp->i_mode&IFMT) == IFDIR) { 898 if (!dirempty(xp) || xp->i_nlink > 2) { 899 error = ENOTEMPTY; 900 goto bad; 901 } 902 if (!doingdirectory) { 903 error = ENOTDIR; 904 goto bad; 905 } 906 } else if (doingdirectory) { 907 error = EISDIR; 908 goto bad; 909 } 910 dirrewrite(dp, ip); 911 if (u.u_error) { 912 error = u.u_error; 913 goto bad1; 914 } 915 /* 916 * Adjust the link count of the target to 917 * reflect the dirrewrite above. If this is 918 * a directory it is empty and there are 919 * no links to it, so we can squash the inode and 920 * any space associated with it. We disallowed 921 * renaming over top of a directory with links to 922 * it above, as we've no way to determine if 923 * we've got a link or the directory itself, and 924 * if we get a link, then ".." will be screwed up. 925 */ 926 xp->i_nlink--; 927 if (doingdirectory) { 928 if (--xp->i_nlink != 0) 929 panic("rename: linked directory"); 930 itrunc(xp, (u_long)0); 931 } 932 xp->i_flag |= ICHG; 933 iput(xp); 934 xp = NULL; 935 } 936 937 /* 938 * 3) Unlink the source. 939 */ 940 u.u_dirp = uap->from; 941 zp = namei(uchar, DELETE | LOCKPARENT, 0); 942 dp = u.u_pdir; 943 /* 944 * Insure directory entry still exists and 945 * has not changed since the start of all 946 * this. If either has occured, forget about 947 * about deleting the original entry. 948 */ 949 if (dp != NULL && zp == ip) { 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 zp->i_nlink--; 966 zp->i_flag |= ICHG; 967 } 968 if (error == 0) /* conservative */ 969 error = u.u_error; 970 } 971 if (zp != NULL) 972 iput(zp); 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 dp->i_id = ++nextinodeid; 1004 (void) rdwri(UIO_WRITE, ip, (caddr_t)&dirbuf, 1005 sizeof (struct dirtemplate), (off_t)0, 1, (int *)0); 1006 } 1007 stuck: 1008 irele(dp); 1009 iput(ip); 1010 } 1011 goto done; 1012 1013 bad: 1014 iput(dp); 1015 bad1: 1016 if (xp) 1017 iput(xp); 1018 out: 1019 ip->i_nlink--; 1020 ip->i_flag |= ICHG; 1021 irele(ip); 1022 done: 1023 if (error) 1024 u.u_error = error; 1025 } 1026 1027 /* 1028 * Make a new file. 1029 */ 1030 struct inode * 1031 maknode(mode) 1032 int mode; 1033 { 1034 register struct inode *ip; 1035 ino_t ipref; 1036 1037 if ((mode & IFMT) == IFDIR) 1038 ipref = dirpref(u.u_pdir->i_fs); 1039 else 1040 ipref = u.u_pdir->i_number; 1041 ip = ialloc(u.u_pdir, ipref, mode); 1042 if (ip == NULL) { 1043 iput(u.u_pdir); 1044 return (NULL); 1045 } 1046 #ifdef QUOTA 1047 if (ip->i_dquot != NODQUOT) 1048 panic("maknode: dquot"); 1049 #endif 1050 ip->i_flag |= IACC|IUPD|ICHG; 1051 if ((mode & IFMT) == 0) 1052 mode |= IFREG; 1053 ip->i_mode = mode & ~u.u_cmask; 1054 ip->i_nlink = 1; 1055 ip->i_uid = u.u_uid; 1056 ip->i_gid = u.u_pdir->i_gid; 1057 if (ip->i_mode & ISGID && !groupmember(ip->i_gid)) 1058 ip->i_mode &= ~ISGID; 1059 #ifdef QUOTA 1060 ip->i_dquot = inoquota(ip); 1061 #endif 1062 1063 /* 1064 * Make sure inode goes to disk before directory entry. 1065 */ 1066 iupdat(ip, &time, &time, 1); 1067 u.u_error = direnter(ip); 1068 if (u.u_error) { 1069 /* 1070 * Write error occurred trying to update directory 1071 * so must deallocate the inode. 1072 */ 1073 ip->i_nlink = 0; 1074 ip->i_flag |= ICHG; 1075 iput(ip); 1076 return (NULL); 1077 } 1078 return (ip); 1079 } 1080 1081 /* 1082 * A virgin directory (no blushing please). 1083 */ 1084 struct dirtemplate mastertemplate = { 1085 0, 12, 1, ".", 1086 0, DIRBLKSIZ - 12, 2, ".." 1087 }; 1088 1089 /* 1090 * Mkdir system call 1091 */ 1092 mkdir() 1093 { 1094 struct a { 1095 char *name; 1096 int dmode; 1097 } *uap; 1098 register struct inode *ip, *dp; 1099 struct dirtemplate dirtemplate; 1100 1101 uap = (struct a *)u.u_ap; 1102 ip = namei(uchar, CREATE, 0); 1103 if (u.u_error) 1104 return; 1105 if (ip != NULL) { 1106 iput(ip); 1107 u.u_error = EEXIST; 1108 return; 1109 } 1110 dp = u.u_pdir; 1111 uap->dmode &= 0777; 1112 uap->dmode |= IFDIR; 1113 /* 1114 * Must simulate part of maknode here 1115 * in order to acquire the inode, but 1116 * not have it entered in the parent 1117 * directory. The entry is made later 1118 * after writing "." and ".." entries out. 1119 */ 1120 ip = ialloc(dp, dirpref(dp->i_fs), uap->dmode); 1121 if (ip == NULL) { 1122 iput(dp); 1123 return; 1124 } 1125 #ifdef QUOTA 1126 if (ip->i_dquot != NODQUOT) 1127 panic("mkdir: dquot"); 1128 #endif 1129 ip->i_flag |= IACC|IUPD|ICHG; 1130 ip->i_mode = uap->dmode & ~u.u_cmask; 1131 ip->i_nlink = 2; 1132 ip->i_uid = u.u_uid; 1133 ip->i_gid = dp->i_gid; 1134 #ifdef QUOTA 1135 ip->i_dquot = inoquota(ip); 1136 #endif 1137 iupdat(ip, &time, &time, 1); 1138 1139 /* 1140 * Bump link count in parent directory 1141 * to reflect work done below. Should 1142 * be done before reference is created 1143 * so reparation is possible if we crash. 1144 */ 1145 dp->i_nlink++; 1146 dp->i_flag |= ICHG; 1147 iupdat(dp, &time, &time, 1); 1148 1149 /* 1150 * Initialize directory with "." 1151 * and ".." from static template. 1152 */ 1153 dirtemplate = mastertemplate; 1154 dirtemplate.dot_ino = ip->i_number; 1155 dirtemplate.dotdot_ino = dp->i_number; 1156 u.u_error = rdwri(UIO_WRITE, ip, (caddr_t)&dirtemplate, 1157 sizeof (dirtemplate), (off_t)0, 1, (int *)0); 1158 if (u.u_error) { 1159 dp->i_nlink--; 1160 dp->i_flag |= ICHG; 1161 goto bad; 1162 } 1163 /* 1164 * Directory all set up, now 1165 * install the entry for it in 1166 * the parent directory. 1167 */ 1168 u.u_error = direnter(ip); 1169 dp = NULL; 1170 if (u.u_error) { 1171 u.u_dirp = uap->name; 1172 dp = namei(uchar, LOOKUP | NOCACHE, 0); 1173 if (dp) { 1174 dp->i_nlink--; 1175 dp->i_flag |= ICHG; 1176 } 1177 } 1178 bad: 1179 /* 1180 * No need to do an explicit itrunc here, 1181 * irele will do this for us because we set 1182 * the link count to 0. 1183 */ 1184 if (u.u_error) { 1185 ip->i_nlink = 0; 1186 ip->i_flag |= ICHG; 1187 } 1188 if (dp) 1189 iput(dp); 1190 iput(ip); 1191 } 1192 1193 /* 1194 * Rmdir system call. 1195 */ 1196 rmdir() 1197 { 1198 struct a { 1199 char *name; 1200 }; 1201 register struct inode *ip, *dp; 1202 1203 ip = namei(uchar, DELETE | LOCKPARENT, 0); 1204 if (ip == NULL) 1205 return; 1206 dp = u.u_pdir; 1207 /* 1208 * No rmdir "." please. 1209 */ 1210 if (dp == ip) { 1211 irele(dp); 1212 iput(ip); 1213 u.u_error = EINVAL; 1214 return; 1215 } 1216 if ((ip->i_mode&IFMT) != IFDIR) { 1217 u.u_error = ENOTDIR; 1218 goto out; 1219 } 1220 /* 1221 * Don't remove a mounted on directory. 1222 */ 1223 if (ip->i_dev != dp->i_dev) { 1224 u.u_error = EBUSY; 1225 goto out; 1226 } 1227 /* 1228 * Verify the directory is empty (and valid). 1229 * (Rmdir ".." won't be valid since 1230 * ".." will contain a reference to 1231 * the current directory and thus be 1232 * non-empty.) 1233 */ 1234 if (ip->i_nlink != 2 || !dirempty(ip)) { 1235 u.u_error = ENOTEMPTY; 1236 goto out; 1237 } 1238 /* 1239 * Delete reference to directory before purging 1240 * inode. If we crash in between, the directory 1241 * will be reattached to lost+found, 1242 */ 1243 if (dirremove() == 0) 1244 goto out; 1245 dp->i_nlink--; 1246 dp->i_flag |= ICHG; 1247 iput(dp); 1248 dp = NULL; 1249 /* 1250 * Truncate inode. The only stuff left 1251 * in the directory is "." and "..". The 1252 * "." reference is inconsequential since 1253 * we're quashing it. The ".." reference 1254 * has already been adjusted above. We've 1255 * removed the "." reference and the reference 1256 * in the parent directory, but there may be 1257 * other hard links so decrement by 2 and 1258 * worry about them later. 1259 */ 1260 ip->i_nlink -= 2; 1261 itrunc(ip, (u_long)0); 1262 out: 1263 if (dp) 1264 iput(dp); 1265 iput(ip); 1266 } 1267 1268 struct file * 1269 getinode(fdes) 1270 int fdes; 1271 { 1272 struct file *fp; 1273 1274 if ((unsigned)fdes >= NOFILE || (fp = u.u_ofile[fdes]) == NULL) { 1275 u.u_error = EBADF; 1276 return ((struct file *)0); 1277 } 1278 if (fp->f_type != DTYPE_INODE) { 1279 u.u_error = EINVAL; 1280 return ((struct file *)0); 1281 } 1282 return (fp); 1283 } 1284 1285 /* 1286 * mode mask for creation of files 1287 */ 1288 umask() 1289 { 1290 register struct a { 1291 int mask; 1292 } *uap; 1293 1294 uap = (struct a *)u.u_ap; 1295 u.u_r.r_val1 = u.u_cmask; 1296 u.u_cmask = uap->mask & 07777; 1297 } 1298