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