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: * @(#)ufs_syscalls.c 7.1 (Berkeley) 6/5/86 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: syncip(ip); 782: IUNLOCK(ip); 783: } 784: 785: /* 786: * Rename system call. 787: * rename("foo", "bar"); 788: * is essentially 789: * unlink("bar"); 790: * link("foo", "bar"); 791: * unlink("foo"); 792: * but ``atomically''. Can't do full commit without saving state in the 793: * inode on disk which isn't feasible at this time. Best we can do is 794: * always guarantee the target exists. 795: * 796: * Basic algorithm is: 797: * 798: * 1) Bump link count on source while we're linking it to the 799: * target. This also insure the inode won't be deleted out 800: * from underneath us while we work (it may be truncated by 801: * a concurrent `trunc' or `open' for creation). 802: * 2) Link source to destination. If destination already exists, 803: * delete it first. 804: * 3) Unlink source reference to inode if still around. If a 805: * directory was moved and the parent of the destination 806: * is different from the source, patch the ".." entry in the 807: * directory. 808: * 809: * Source and destination must either both be directories, or both 810: * not be directories. If target is a directory, it must be empty. 811: */ 812: rename() 813: { 814: struct a { 815: char *from; 816: char *to; 817: } *uap = (struct a *)u.u_ap; 818: register struct inode *ip, *xp, *dp; 819: struct dirtemplate dirbuf; 820: int doingdirectory = 0, oldparent = 0, newparent = 0; 821: register struct nameidata *ndp = &u.u_nd; 822: int error = 0; 823: 824: ndp->ni_nameiop = DELETE | LOCKPARENT; 825: ndp->ni_segflg = UIO_USERSPACE; 826: ndp->ni_dirp = uap->from; 827: ip = namei(ndp); 828: if (ip == NULL) 829: return; 830: dp = ndp->ni_pdir; 831: if ((ip->i_mode&IFMT) == IFDIR) { 832: register struct direct *d; 833: 834: d = &ndp->ni_dent; 835: /* 836: * Avoid ".", "..", and aliases of "." for obvious reasons. 837: */ 838: if ((d->d_namlen == 1 && d->d_name[0] == '.') || 839: (d->d_namlen == 2 && bcmp(d->d_name, "..", 2) == 0) || 840: (dp == ip) || (ip->i_flag & IRENAME)) { 841: iput(dp); 842: if (dp == ip) 843: irele(ip); 844: else 845: iput(ip); 846: u.u_error = EINVAL; 847: return; 848: } 849: ip->i_flag |= IRENAME; 850: oldparent = dp->i_number; 851: doingdirectory++; 852: } 853: iput(dp); 854: 855: /* 856: * 1) Bump link count while we're moving stuff 857: * around. If we crash somewhere before 858: * completing our work, the link count 859: * may be wrong, but correctable. 860: */ 861: ip->i_nlink++; 862: ip->i_flag |= ICHG; 863: iupdat(ip, &time, &time, 1); 864: IUNLOCK(ip); 865: 866: /* 867: * When the target exists, both the directory 868: * and target inodes are returned locked. 869: */ 870: ndp->ni_nameiop = CREATE | LOCKPARENT | NOCACHE; 871: ndp->ni_dirp = (caddr_t)uap->to; 872: xp = namei(ndp); 873: if (u.u_error) { 874: error = u.u_error; 875: goto out; 876: } 877: dp = ndp->ni_pdir; 878: /* 879: * If ".." must be changed (ie the directory gets a new 880: * parent) then the source directory must not be in the 881: * directory heirarchy above the target, as this would 882: * orphan everything below the source directory. Also 883: * the user must have write permission in the source so 884: * as to be able to change "..". We must repeat the call 885: * to namei, as the parent directory is unlocked by the 886: * call to checkpath(). 887: */ 888: if (oldparent != dp->i_number) 889: newparent = dp->i_number; 890: if (doingdirectory && newparent) { 891: if (access(ip, IWRITE)) 892: goto bad; 893: do { 894: dp = ndp->ni_pdir; 895: if (xp != NULL) 896: iput(xp); 897: u.u_error = checkpath(ip, dp); 898: if (u.u_error) 899: goto out; 900: xp = namei(ndp); 901: if (u.u_error) { 902: error = u.u_error; 903: goto out; 904: } 905: } while (dp != ndp->ni_pdir); 906: } 907: /* 908: * 2) If target doesn't exist, link the target 909: * to the source and unlink the source. 910: * Otherwise, rewrite the target directory 911: * entry to reference the source inode and 912: * expunge the original entry's existence. 913: */ 914: if (xp == NULL) { 915: if (dp->i_dev != ip->i_dev) { 916: error = EXDEV; 917: goto bad; 918: } 919: /* 920: * Account for ".." in new directory. 921: * When source and destination have the same 922: * parent we don't fool with the link count. 923: */ 924: if (doingdirectory && newparent) { 925: dp->i_nlink++; 926: dp->i_flag |= ICHG; 927: iupdat(dp, &time, &time, 1); 928: } 929: error = direnter(ip, ndp); 930: if (error) 931: goto out; 932: } else { 933: if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev) { 934: error = EXDEV; 935: goto bad; 936: } 937: /* 938: * Short circuit rename(foo, foo). 939: */ 940: if (xp->i_number == ip->i_number) 941: goto bad; 942: /* 943: * If the parent directory is "sticky", then the user must 944: * own the parent directory, or the destination of the rename, 945: * otherwise the destination may not be changed (except by 946: * root). This implements append-only directories. 947: */ 948: if ((dp->i_mode & ISVTX) && u.u_uid != 0 && 949: u.u_uid != dp->i_uid && xp->i_uid != u.u_uid) { 950: error = EPERM; 951: goto bad; 952: } 953: /* 954: * Target must be empty if a directory 955: * and have no links to it. 956: * Also, insure source and target are 957: * compatible (both directories, or both 958: * not directories). 959: */ 960: if ((xp->i_mode&IFMT) == IFDIR) { 961: if (!dirempty(xp, dp->i_number) || xp->i_nlink > 2) { 962: error = ENOTEMPTY; 963: goto bad; 964: } 965: if (!doingdirectory) { 966: error = ENOTDIR; 967: goto bad; 968: } 969: cacheinval(dp); 970: } else if (doingdirectory) { 971: error = EISDIR; 972: goto bad; 973: } 974: dirrewrite(dp, ip, ndp); 975: if (u.u_error) { 976: error = u.u_error; 977: goto bad1; 978: } 979: /* 980: * Adjust the link count of the target to 981: * reflect the dirrewrite above. If this is 982: * a directory it is empty and there are 983: * no links to it, so we can squash the inode and 984: * any space associated with it. We disallowed 985: * renaming over top of a directory with links to 986: * it above, as the remaining link would point to 987: * a directory without "." or ".." entries. 988: */ 989: xp->i_nlink--; 990: if (doingdirectory) { 991: if (--xp->i_nlink != 0) 992: panic("rename: linked directory"); 993: itrunc(xp, (u_long)0); 994: } 995: xp->i_flag |= ICHG; 996: iput(xp); 997: xp = NULL; 998: } 999: 1000: /* 1001: * 3) Unlink the source. 1002: */ 1003: ndp->ni_nameiop = DELETE | LOCKPARENT; 1004: ndp->ni_segflg = UIO_USERSPACE; 1005: ndp->ni_dirp = uap->from; 1006: xp = namei(ndp); 1007: if (xp != NULL) 1008: dp = ndp->ni_pdir; 1009: else 1010: dp = NULL; 1011: /* 1012: * Insure that the directory entry still exists and has not 1013: * changed while the new name has been entered. If the source is 1014: * a file then the entry may have been unlinked or renamed. In 1015: * either case there is no further work to be done. If the source 1016: * is a directory then it cannot have been rmdir'ed; its link 1017: * count of three would cause a rmdir to fail with ENOTEMPTY. 1018: * The IRENAME flag insures that it cannot be moved by another 1019: * rename. 1020: */ 1021: if (xp != ip) { 1022: if (doingdirectory) 1023: panic("rename: lost dir entry"); 1024: } else { 1025: /* 1026: * If the source is a directory with a 1027: * new parent, the link count of the old 1028: * parent directory must be decremented 1029: * and ".." set to point to the new parent. 1030: */ 1031: if (doingdirectory && newparent) { 1032: dp->i_nlink--; 1033: dp->i_flag |= ICHG; 1034: error = rdwri(UIO_READ, xp, (caddr_t)&dirbuf, 1035: sizeof (struct dirtemplate), (off_t)0, 1, 1036: (int *)0); 1037: if (error == 0) { 1038: if (dirbuf.dotdot_namlen != 2 || 1039: dirbuf.dotdot_name[0] != '.' || 1040: dirbuf.dotdot_name[1] != '.') { 1041: printf("rename: mangled dir\n"); 1042: } else { 1043: dirbuf.dotdot_ino = newparent; 1044: (void) rdwri(UIO_WRITE, xp, 1045: (caddr_t)&dirbuf, 1046: sizeof (struct dirtemplate), 1047: (off_t)0, 1, (int *)0); 1048: cacheinval(dp); 1049: } 1050: } 1051: } 1052: if (dirremove(ndp)) { 1053: xp->i_nlink--; 1054: xp->i_flag |= ICHG; 1055: } 1056: xp->i_flag &= ~IRENAME; 1057: if (error == 0) /* XXX conservative */ 1058: error = u.u_error; 1059: } 1060: if (dp) 1061: iput(dp); 1062: if (xp) 1063: iput(xp); 1064: irele(ip); 1065: if (error) 1066: u.u_error = error; 1067: return; 1068: 1069: bad: 1070: iput(dp); 1071: bad1: 1072: if (xp) 1073: iput(xp); 1074: out: 1075: ip->i_nlink--; 1076: ip->i_flag |= ICHG; 1077: irele(ip); 1078: if (error) 1079: u.u_error = error; 1080: } 1081: 1082: /* 1083: * Make a new file. 1084: */ 1085: struct inode * 1086: maknode(mode, ndp) 1087: int mode; 1088: register struct nameidata *ndp; 1089: { 1090: register struct inode *ip; 1091: register struct inode *pdir = ndp->ni_pdir; 1092: ino_t ipref; 1093: 1094: if ((mode & IFMT) == IFDIR) 1095: ipref = dirpref(pdir->i_fs); 1096: else 1097: ipref = pdir->i_number; 1098: ip = ialloc(pdir, ipref, mode); 1099: if (ip == NULL) { 1100: iput(pdir); 1101: return (NULL); 1102: } 1103: #ifdef QUOTA 1104: if (ip->i_dquot != NODQUOT) 1105: panic("maknode: dquot"); 1106: #endif 1107: ip->i_flag |= IACC|IUPD|ICHG; 1108: if ((mode & IFMT) == 0) 1109: mode |= IFREG; 1110: ip->i_mode = mode & ~u.u_cmask; 1111: ip->i_nlink = 1; 1112: ip->i_uid = u.u_uid; 1113: ip->i_gid = pdir->i_gid; 1114: if (ip->i_mode & ISGID && !groupmember(ip->i_gid)) 1115: ip->i_mode &= ~ISGID; 1116: #ifdef QUOTA 1117: ip->i_dquot = inoquota(ip); 1118: #endif 1119: 1120: /* 1121: * Make sure inode goes to disk before directory entry. 1122: */ 1123: iupdat(ip, &time, &time, 1); 1124: u.u_error = direnter(ip, ndp); 1125: if (u.u_error) { 1126: /* 1127: * Write error occurred trying to update directory 1128: * so must deallocate the inode. 1129: */ 1130: ip->i_nlink = 0; 1131: ip->i_flag |= ICHG; 1132: iput(ip); 1133: return (NULL); 1134: } 1135: return (ip); 1136: } 1137: 1138: /* 1139: * A virgin directory (no blushing please). 1140: */ 1141: struct dirtemplate mastertemplate = { 1142: 0, 12, 1, ".", 1143: 0, DIRBLKSIZ - 12, 2, ".." 1144: }; 1145: 1146: /* 1147: * Mkdir system call 1148: */ 1149: mkdir() 1150: { 1151: struct a { 1152: char *name; 1153: int dmode; 1154: } *uap = (struct a *)u.u_ap; 1155: register struct inode *ip, *dp; 1156: struct dirtemplate dirtemplate; 1157: register struct nameidata *ndp = &u.u_nd; 1158: 1159: ndp->ni_nameiop = CREATE; 1160: ndp->ni_segflg = UIO_USERSPACE; 1161: ndp->ni_dirp = uap->name; 1162: ip = namei(ndp); 1163: if (u.u_error) 1164: return; 1165: if (ip != NULL) { 1166: iput(ip); 1167: u.u_error = EEXIST; 1168: return; 1169: } 1170: dp = ndp->ni_pdir; 1171: uap->dmode &= 0777; 1172: uap->dmode |= IFDIR; 1173: /* 1174: * Must simulate part of maknode here 1175: * in order to acquire the inode, but 1176: * not have it entered in the parent 1177: * directory. The entry is made later 1178: * after writing "." and ".." entries out. 1179: */ 1180: ip = ialloc(dp, dirpref(dp->i_fs), uap->dmode); 1181: if (ip == NULL) { 1182: iput(dp); 1183: return; 1184: } 1185: #ifdef QUOTA 1186: if (ip->i_dquot != NODQUOT) 1187: panic("mkdir: dquot"); 1188: #endif 1189: ip->i_flag |= IACC|IUPD|ICHG; 1190: ip->i_mode = uap->dmode & ~u.u_cmask; 1191: ip->i_nlink = 2; 1192: ip->i_uid = u.u_uid; 1193: ip->i_gid = dp->i_gid; 1194: #ifdef QUOTA 1195: ip->i_dquot = inoquota(ip); 1196: #endif 1197: iupdat(ip, &time, &time, 1); 1198: 1199: /* 1200: * Bump link count in parent directory 1201: * to reflect work done below. Should 1202: * be done before reference is created 1203: * so reparation is possible if we crash. 1204: */ 1205: dp->i_nlink++; 1206: dp->i_flag |= ICHG; 1207: iupdat(dp, &time, &time, 1); 1208: 1209: /* 1210: * Initialize directory with "." 1211: * and ".." from static template. 1212: */ 1213: dirtemplate = mastertemplate; 1214: dirtemplate.dot_ino = ip->i_number; 1215: dirtemplate.dotdot_ino = dp->i_number; 1216: u.u_error = rdwri(UIO_WRITE, ip, (caddr_t)&dirtemplate, 1217: sizeof (dirtemplate), (off_t)0, 1, (int *)0); 1218: if (u.u_error) { 1219: dp->i_nlink--; 1220: dp->i_flag |= ICHG; 1221: goto bad; 1222: } 1223: if (DIRBLKSIZ > ip->i_fs->fs_fsize) 1224: panic("mkdir: blksize"); /* XXX - should grow with bmap() */ 1225: else 1226: ip->i_size = DIRBLKSIZ; 1227: /* 1228: * Directory all set up, now 1229: * install the entry for it in 1230: * the parent directory. 1231: */ 1232: u.u_error = direnter(ip, ndp); 1233: dp = NULL; 1234: if (u.u_error) { 1235: ndp->ni_nameiop = LOOKUP | NOCACHE; 1236: ndp->ni_segflg = UIO_USERSPACE; 1237: ndp->ni_dirp = uap->name; 1238: dp = namei(ndp); 1239: if (dp) { 1240: dp->i_nlink--; 1241: dp->i_flag |= ICHG; 1242: } 1243: } 1244: bad: 1245: /* 1246: * No need to do an explicit itrunc here, 1247: * irele will do this for us because we set 1248: * the link count to 0. 1249: */ 1250: if (u.u_error) { 1251: ip->i_nlink = 0; 1252: ip->i_flag |= ICHG; 1253: } 1254: if (dp) 1255: iput(dp); 1256: iput(ip); 1257: } 1258: 1259: /* 1260: * Rmdir system call. 1261: */ 1262: rmdir() 1263: { 1264: struct a { 1265: char *name; 1266: } *uap = (struct a *)u.u_ap; 1267: register struct inode *ip, *dp; 1268: register struct nameidata *ndp = &u.u_nd; 1269: 1270: ndp->ni_nameiop = DELETE | LOCKPARENT; 1271: ndp->ni_segflg = UIO_USERSPACE; 1272: ndp->ni_dirp = uap->name; 1273: ip = namei(ndp); 1274: if (ip == NULL) 1275: return; 1276: dp = ndp->ni_pdir; 1277: /* 1278: * No rmdir "." please. 1279: */ 1280: if (dp == ip) { 1281: irele(dp); 1282: iput(ip); 1283: u.u_error = EINVAL; 1284: return; 1285: } 1286: if ((ip->i_mode&IFMT) != IFDIR) { 1287: u.u_error = ENOTDIR; 1288: goto out; 1289: } 1290: /* 1291: * Don't remove a mounted on directory. 1292: */ 1293: if (ip->i_dev != dp->i_dev) { 1294: u.u_error = EBUSY; 1295: goto out; 1296: } 1297: /* 1298: * Verify the directory is empty (and valid). 1299: * (Rmdir ".." won't be valid since 1300: * ".." will contain a reference to 1301: * the current directory and thus be 1302: * non-empty.) 1303: */ 1304: if (ip->i_nlink != 2 || !dirempty(ip, dp->i_number)) { 1305: u.u_error = ENOTEMPTY; 1306: goto out; 1307: } 1308: /* 1309: * Delete reference to directory before purging 1310: * inode. If we crash in between, the directory 1311: * will be reattached to lost+found, 1312: */ 1313: if (dirremove(ndp) == 0) 1314: goto out; 1315: dp->i_nlink--; 1316: dp->i_flag |= ICHG; 1317: cacheinval(dp); 1318: iput(dp); 1319: dp = NULL; 1320: /* 1321: * Truncate inode. The only stuff left 1322: * in the directory is "." and "..". The 1323: * "." reference is inconsequential since 1324: * we're quashing it. The ".." reference 1325: * has already been adjusted above. We've 1326: * removed the "." reference and the reference 1327: * in the parent directory, but there may be 1328: * other hard links so decrement by 2 and 1329: * worry about them later. 1330: */ 1331: ip->i_nlink -= 2; 1332: itrunc(ip, (u_long)0); 1333: cacheinval(ip); 1334: out: 1335: if (dp) 1336: iput(dp); 1337: iput(ip); 1338: } 1339: 1340: struct file * 1341: getinode(fdes) 1342: int fdes; 1343: { 1344: struct file *fp; 1345: 1346: if ((unsigned)fdes >= NOFILE || (fp = u.u_ofile[fdes]) == NULL) { 1347: u.u_error = EBADF; 1348: return ((struct file *)0); 1349: } 1350: if (fp->f_type != DTYPE_INODE) { 1351: u.u_error = EINVAL; 1352: return ((struct file *)0); 1353: } 1354: return (fp); 1355: } 1356: 1357: /* 1358: * mode mask for creation of files 1359: */ 1360: umask() 1361: { 1362: register struct a { 1363: int mask; 1364: } *uap = (struct a *)u.u_ap; 1365: 1366: u.u_r.r_val1 = u.u_cmask; 1367: u.u_cmask = uap->mask & 07777; 1368: }