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