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