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