1 /* 2 * Copyright (c) 1982, 1986 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 * @(#)lfs_vnops.c 7.3 (Berkeley) 04/18/87 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 indx; 123 124 fp = falloc(); 125 if (fp == NULL) 126 return; 127 indx = u.u_r.r_val1; 128 ndp->ni_segflg = UIO_USERSPACE; 129 ndp->ni_dirp = fname; 130 if (mode&FCREAT) { 131 if (mode & FEXCL) 132 ndp->ni_nameiop = CREATE; 133 else 134 ndp->ni_nameiop = CREATE | FOLLOW; 135 ip = namei(ndp); 136 if (ip == NULL) { 137 if (u.u_error) 138 goto bad1; 139 ip = maknode(arg&07777&(~ISVTX), ndp); 140 if (ip == NULL) 141 goto bad1; 142 mode &= ~FTRUNC; 143 } else { 144 if (mode&FEXCL) { 145 u.u_error = EEXIST; 146 goto bad; 147 } 148 mode &= ~FCREAT; 149 } 150 } else { 151 ndp->ni_nameiop = LOOKUP | FOLLOW; 152 ip = namei(ndp); 153 if (ip == NULL) 154 goto bad1; 155 } 156 if ((ip->i_mode & IFMT) == IFSOCK) { 157 u.u_error = EOPNOTSUPP; 158 goto bad; 159 } 160 if ((mode&FCREAT) == 0) { 161 if (mode&FREAD) 162 if (access(ip, IREAD)) 163 goto bad; 164 if (mode&(FWRITE|FTRUNC)) { 165 if (access(ip, IWRITE)) 166 goto bad; 167 if ((ip->i_mode&IFMT) == IFDIR) { 168 u.u_error = EISDIR; 169 goto bad; 170 } 171 } 172 } 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 if (setjmp(&u.u_qsave)) { 181 if (u.u_error == 0) 182 u.u_error = EINTR; 183 u.u_ofile[indx] = NULL; 184 closef(fp); 185 return; 186 } 187 u.u_error = openi(ip, mode); 188 if (u.u_error == 0) 189 return; 190 ILOCK(ip); 191 bad: 192 iput(ip); 193 bad1: 194 u.u_ofile[indx] = NULL; 195 fp->f_count--; 196 } 197 198 /* 199 * Mknod system call 200 */ 201 mknod() 202 { 203 register struct inode *ip; 204 register struct a { 205 char *fname; 206 int fmode; 207 int dev; 208 } *uap = (struct a *)u.u_ap; 209 register struct nameidata *ndp = &u.u_nd; 210 211 if (!suser()) 212 return; 213 ndp->ni_nameiop = CREATE; 214 ndp->ni_segflg = UIO_USERSPACE; 215 ndp->ni_dirp = uap->fname; 216 ip = namei(ndp); 217 if (ip != NULL) { 218 u.u_error = EEXIST; 219 goto out; 220 } 221 if (u.u_error) 222 return; 223 ip = maknode(uap->fmode, ndp); 224 if (ip == NULL) 225 return; 226 switch (ip->i_mode & IFMT) { 227 228 case IFMT: /* used by badsect to flag bad sectors */ 229 case IFCHR: 230 case IFBLK: 231 if (uap->dev) { 232 /* 233 * Want to be able to use this to make badblock 234 * inodes, so don't truncate the dev number. 235 */ 236 ip->i_rdev = uap->dev; 237 ip->i_flag |= IACC|IUPD|ICHG; 238 } 239 } 240 241 out: 242 iput(ip); 243 } 244 245 /* 246 * link system call 247 */ 248 link() 249 { 250 register struct inode *ip, *xp; 251 register struct a { 252 char *target; 253 char *linkname; 254 } *uap = (struct a *)u.u_ap; 255 register struct nameidata *ndp = &u.u_nd; 256 257 ndp->ni_nameiop = LOOKUP | FOLLOW; 258 ndp->ni_segflg = UIO_USERSPACE; 259 ndp->ni_dirp = uap->target; 260 ip = namei(ndp); /* well, this routine is doomed anyhow */ 261 if (ip == NULL) 262 return; 263 if ((ip->i_mode&IFMT) == IFDIR && !suser()) { 264 iput(ip); 265 return; 266 } 267 ip->i_nlink++; 268 ip->i_flag |= ICHG; 269 iupdat(ip, &time, &time, 1); 270 IUNLOCK(ip); 271 ndp->ni_nameiop = CREATE; 272 ndp->ni_segflg = UIO_USERSPACE; 273 ndp->ni_dirp = (caddr_t)uap->linkname; 274 xp = namei(ndp); 275 if (xp != NULL) { 276 u.u_error = EEXIST; 277 iput(xp); 278 goto out; 279 } 280 if (u.u_error) 281 goto out; 282 if (ndp->ni_pdir->i_dev != ip->i_dev) { 283 iput(ndp->ni_pdir); 284 u.u_error = EXDEV; 285 goto out; 286 } 287 u.u_error = direnter(ip, ndp); 288 out: 289 if (u.u_error) { 290 ip->i_nlink--; 291 ip->i_flag |= ICHG; 292 } 293 irele(ip); 294 } 295 296 /* 297 * symlink -- make a symbolic link 298 */ 299 symlink() 300 { 301 register struct a { 302 char *target; 303 char *linkname; 304 } *uap = (struct a *)u.u_ap; 305 register struct inode *ip; 306 register char *tp; 307 register c, nc; 308 register struct nameidata *ndp = &u.u_nd; 309 310 tp = uap->target; 311 nc = 0; 312 while (c = fubyte(tp)) { 313 if (c < 0) { 314 u.u_error = EFAULT; 315 return; 316 } 317 tp++; 318 nc++; 319 } 320 ndp->ni_nameiop = CREATE; 321 ndp->ni_segflg = UIO_USERSPACE; 322 ndp->ni_dirp = uap->linkname; 323 ip = namei(ndp); 324 if (ip) { 325 iput(ip); 326 u.u_error = EEXIST; 327 return; 328 } 329 if (u.u_error) 330 return; 331 ip = maknode(IFLNK | 0777, ndp); 332 if (ip == NULL) 333 return; 334 u.u_error = rdwri(UIO_WRITE, ip, uap->target, nc, (off_t)0, 0, 335 (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, (off_t)0, 0, 521 &resid); 522 out: 523 iput(ip); 524 u.u_r.r_val1 = uap->count - resid; 525 } 526 527 /* 528 * Change mode of a file given path name. 529 */ 530 chmod() 531 { 532 struct inode *ip; 533 struct a { 534 char *fname; 535 int fmode; 536 } *uap = (struct a *)u.u_ap; 537 538 if ((ip = owner(uap->fname, FOLLOW)) == NULL) 539 return; 540 u.u_error = chmod1(ip, uap->fmode); 541 iput(ip); 542 } 543 544 /* 545 * Change mode of a file given a file descriptor. 546 */ 547 fchmod() 548 { 549 struct a { 550 int fd; 551 int fmode; 552 } *uap = (struct a *)u.u_ap; 553 register struct inode *ip; 554 register struct file *fp; 555 556 fp = getinode(uap->fd); 557 if (fp == NULL) 558 return; 559 ip = (struct inode *)fp->f_data; 560 if (u.u_uid != ip->i_uid && !suser()) 561 return; 562 ILOCK(ip); 563 u.u_error = chmod1(ip, uap->fmode); 564 IUNLOCK(ip); 565 } 566 567 /* 568 * Change the mode on a file. 569 * Inode must be locked before calling. 570 */ 571 chmod1(ip, mode) 572 register struct inode *ip; 573 register int mode; 574 { 575 576 if (ip->i_fs->fs_ronly) 577 return (EROFS); 578 ip->i_mode &= ~07777; 579 if (u.u_uid) { 580 if ((ip->i_mode & IFMT) != IFDIR) 581 mode &= ~ISVTX; 582 if (!groupmember(ip->i_gid)) 583 mode &= ~ISGID; 584 } 585 ip->i_mode |= mode&07777; 586 ip->i_flag |= ICHG; 587 if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0) 588 xrele(ip); 589 return (0); 590 } 591 592 /* 593 * Set ownership given a path name. 594 */ 595 chown() 596 { 597 struct inode *ip; 598 struct a { 599 char *fname; 600 int uid; 601 int gid; 602 } *uap = (struct a *)u.u_ap; 603 604 if ((ip = owner(uap->fname, NOFOLLOW)) == NULL) 605 return; 606 u.u_error = chown1(ip, uap->uid, uap->gid); 607 iput(ip); 608 } 609 610 /* 611 * Set ownership given a file descriptor. 612 */ 613 fchown() 614 { 615 struct a { 616 int fd; 617 int uid; 618 int gid; 619 } *uap = (struct a *)u.u_ap; 620 register struct inode *ip; 621 register struct file *fp; 622 623 fp = getinode(uap->fd); 624 if (fp == NULL) 625 return; 626 ip = (struct inode *)fp->f_data; 627 ILOCK(ip); 628 u.u_error = chown1(ip, uap->uid, uap->gid); 629 IUNLOCK(ip); 630 } 631 632 /* 633 * Perform chown operation on inode ip; 634 * inode must be locked prior to call. 635 */ 636 chown1(ip, uid, gid) 637 register struct inode *ip; 638 int uid, gid; 639 { 640 #ifdef QUOTA 641 register long change; 642 #endif 643 644 if (ip->i_fs->fs_ronly) 645 return (EROFS); 646 if (uid == -1) 647 uid = ip->i_uid; 648 if (gid == -1) 649 gid = ip->i_gid; 650 if (uid != ip->i_uid && !suser()) 651 return (u.u_error); 652 if (gid != ip->i_gid && !groupmember((gid_t)gid) && !suser()) 653 return (u.u_error); 654 #ifdef QUOTA 655 if (ip->i_uid == uid) /* this just speeds things a little */ 656 change = 0; 657 else 658 change = ip->i_blocks; 659 (void) chkdq(ip, -change, 1); 660 (void) chkiq(ip->i_dev, ip, ip->i_uid, 1); 661 dqrele(ip->i_dquot); 662 #endif 663 ip->i_uid = uid; 664 ip->i_gid = gid; 665 ip->i_flag |= ICHG; 666 if (u.u_ruid != 0) 667 ip->i_mode &= ~(ISUID|ISGID); 668 #ifdef QUOTA 669 ip->i_dquot = inoquota(ip); 670 (void) chkdq(ip, change, 1); 671 (void) chkiq(ip->i_dev, (struct inode *)NULL, (uid_t)uid, 1); 672 return (u.u_error); /* should == 0 ALWAYS !! */ 673 #else 674 return (0); 675 #endif 676 } 677 678 utimes() 679 { 680 register struct a { 681 char *fname; 682 struct timeval *tptr; 683 } *uap = (struct a *)u.u_ap; 684 register struct inode *ip; 685 struct timeval tv[2]; 686 687 if ((ip = owner(uap->fname, FOLLOW)) == NULL) 688 return; 689 if (ip->i_fs->fs_ronly) { 690 u.u_error = EROFS; 691 iput(ip); 692 return; 693 } 694 u.u_error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)); 695 if (u.u_error == 0) { 696 ip->i_flag |= IACC|IUPD|ICHG; 697 iupdat(ip, &tv[0], &tv[1], 0); 698 } 699 iput(ip); 700 } 701 702 /* 703 * Flush any pending I/O. 704 */ 705 sync() 706 { 707 708 update(); 709 } 710 711 /* 712 * Truncate a file given its path name. 713 */ 714 truncate() 715 { 716 struct a { 717 char *fname; 718 off_t length; 719 } *uap = (struct a *)u.u_ap; 720 struct inode *ip; 721 register struct nameidata *ndp = &u.u_nd; 722 723 ndp->ni_nameiop = LOOKUP | FOLLOW; 724 ndp->ni_segflg = UIO_USERSPACE; 725 ndp->ni_dirp = uap->fname; 726 ip = namei(ndp); 727 if (ip == NULL) 728 return; 729 if (access(ip, IWRITE)) 730 goto bad; 731 if ((ip->i_mode&IFMT) == IFDIR) { 732 u.u_error = EISDIR; 733 goto bad; 734 } 735 itrunc(ip, (u_long)uap->length); 736 bad: 737 iput(ip); 738 } 739 740 /* 741 * Truncate a file given a file descriptor. 742 */ 743 ftruncate() 744 { 745 struct a { 746 int fd; 747 off_t length; 748 } *uap = (struct a *)u.u_ap; 749 struct inode *ip; 750 struct file *fp; 751 752 fp = getinode(uap->fd); 753 if (fp == NULL) 754 return; 755 if ((fp->f_flag&FWRITE) == 0) { 756 u.u_error = EINVAL; 757 return; 758 } 759 ip = (struct inode *)fp->f_data; 760 ILOCK(ip); 761 itrunc(ip, (u_long)uap->length); 762 IUNLOCK(ip); 763 } 764 765 /* 766 * Synch an open file. 767 */ 768 fsync() 769 { 770 struct a { 771 int fd; 772 } *uap = (struct a *)u.u_ap; 773 struct inode *ip; 774 struct file *fp; 775 776 fp = getinode(uap->fd); 777 if (fp == NULL) 778 return; 779 ip = (struct inode *)fp->f_data; 780 ILOCK(ip); 781 if (fp->f_flag&FWRITE) 782 ip->i_flag |= ICHG; 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 (it may be truncated by 803 * a concurrent `trunc' or `open' for creation). 804 * 2) Link source to destination. If destination already exists, 805 * delete it first. 806 * 3) Unlink source reference to inode if still around. If a 807 * directory was moved and the parent of the destination 808 * is different from the source, patch the ".." entry in the 809 * directory. 810 * 811 * Source and destination must either both be directories, or both 812 * not be directories. If target is a directory, it must be empty. 813 */ 814 rename() 815 { 816 struct a { 817 char *from; 818 char *to; 819 } *uap = (struct a *)u.u_ap; 820 register struct inode *ip, *xp, *dp; 821 struct dirtemplate dirbuf; 822 int doingdirectory = 0, oldparent = 0, newparent = 0; 823 register struct nameidata *ndp = &u.u_nd; 824 int error = 0; 825 826 ndp->ni_nameiop = DELETE | LOCKPARENT; 827 ndp->ni_segflg = UIO_USERSPACE; 828 ndp->ni_dirp = uap->from; 829 ip = namei(ndp); 830 if (ip == NULL) 831 return; 832 dp = ndp->ni_pdir; 833 if ((ip->i_mode&IFMT) == IFDIR) { 834 register struct direct *d; 835 836 d = &ndp->ni_dent; 837 /* 838 * Avoid ".", "..", and aliases of "." for obvious reasons. 839 */ 840 if ((d->d_namlen == 1 && d->d_name[0] == '.') || 841 (d->d_namlen == 2 && bcmp(d->d_name, "..", 2) == 0) || 842 (dp == ip) || (ip->i_flag & IRENAME)) { 843 iput(dp); 844 if (dp == ip) 845 irele(ip); 846 else 847 iput(ip); 848 u.u_error = EINVAL; 849 return; 850 } 851 ip->i_flag |= IRENAME; 852 oldparent = dp->i_number; 853 doingdirectory++; 854 } 855 iput(dp); 856 857 /* 858 * 1) Bump link count while we're moving stuff 859 * around. If we crash somewhere before 860 * completing our work, the link count 861 * may be wrong, but correctable. 862 */ 863 ip->i_nlink++; 864 ip->i_flag |= ICHG; 865 iupdat(ip, &time, &time, 1); 866 IUNLOCK(ip); 867 868 /* 869 * When the target exists, both the directory 870 * and target inodes are returned locked. 871 */ 872 ndp->ni_nameiop = CREATE | LOCKPARENT | NOCACHE; 873 ndp->ni_dirp = (caddr_t)uap->to; 874 xp = namei(ndp); 875 if (u.u_error) { 876 error = u.u_error; 877 goto out; 878 } 879 dp = ndp->ni_pdir; 880 /* 881 * If ".." must be changed (ie the directory gets a new 882 * parent) then the source directory must not be in the 883 * directory heirarchy above the target, as this would 884 * orphan everything below the source directory. Also 885 * the user must have write permission in the source so 886 * as to be able to change "..". We must repeat the call 887 * to namei, as the parent directory is unlocked by the 888 * call to checkpath(). 889 */ 890 if (oldparent != dp->i_number) 891 newparent = dp->i_number; 892 if (doingdirectory && newparent) { 893 if (access(ip, IWRITE)) 894 goto bad; 895 do { 896 dp = ndp->ni_pdir; 897 if (xp != NULL) 898 iput(xp); 899 u.u_error = checkpath(ip, dp); 900 if (u.u_error) 901 goto out; 902 xp = namei(ndp); 903 if (u.u_error) { 904 error = u.u_error; 905 goto out; 906 } 907 } while (dp != ndp->ni_pdir); 908 } 909 /* 910 * 2) If target doesn't exist, link the target 911 * to the source and unlink the source. 912 * Otherwise, rewrite the target directory 913 * entry to reference the source inode and 914 * expunge the original entry's existence. 915 */ 916 if (xp == NULL) { 917 if (dp->i_dev != ip->i_dev) { 918 error = EXDEV; 919 goto bad; 920 } 921 /* 922 * Account for ".." in new directory. 923 * When source and destination have the same 924 * parent we don't fool with the link count. 925 */ 926 if (doingdirectory && newparent) { 927 dp->i_nlink++; 928 dp->i_flag |= ICHG; 929 iupdat(dp, &time, &time, 1); 930 } 931 error = direnter(ip, ndp); 932 if (error) 933 goto out; 934 } else { 935 if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev) { 936 error = EXDEV; 937 goto bad; 938 } 939 /* 940 * Short circuit rename(foo, foo). 941 */ 942 if (xp->i_number == ip->i_number) 943 goto bad; 944 /* 945 * If the parent directory is "sticky", then the user must 946 * own the parent directory, or the destination of the rename, 947 * otherwise the destination may not be changed (except by 948 * root). This implements append-only directories. 949 */ 950 if ((dp->i_mode & ISVTX) && u.u_uid != 0 && 951 u.u_uid != dp->i_uid && xp->i_uid != u.u_uid) { 952 error = EPERM; 953 goto bad; 954 } 955 /* 956 * Target must be empty if a directory 957 * and have no links to it. 958 * Also, insure source and target are 959 * compatible (both directories, or both 960 * not directories). 961 */ 962 if ((xp->i_mode&IFMT) == IFDIR) { 963 if (!dirempty(xp, dp->i_number) || xp->i_nlink > 2) { 964 error = ENOTEMPTY; 965 goto bad; 966 } 967 if (!doingdirectory) { 968 error = ENOTDIR; 969 goto bad; 970 } 971 cacheinval(dp); 972 } else if (doingdirectory) { 973 error = EISDIR; 974 goto bad; 975 } 976 dirrewrite(dp, ip, ndp); 977 if (u.u_error) { 978 error = u.u_error; 979 goto bad1; 980 } 981 /* 982 * Adjust the link count of the target to 983 * reflect the dirrewrite above. If this is 984 * a directory it is empty and there are 985 * no links to it, so we can squash the inode and 986 * any space associated with it. We disallowed 987 * renaming over top of a directory with links to 988 * it above, as the remaining link would point to 989 * a directory without "." or ".." entries. 990 */ 991 xp->i_nlink--; 992 if (doingdirectory) { 993 if (--xp->i_nlink != 0) 994 panic("rename: linked directory"); 995 itrunc(xp, (u_long)0); 996 } 997 xp->i_flag |= ICHG; 998 iput(xp); 999 xp = NULL; 1000 } 1001 1002 /* 1003 * 3) Unlink the source. 1004 */ 1005 ndp->ni_nameiop = DELETE | LOCKPARENT; 1006 ndp->ni_segflg = UIO_USERSPACE; 1007 ndp->ni_dirp = uap->from; 1008 xp = namei(ndp); 1009 if (xp != NULL) 1010 dp = ndp->ni_pdir; 1011 else 1012 dp = NULL; 1013 /* 1014 * Insure that the directory entry still exists and has not 1015 * changed while the new name has been entered. If the source is 1016 * a file then the entry may have been unlinked or renamed. In 1017 * either case there is no further work to be done. If the source 1018 * is a directory then it cannot have been rmdir'ed; its link 1019 * count of three would cause a rmdir to fail with ENOTEMPTY. 1020 * The IRENAME flag insures that it cannot be moved by another 1021 * rename. 1022 */ 1023 if (xp != ip) { 1024 if (doingdirectory) 1025 panic("rename: lost dir entry"); 1026 } else { 1027 /* 1028 * If the source is a directory with a 1029 * new parent, the link count of the old 1030 * parent directory must be decremented 1031 * and ".." set to point to the new parent. 1032 */ 1033 if (doingdirectory && newparent) { 1034 dp->i_nlink--; 1035 dp->i_flag |= ICHG; 1036 error = rdwri(UIO_READ, xp, (caddr_t)&dirbuf, 1037 sizeof (struct dirtemplate), (off_t)0, 1, 1038 (int *)0); 1039 if (error == 0) { 1040 if (dirbuf.dotdot_namlen != 2 || 1041 dirbuf.dotdot_name[0] != '.' || 1042 dirbuf.dotdot_name[1] != '.') { 1043 printf("rename: mangled dir\n"); 1044 } else { 1045 dirbuf.dotdot_ino = newparent; 1046 (void) rdwri(UIO_WRITE, xp, 1047 (caddr_t)&dirbuf, 1048 sizeof (struct dirtemplate), 1049 (off_t)0, 1, (int *)0); 1050 cacheinval(dp); 1051 } 1052 } 1053 } 1054 if (dirremove(ndp)) { 1055 xp->i_nlink--; 1056 xp->i_flag |= ICHG; 1057 } 1058 xp->i_flag &= ~IRENAME; 1059 if (error == 0) /* XXX conservative */ 1060 error = u.u_error; 1061 } 1062 if (dp) 1063 iput(dp); 1064 if (xp) 1065 iput(xp); 1066 irele(ip); 1067 if (error) 1068 u.u_error = error; 1069 return; 1070 1071 bad: 1072 iput(dp); 1073 bad1: 1074 if (xp) 1075 iput(xp); 1076 out: 1077 ip->i_nlink--; 1078 ip->i_flag |= ICHG; 1079 irele(ip); 1080 if (error) 1081 u.u_error = error; 1082 } 1083 1084 /* 1085 * Make a new file. 1086 */ 1087 struct inode * 1088 maknode(mode, ndp) 1089 int mode; 1090 register struct nameidata *ndp; 1091 { 1092 register struct inode *ip; 1093 register struct inode *pdir = ndp->ni_pdir; 1094 ino_t ipref; 1095 1096 if ((mode & IFMT) == IFDIR) 1097 ipref = dirpref(pdir->i_fs); 1098 else 1099 ipref = pdir->i_number; 1100 ip = ialloc(pdir, ipref, mode); 1101 if (ip == NULL) { 1102 iput(pdir); 1103 return (NULL); 1104 } 1105 #ifdef QUOTA 1106 if (ip->i_dquot != NODQUOT) 1107 panic("maknode: dquot"); 1108 #endif 1109 ip->i_flag |= IACC|IUPD|ICHG; 1110 if ((mode & IFMT) == 0) 1111 mode |= IFREG; 1112 ip->i_mode = mode & ~u.u_cmask; 1113 ip->i_nlink = 1; 1114 ip->i_uid = u.u_uid; 1115 ip->i_gid = pdir->i_gid; 1116 if (ip->i_mode & ISGID && !groupmember(ip->i_gid) && !suser()) 1117 ip->i_mode &= ~ISGID; 1118 #ifdef QUOTA 1119 ip->i_dquot = inoquota(ip); 1120 #endif 1121 1122 /* 1123 * Make sure inode goes to disk before directory entry. 1124 */ 1125 iupdat(ip, &time, &time, 1); 1126 u.u_error = direnter(ip, ndp); 1127 if (u.u_error) { 1128 /* 1129 * Write error occurred trying to update directory 1130 * so must deallocate the inode. 1131 */ 1132 ip->i_nlink = 0; 1133 ip->i_flag |= ICHG; 1134 iput(ip); 1135 return (NULL); 1136 } 1137 return (ip); 1138 } 1139 1140 /* 1141 * A virgin directory (no blushing please). 1142 */ 1143 struct dirtemplate mastertemplate = { 1144 0, 12, 1, ".", 1145 0, DIRBLKSIZ - 12, 2, ".." 1146 }; 1147 1148 /* 1149 * Mkdir system call 1150 */ 1151 mkdir() 1152 { 1153 struct a { 1154 char *name; 1155 int dmode; 1156 } *uap = (struct a *)u.u_ap; 1157 register struct inode *ip, *dp; 1158 struct dirtemplate dirtemplate; 1159 register struct nameidata *ndp = &u.u_nd; 1160 1161 ndp->ni_nameiop = CREATE; 1162 ndp->ni_segflg = UIO_USERSPACE; 1163 ndp->ni_dirp = uap->name; 1164 ip = namei(ndp); 1165 if (u.u_error) 1166 return; 1167 if (ip != NULL) { 1168 iput(ip); 1169 u.u_error = EEXIST; 1170 return; 1171 } 1172 dp = ndp->ni_pdir; 1173 uap->dmode &= 0777; 1174 uap->dmode |= IFDIR; 1175 /* 1176 * Must simulate part of maknode here 1177 * in order to acquire the inode, but 1178 * not have it entered in the parent 1179 * directory. The entry is made later 1180 * after writing "." and ".." entries out. 1181 */ 1182 ip = ialloc(dp, dirpref(dp->i_fs), uap->dmode); 1183 if (ip == NULL) { 1184 iput(dp); 1185 return; 1186 } 1187 #ifdef QUOTA 1188 if (ip->i_dquot != NODQUOT) 1189 panic("mkdir: dquot"); 1190 #endif 1191 ip->i_flag |= IACC|IUPD|ICHG; 1192 ip->i_mode = uap->dmode & ~u.u_cmask; 1193 ip->i_nlink = 2; 1194 ip->i_uid = u.u_uid; 1195 ip->i_gid = dp->i_gid; 1196 #ifdef QUOTA 1197 ip->i_dquot = inoquota(ip); 1198 #endif 1199 iupdat(ip, &time, &time, 1); 1200 1201 /* 1202 * Bump link count in parent directory 1203 * to reflect work done below. Should 1204 * be done before reference is created 1205 * so reparation is possible if we crash. 1206 */ 1207 dp->i_nlink++; 1208 dp->i_flag |= ICHG; 1209 iupdat(dp, &time, &time, 1); 1210 1211 /* 1212 * Initialize directory with "." 1213 * and ".." from static template. 1214 */ 1215 dirtemplate = mastertemplate; 1216 dirtemplate.dot_ino = ip->i_number; 1217 dirtemplate.dotdot_ino = dp->i_number; 1218 u.u_error = rdwri(UIO_WRITE, ip, (caddr_t)&dirtemplate, 1219 sizeof (dirtemplate), (off_t)0, 1, (int *)0); 1220 if (u.u_error) { 1221 dp->i_nlink--; 1222 dp->i_flag |= ICHG; 1223 goto bad; 1224 } 1225 if (DIRBLKSIZ > ip->i_fs->fs_fsize) 1226 panic("mkdir: blksize"); /* XXX - should grow with bmap() */ 1227 else 1228 ip->i_size = DIRBLKSIZ; 1229 /* 1230 * Directory all set up, now 1231 * install the entry for it in 1232 * the parent directory. 1233 */ 1234 u.u_error = direnter(ip, ndp); 1235 dp = NULL; 1236 if (u.u_error) { 1237 ndp->ni_nameiop = LOOKUP | NOCACHE; 1238 ndp->ni_segflg = UIO_USERSPACE; 1239 ndp->ni_dirp = uap->name; 1240 dp = namei(ndp); 1241 if (dp) { 1242 dp->i_nlink--; 1243 dp->i_flag |= ICHG; 1244 } 1245 } 1246 bad: 1247 /* 1248 * No need to do an explicit itrunc here, 1249 * irele will do this for us because we set 1250 * the link count to 0. 1251 */ 1252 if (u.u_error) { 1253 ip->i_nlink = 0; 1254 ip->i_flag |= ICHG; 1255 } 1256 if (dp) 1257 iput(dp); 1258 iput(ip); 1259 } 1260 1261 /* 1262 * Rmdir system call. 1263 */ 1264 rmdir() 1265 { 1266 struct a { 1267 char *name; 1268 } *uap = (struct a *)u.u_ap; 1269 register struct inode *ip, *dp; 1270 register struct nameidata *ndp = &u.u_nd; 1271 1272 ndp->ni_nameiop = DELETE | LOCKPARENT; 1273 ndp->ni_segflg = UIO_USERSPACE; 1274 ndp->ni_dirp = uap->name; 1275 ip = namei(ndp); 1276 if (ip == NULL) 1277 return; 1278 dp = ndp->ni_pdir; 1279 /* 1280 * No rmdir "." please. 1281 */ 1282 if (dp == ip) { 1283 irele(dp); 1284 iput(ip); 1285 u.u_error = EINVAL; 1286 return; 1287 } 1288 if ((ip->i_mode&IFMT) != IFDIR) { 1289 u.u_error = ENOTDIR; 1290 goto out; 1291 } 1292 /* 1293 * Don't remove a mounted on directory. 1294 */ 1295 if (ip->i_dev != dp->i_dev) { 1296 u.u_error = EBUSY; 1297 goto out; 1298 } 1299 /* 1300 * Verify the directory is empty (and valid). 1301 * (Rmdir ".." won't be valid since 1302 * ".." will contain a reference to 1303 * the current directory and thus be 1304 * non-empty.) 1305 */ 1306 if (ip->i_nlink != 2 || !dirempty(ip, dp->i_number)) { 1307 u.u_error = ENOTEMPTY; 1308 goto out; 1309 } 1310 /* 1311 * Delete reference to directory before purging 1312 * inode. If we crash in between, the directory 1313 * will be reattached to lost+found, 1314 */ 1315 if (dirremove(ndp) == 0) 1316 goto out; 1317 dp->i_nlink--; 1318 dp->i_flag |= ICHG; 1319 cacheinval(dp); 1320 iput(dp); 1321 dp = NULL; 1322 /* 1323 * Truncate inode. The only stuff left 1324 * in the directory is "." and "..". The 1325 * "." reference is inconsequential since 1326 * we're quashing it. The ".." reference 1327 * has already been adjusted above. We've 1328 * removed the "." reference and the reference 1329 * in the parent directory, but there may be 1330 * other hard links so decrement by 2 and 1331 * worry about them later. 1332 */ 1333 ip->i_nlink -= 2; 1334 itrunc(ip, (u_long)0); 1335 cacheinval(ip); 1336 out: 1337 if (dp) 1338 iput(dp); 1339 iput(ip); 1340 } 1341 1342 struct file * 1343 getinode(fdes) 1344 int fdes; 1345 { 1346 struct file *fp; 1347 1348 if ((unsigned)fdes >= NOFILE || (fp = u.u_ofile[fdes]) == NULL) { 1349 u.u_error = EBADF; 1350 return ((struct file *)0); 1351 } 1352 if (fp->f_type != DTYPE_INODE) { 1353 u.u_error = EINVAL; 1354 return ((struct file *)0); 1355 } 1356 return (fp); 1357 } 1358 1359 /* 1360 * mode mask for creation of files 1361 */ 1362 umask() 1363 { 1364 register struct a { 1365 int mask; 1366 } *uap = (struct a *)u.u_ap; 1367 1368 u.u_r.r_val1 = u.u_cmask; 1369 u.u_cmask = uap->mask & 07777; 1370 } 1371