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