1 /* vfs_syscalls.c 6.18 85/05/22 */ 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 = EINVAL; 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 u.u_error = 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 u.u_error = 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 if (ip->i_fs->fs_ronly) 576 return (EROFS); 577 ip->i_mode &= ~07777; 578 if (u.u_uid) { 579 if ((ip->i_mode & IFMT) != IFDIR) 580 mode &= ~ISVTX; 581 if (!groupmember(ip->i_gid)) 582 mode &= ~ISGID; 583 } 584 ip->i_mode |= mode&07777; 585 ip->i_flag |= ICHG; 586 if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0) 587 xrele(ip); 588 return (0); 589 } 590 591 /* 592 * Set ownership given a path name. 593 */ 594 chown() 595 { 596 struct inode *ip; 597 struct a { 598 char *fname; 599 int uid; 600 int gid; 601 } *uap = (struct a *)u.u_ap; 602 603 if (!suser() || (ip = owner(uap->fname, NOFOLLOW)) == NULL) 604 return; 605 u.u_error = chown1(ip, uap->uid, uap->gid); 606 iput(ip); 607 } 608 609 /* 610 * Set ownership given a file descriptor. 611 */ 612 fchown() 613 { 614 struct a { 615 int fd; 616 int uid; 617 int gid; 618 } *uap = (struct a *)u.u_ap; 619 register struct inode *ip; 620 register struct file *fp; 621 622 fp = getinode(uap->fd); 623 if (fp == NULL) 624 return; 625 ip = (struct inode *)fp->f_data; 626 if (!suser()) 627 return; 628 ILOCK(ip); 629 u.u_error = chown1(ip, uap->uid, uap->gid); 630 IUNLOCK(ip); 631 } 632 633 /* 634 * Perform chown operation on inode ip; 635 * inode must be locked prior to call. 636 */ 637 chown1(ip, uid, gid) 638 register struct inode *ip; 639 int uid, gid; 640 { 641 #ifdef QUOTA 642 register long change; 643 #endif 644 645 if (ip->i_fs->fs_ronly) 646 return (EROFS); 647 if (uid == -1) 648 uid = ip->i_uid; 649 if (gid == -1) 650 gid = ip->i_gid; 651 #ifdef QUOTA 652 if (ip->i_uid == uid) /* this just speeds things a little */ 653 change = 0; 654 else 655 change = ip->i_blocks; 656 (void) chkdq(ip, -change, 1); 657 (void) chkiq(ip->i_dev, ip, ip->i_uid, 1); 658 dqrele(ip->i_dquot); 659 #endif 660 ip->i_uid = uid; 661 ip->i_gid = gid; 662 ip->i_flag |= ICHG; 663 if (u.u_ruid != 0) 664 ip->i_mode &= ~(ISUID|ISGID); 665 #ifdef QUOTA 666 ip->i_dquot = inoquota(ip); 667 (void) chkdq(ip, change, 1); 668 (void) chkiq(ip->i_dev, (struct inode *)NULL, uid, 1); 669 return (u.u_error); /* should == 0 ALWAYS !! */ 670 #else 671 return (0); 672 #endif 673 } 674 675 utimes() 676 { 677 register struct a { 678 char *fname; 679 struct timeval *tptr; 680 } *uap = (struct a *)u.u_ap; 681 register struct inode *ip; 682 struct timeval tv[2]; 683 684 if ((ip = owner(uap->fname, FOLLOW)) == NULL) 685 return; 686 if (ip->i_fs->fs_ronly) { 687 u.u_error = EROFS; 688 iput(ip); 689 return; 690 } 691 u.u_error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)); 692 if (u.u_error == 0) { 693 ip->i_flag |= IACC|IUPD|ICHG; 694 iupdat(ip, &tv[0], &tv[1], 0); 695 } 696 iput(ip); 697 } 698 699 /* 700 * Flush any pending I/O. 701 */ 702 sync() 703 { 704 705 update(); 706 } 707 708 /* 709 * Truncate a file given its path name. 710 */ 711 truncate() 712 { 713 struct a { 714 char *fname; 715 u_long length; 716 } *uap = (struct a *)u.u_ap; 717 struct inode *ip; 718 register struct nameidata *ndp = &u.u_nd; 719 720 ndp->ni_nameiop = LOOKUP | FOLLOW; 721 ndp->ni_segflg = UIO_USERSPACE; 722 ndp->ni_dirp = uap->fname; 723 ip = namei(ndp); 724 if (ip == NULL) 725 return; 726 if (access(ip, IWRITE)) 727 goto bad; 728 if ((ip->i_mode&IFMT) == IFDIR) { 729 u.u_error = EISDIR; 730 goto bad; 731 } 732 itrunc(ip, uap->length); 733 bad: 734 iput(ip); 735 } 736 737 /* 738 * Truncate a file given a file descriptor. 739 */ 740 ftruncate() 741 { 742 struct a { 743 int fd; 744 u_long length; 745 } *uap = (struct a *)u.u_ap; 746 struct inode *ip; 747 struct file *fp; 748 749 fp = getinode(uap->fd); 750 if (fp == NULL) 751 return; 752 if ((fp->f_flag&FWRITE) == 0) { 753 u.u_error = EINVAL; 754 return; 755 } 756 ip = (struct inode *)fp->f_data; 757 ILOCK(ip); 758 itrunc(ip, uap->length); 759 IUNLOCK(ip); 760 } 761 762 /* 763 * Synch an open file. 764 */ 765 fsync() 766 { 767 struct a { 768 int fd; 769 } *uap = (struct a *)u.u_ap; 770 struct inode *ip; 771 struct file *fp; 772 773 fp = getinode(uap->fd); 774 if (fp == NULL) 775 return; 776 ip = (struct inode *)fp->f_data; 777 ILOCK(ip); 778 syncip(ip); 779 IUNLOCK(ip); 780 } 781 782 /* 783 * Rename system call. 784 * rename("foo", "bar"); 785 * is essentially 786 * unlink("bar"); 787 * link("foo", "bar"); 788 * unlink("foo"); 789 * but ``atomically''. Can't do full commit without saving state in the 790 * inode on disk which isn't feasible at this time. Best we can do is 791 * always guarantee the target exists. 792 * 793 * Basic algorithm is: 794 * 795 * 1) Bump link count on source while we're linking it to the 796 * target. This also insure the inode won't be deleted out 797 * from underneath us while we work (it may be truncated by 798 * a concurrent `trunc' or `open' for creation). 799 * 2) Link source to destination. If destination already exists, 800 * delete it first. 801 * 3) Unlink source reference to inode if still around. If a 802 * directory was moved and the parent of the destination 803 * is different from the source, patch the ".." entry in the 804 * directory. 805 * 806 * Source and destination must either both be directories, or both 807 * not be directories. If target is a directory, it must be empty. 808 */ 809 rename() 810 { 811 struct a { 812 char *from; 813 char *to; 814 } *uap = (struct a *)u.u_ap; 815 register struct inode *ip, *xp, *dp; 816 struct dirtemplate dirbuf; 817 int doingdirectory = 0, oldparent = 0, newparent = 0; 818 register struct nameidata *ndp = &u.u_nd; 819 int error = 0; 820 821 ndp->ni_nameiop = DELETE | LOCKPARENT; 822 ndp->ni_segflg = UIO_USERSPACE; 823 ndp->ni_dirp = uap->from; 824 ip = namei(ndp); 825 if (ip == NULL) 826 return; 827 dp = ndp->ni_pdir; 828 if ((ip->i_mode&IFMT) == IFDIR) { 829 register struct direct *d; 830 831 d = &ndp->ni_dent; 832 /* 833 * Avoid ".", "..", and aliases of "." for obvious reasons. 834 */ 835 if ((d->d_namlen == 1 && d->d_name[0] == '.') || 836 (d->d_namlen == 2 && bcmp(d->d_name, "..", 2) == 0) || 837 (dp == ip) || (ip->i_flag & IRENAME)) { 838 iput(dp); 839 if (dp == ip) 840 irele(ip); 841 else 842 iput(ip); 843 u.u_error = EINVAL; 844 return; 845 } 846 ip->i_flag |= IRENAME; 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 ndp->ni_nameiop = CREATE | LOCKPARENT | NOCACHE; 868 ndp->ni_dirp = (caddr_t)uap->to; 869 xp = namei(ndp); 870 if (u.u_error) { 871 error = u.u_error; 872 goto out; 873 } 874 dp = ndp->ni_pdir; 875 /* 876 * If ".." must be changed (ie the directory gets a new 877 * parent) then the source directory must not be in the 878 * directory heirarchy above the target, as this would 879 * orphan everything below the source directory. Also 880 * the user must have write permission in the source so 881 * as to be able to change "..". We must repeat the call 882 * to namei, as the parent directory is unlocked by the 883 * call to checkpath(). 884 */ 885 if (oldparent != dp->i_number) 886 newparent = dp->i_number; 887 if (doingdirectory && newparent) { 888 if (access(ip, IWRITE)) 889 goto bad; 890 do { 891 dp = ndp->ni_pdir; 892 if (xp != NULL) 893 iput(xp); 894 u.u_error = checkpath(ip, dp); 895 if (u.u_error) 896 goto out; 897 xp = namei(ndp); 898 if (u.u_error) { 899 error = u.u_error; 900 goto out; 901 } 902 } while (dp != ndp->ni_pdir); 903 } 904 /* 905 * 2) If target doesn't exist, link the target 906 * to the source and unlink the source. 907 * Otherwise, rewrite the target directory 908 * entry to reference the source inode and 909 * expunge the original entry's existence. 910 */ 911 if (xp == NULL) { 912 if (dp->i_dev != ip->i_dev) { 913 error = EXDEV; 914 goto bad; 915 } 916 /* 917 * Account for ".." in new directory. 918 * When source and destination have the same 919 * parent we don't fool with the link count. 920 */ 921 if (doingdirectory && newparent) { 922 dp->i_nlink++; 923 dp->i_flag |= ICHG; 924 iupdat(dp, &time, &time, 1); 925 } 926 error = direnter(ip, ndp); 927 if (error) 928 goto out; 929 } else { 930 if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev) { 931 error = EXDEV; 932 goto bad; 933 } 934 /* 935 * Short circuit rename(foo, foo). 936 */ 937 if (xp->i_number == ip->i_number) 938 goto bad; 939 /* 940 * Target must be empty if a directory 941 * and have no links to it. 942 * Also, insure source and target are 943 * compatible (both directories, or both 944 * not directories). 945 */ 946 if ((xp->i_mode&IFMT) == IFDIR) { 947 if (!dirempty(xp, dp->i_number) || xp->i_nlink > 2) { 948 error = ENOTEMPTY; 949 goto bad; 950 } 951 if (!doingdirectory) { 952 error = ENOTDIR; 953 goto bad; 954 } 955 cacheinval(dp); 956 } else if (doingdirectory) { 957 error = EISDIR; 958 goto bad; 959 } 960 dirrewrite(dp, ip, ndp); 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 the remaining link would point to 973 * a directory without "." or ".." entries. 974 */ 975 xp->i_nlink--; 976 if (doingdirectory) { 977 if (--xp->i_nlink != 0) 978 panic("rename: linked directory"); 979 itrunc(xp, (u_long)0); 980 } 981 xp->i_flag |= ICHG; 982 iput(xp); 983 xp = NULL; 984 } 985 986 /* 987 * 3) Unlink the source. 988 */ 989 ndp->ni_nameiop = DELETE | LOCKPARENT; 990 ndp->ni_segflg = UIO_USERSPACE; 991 ndp->ni_dirp = uap->from; 992 xp = namei(ndp); 993 if (xp != NULL) 994 dp = ndp->ni_pdir; 995 else 996 dp = NULL; 997 /* 998 * Insure that the directory entry still exists and has not 999 * changed while the new name has been entered. If the source is 1000 * a file then the entry may have been unlinked or renamed. In 1001 * either case there is no further work to be done. If the source 1002 * is a directory then it cannot have been rmdir'ed; its link 1003 * count of three would cause a rmdir to fail with ENOTEMPTY. 1004 * The IRENAME flag insures that it cannot be moved by another 1005 * rename. 1006 */ 1007 if (xp != ip) { 1008 if (doingdirectory) 1009 panic("rename: lost dir entry"); 1010 } else { 1011 /* 1012 * If the source is a directory with a 1013 * new parent, the link count of the old 1014 * parent directory must be decremented 1015 * and ".." set to point to the new parent. 1016 */ 1017 if (doingdirectory && newparent) { 1018 dp->i_nlink--; 1019 dp->i_flag |= ICHG; 1020 error = rdwri(UIO_READ, xp, (caddr_t)&dirbuf, 1021 sizeof (struct dirtemplate), (off_t)0, 1, 1022 (int *)0); 1023 if (error == 0) { 1024 if (dirbuf.dotdot_namlen != 2 || 1025 dirbuf.dotdot_name[0] != '.' || 1026 dirbuf.dotdot_name[1] != '.') { 1027 printf("rename: mangled dir\n"); 1028 } else { 1029 dirbuf.dotdot_ino = newparent; 1030 (void) rdwri(UIO_WRITE, xp, 1031 (caddr_t)&dirbuf, 1032 sizeof (struct dirtemplate), 1033 (off_t)0, 1, (int *)0); 1034 cacheinval(dp); 1035 } 1036 } 1037 } 1038 if (dirremove(ndp)) { 1039 xp->i_nlink--; 1040 xp->i_flag |= ICHG; 1041 } 1042 xp->i_flag &= ~IRENAME; 1043 if (error == 0) /* XXX conservative */ 1044 error = u.u_error; 1045 } 1046 if (dp) 1047 iput(dp); 1048 if (xp) 1049 iput(xp); 1050 irele(ip); 1051 if (error) 1052 u.u_error = error; 1053 return; 1054 1055 bad: 1056 iput(dp); 1057 bad1: 1058 if (xp) 1059 iput(xp); 1060 out: 1061 ip->i_nlink--; 1062 ip->i_flag |= ICHG; 1063 irele(ip); 1064 if (error) 1065 u.u_error = error; 1066 } 1067 1068 /* 1069 * Make a new file. 1070 */ 1071 struct inode * 1072 maknode(mode, ndp) 1073 int mode; 1074 register struct nameidata *ndp; 1075 { 1076 register struct inode *ip; 1077 register struct inode *pdir = ndp->ni_pdir; 1078 ino_t ipref; 1079 1080 if ((mode & IFMT) == IFDIR) 1081 ipref = dirpref(pdir->i_fs); 1082 else 1083 ipref = pdir->i_number; 1084 ip = ialloc(pdir, ipref, mode); 1085 if (ip == NULL) { 1086 iput(pdir); 1087 return (NULL); 1088 } 1089 #ifdef QUOTA 1090 if (ip->i_dquot != NODQUOT) 1091 panic("maknode: dquot"); 1092 #endif 1093 ip->i_flag |= IACC|IUPD|ICHG; 1094 if ((mode & IFMT) == 0) 1095 mode |= IFREG; 1096 ip->i_mode = mode & ~u.u_cmask; 1097 ip->i_nlink = 1; 1098 ip->i_uid = u.u_uid; 1099 ip->i_gid = pdir->i_gid; 1100 if (ip->i_mode & ISGID && !groupmember(ip->i_gid)) 1101 ip->i_mode &= ~ISGID; 1102 #ifdef QUOTA 1103 ip->i_dquot = inoquota(ip); 1104 #endif 1105 1106 /* 1107 * Make sure inode goes to disk before directory entry. 1108 */ 1109 iupdat(ip, &time, &time, 1); 1110 u.u_error = direnter(ip, ndp); 1111 if (u.u_error) { 1112 /* 1113 * Write error occurred trying to update directory 1114 * so must deallocate the inode. 1115 */ 1116 ip->i_nlink = 0; 1117 ip->i_flag |= ICHG; 1118 iput(ip); 1119 return (NULL); 1120 } 1121 return (ip); 1122 } 1123 1124 /* 1125 * A virgin directory (no blushing please). 1126 */ 1127 struct dirtemplate mastertemplate = { 1128 0, 12, 1, ".", 1129 0, DIRBLKSIZ - 12, 2, ".." 1130 }; 1131 1132 /* 1133 * Mkdir system call 1134 */ 1135 mkdir() 1136 { 1137 struct a { 1138 char *name; 1139 int dmode; 1140 } *uap = (struct a *)u.u_ap; 1141 register struct inode *ip, *dp; 1142 struct dirtemplate dirtemplate; 1143 register struct nameidata *ndp = &u.u_nd; 1144 1145 ndp->ni_nameiop = CREATE; 1146 ndp->ni_segflg = UIO_USERSPACE; 1147 ndp->ni_dirp = uap->name; 1148 ip = namei(ndp); 1149 if (u.u_error) 1150 return; 1151 if (ip != NULL) { 1152 iput(ip); 1153 u.u_error = EEXIST; 1154 return; 1155 } 1156 dp = ndp->ni_pdir; 1157 uap->dmode &= 0777; 1158 uap->dmode |= IFDIR; 1159 /* 1160 * Must simulate part of maknode here 1161 * in order to acquire the inode, but 1162 * not have it entered in the parent 1163 * directory. The entry is made later 1164 * after writing "." and ".." entries out. 1165 */ 1166 ip = ialloc(dp, dirpref(dp->i_fs), uap->dmode); 1167 if (ip == NULL) { 1168 iput(dp); 1169 return; 1170 } 1171 #ifdef QUOTA 1172 if (ip->i_dquot != NODQUOT) 1173 panic("mkdir: dquot"); 1174 #endif 1175 ip->i_flag |= IACC|IUPD|ICHG; 1176 ip->i_mode = uap->dmode & ~u.u_cmask; 1177 ip->i_nlink = 2; 1178 ip->i_uid = u.u_uid; 1179 ip->i_gid = dp->i_gid; 1180 #ifdef QUOTA 1181 ip->i_dquot = inoquota(ip); 1182 #endif 1183 iupdat(ip, &time, &time, 1); 1184 1185 /* 1186 * Bump link count in parent directory 1187 * to reflect work done below. Should 1188 * be done before reference is created 1189 * so reparation is possible if we crash. 1190 */ 1191 dp->i_nlink++; 1192 dp->i_flag |= ICHG; 1193 iupdat(dp, &time, &time, 1); 1194 1195 /* 1196 * Initialize directory with "." 1197 * and ".." from static template. 1198 */ 1199 dirtemplate = mastertemplate; 1200 dirtemplate.dot_ino = ip->i_number; 1201 dirtemplate.dotdot_ino = dp->i_number; 1202 u.u_error = rdwri(UIO_WRITE, ip, (caddr_t)&dirtemplate, 1203 sizeof (dirtemplate), (off_t)0, 1, (int *)0); 1204 if (u.u_error) { 1205 dp->i_nlink--; 1206 dp->i_flag |= ICHG; 1207 goto bad; 1208 } 1209 if (DIRBLKSIZ > ip->i_fs->fs_fsize) 1210 panic("mkdir: blksize"); /* XXX - should grow with bmap() */ 1211 else 1212 ip->i_size = DIRBLKSIZ; 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, ndp); 1219 dp = NULL; 1220 if (u.u_error) { 1221 ndp->ni_nameiop = LOOKUP | NOCACHE; 1222 ndp->ni_segflg = UIO_USERSPACE; 1223 ndp->ni_dirp = uap->name; 1224 dp = namei(ndp); 1225 if (dp) { 1226 dp->i_nlink--; 1227 dp->i_flag |= ICHG; 1228 } 1229 } 1230 bad: 1231 /* 1232 * No need to do an explicit itrunc here, 1233 * irele will do this for us because we set 1234 * the link count to 0. 1235 */ 1236 if (u.u_error) { 1237 ip->i_nlink = 0; 1238 ip->i_flag |= ICHG; 1239 } 1240 if (dp) 1241 iput(dp); 1242 iput(ip); 1243 } 1244 1245 /* 1246 * Rmdir system call. 1247 */ 1248 rmdir() 1249 { 1250 struct a { 1251 char *name; 1252 } *uap = (struct a *)u.u_ap; 1253 register struct inode *ip, *dp; 1254 register struct nameidata *ndp = &u.u_nd; 1255 1256 ndp->ni_nameiop = DELETE | LOCKPARENT; 1257 ndp->ni_segflg = UIO_USERSPACE; 1258 ndp->ni_dirp = uap->name; 1259 ip = namei(ndp); 1260 if (ip == NULL) 1261 return; 1262 dp = ndp->ni_pdir; 1263 /* 1264 * No rmdir "." please. 1265 */ 1266 if (dp == ip) { 1267 irele(dp); 1268 iput(ip); 1269 u.u_error = EINVAL; 1270 return; 1271 } 1272 if ((ip->i_mode&IFMT) != IFDIR) { 1273 u.u_error = ENOTDIR; 1274 goto out; 1275 } 1276 /* 1277 * Don't remove a mounted on directory. 1278 */ 1279 if (ip->i_dev != dp->i_dev) { 1280 u.u_error = EBUSY; 1281 goto out; 1282 } 1283 /* 1284 * Verify the directory is empty (and valid). 1285 * (Rmdir ".." won't be valid since 1286 * ".." will contain a reference to 1287 * the current directory and thus be 1288 * non-empty.) 1289 */ 1290 if (ip->i_nlink != 2 || !dirempty(ip, dp->i_number)) { 1291 u.u_error = ENOTEMPTY; 1292 goto out; 1293 } 1294 /* 1295 * Delete reference to directory before purging 1296 * inode. If we crash in between, the directory 1297 * will be reattached to lost+found, 1298 */ 1299 if (dirremove(ndp) == 0) 1300 goto out; 1301 dp->i_nlink--; 1302 dp->i_flag |= ICHG; 1303 cacheinval(dp); 1304 iput(dp); 1305 dp = NULL; 1306 /* 1307 * Truncate inode. The only stuff left 1308 * in the directory is "." and "..". The 1309 * "." reference is inconsequential since 1310 * we're quashing it. The ".." reference 1311 * has already been adjusted above. We've 1312 * removed the "." reference and the reference 1313 * in the parent directory, but there may be 1314 * other hard links so decrement by 2 and 1315 * worry about them later. 1316 */ 1317 ip->i_nlink -= 2; 1318 itrunc(ip, (u_long)0); 1319 cacheinval(ip); 1320 out: 1321 if (dp) 1322 iput(dp); 1323 iput(ip); 1324 } 1325 1326 struct file * 1327 getinode(fdes) 1328 int fdes; 1329 { 1330 struct file *fp; 1331 1332 if ((unsigned)fdes >= NOFILE || (fp = u.u_ofile[fdes]) == NULL) { 1333 u.u_error = EBADF; 1334 return ((struct file *)0); 1335 } 1336 if (fp->f_type != DTYPE_INODE) { 1337 u.u_error = EINVAL; 1338 return ((struct file *)0); 1339 } 1340 return (fp); 1341 } 1342 1343 /* 1344 * mode mask for creation of files 1345 */ 1346 umask() 1347 { 1348 register struct a { 1349 int mask; 1350 } *uap = (struct a *)u.u_ap; 1351 1352 u.u_r.r_val1 = u.u_cmask; 1353 u.u_cmask = uap->mask & 07777; 1354 } 1355