]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/hfs/hfscommon/Misc/FileExtentMapping.c
xnu-2782.20.48.tar.gz
[apple/xnu.git] / bsd / hfs / hfscommon / Misc / FileExtentMapping.c
index a732366ca8be9a1bf8dd3efe5c82ee2a3ad84d5d..018a8701eda78004433f3018c1f752fe428abe19 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
@@ -97,7 +97,9 @@ Internal Routines:
                                        and was in the extents file, then delete the record instead.
 */
 
                                        and was in the extents file, then delete the record instead.
 */
 
+#if CONFIG_HFS_STD
 static const int64_t kTwoGigabytes = 0x80000000LL;
 static const int64_t kTwoGigabytes = 0x80000000LL;
+#endif
 
 enum
 {
 
 enum
 {
@@ -108,9 +110,11 @@ enum
 };
 
 
 };
 
 
+#if CONFIG_HFS_STD
 static OSErr HFSPlusToHFSExtents(
        const HFSPlusExtentRecord       oldExtents,
        HFSExtentRecord                         newExtents);
 static OSErr HFSPlusToHFSExtents(
        const HFSPlusExtentRecord       oldExtents,
        HFSExtentRecord                         newExtents);
+#endif
 
 static OSErr FindExtentRecord(
        const ExtendedVCB               *vcb,
 
 static OSErr FindExtentRecord(
        const ExtendedVCB               *vcb,
@@ -180,7 +184,8 @@ static OSErr TruncateExtents(
 
 static OSErr UpdateExtentRecord (
        ExtendedVCB             *vcb,
 
 static OSErr UpdateExtentRecord (
        ExtendedVCB             *vcb,
-       FCB                                             *fcb,
+       FCB                             *fcb,
+       int                             deleted,
        const HFSPlusExtentKey  *extentFileKey,
        const HFSPlusExtentRecord       extentData,
        u_int32_t                                       extentBTreeHint);
        const HFSPlusExtentKey  *extentFileKey,
        const HFSPlusExtentRecord       extentData,
        u_int32_t                                       extentBTreeHint);
@@ -224,7 +229,7 @@ static OSErr FindExtentRecord(
        u_int32_t                       *foundHint)
 {
        FCB *                           fcb;
        u_int32_t                       *foundHint)
 {
        FCB *                           fcb;
-       BTreeIterator           *btIterator;
+       struct BTreeIterator *btIterator = NULL;
        FSBufferDescriptor      btRecord;
        OSErr                           err;
        u_int16_t                       btRecordSize;
        FSBufferDescriptor      btRecord;
        OSErr                           err;
        u_int16_t                       btRecordSize;
@@ -233,22 +238,27 @@ static OSErr FindExtentRecord(
        if (foundHint)
                *foundHint = 0;
        fcb = GetFileControlBlock(vcb->extentsRefNum);
        if (foundHint)
                *foundHint = 0;
        fcb = GetFileControlBlock(vcb->extentsRefNum);
-       
-       MALLOC(btIterator, BTreeIterator *, sizeof(*btIterator), M_TEMP, M_WAITOK);
+
+       MALLOC (btIterator, struct BTreeIterator*, sizeof(struct BTreeIterator), M_TEMP, M_WAITOK);
+       if (btIterator == NULL) {
+               return memFullErr;  // translates to ENOMEM
+       }
        bzero(btIterator, sizeof(*btIterator));
 
        bzero(btIterator, sizeof(*btIterator));
 
-       if (vcb->vcbSigWord == kHFSSigWord) {
-               HFSExtentKey *          extentKeyPtr;
-               HFSExtentRecord         extentData;
+       /* HFS Plus / HFSX */
+       if (vcb->vcbSigWord != kHFSSigWord) {
+               HFSPlusExtentKey *      extentKeyPtr;
+               HFSPlusExtentRecord     extentData;
 
 
-               extentKeyPtr = (HFSExtentKey*) &btIterator->key;
-               extentKeyPtr->keyLength = kHFSExtentKeyMaximumLength;
-               extentKeyPtr->forkType = forkType;
-               extentKeyPtr->fileID = fileID;
+               extentKeyPtr = (HFSPlusExtentKey*) &btIterator->key;
+               extentKeyPtr->keyLength  = kHFSPlusExtentKeyMaximumLength;
+               extentKeyPtr->forkType   = forkType;
+               extentKeyPtr->pad                = 0;
+               extentKeyPtr->fileID     = fileID;
                extentKeyPtr->startBlock = startBlock;
                
                btRecord.bufferAddress = &extentData;
                extentKeyPtr->startBlock = startBlock;
                
                btRecord.bufferAddress = &extentData;
-               btRecord.itemSize = sizeof(HFSExtentRecord);
+               btRecord.itemSize = sizeof(HFSPlusExtentRecord);
                btRecord.itemCount = 1;
 
                err = BTSearchRecord(fcb, btIterator, &btRecord, &btRecordSize, btIterator);
                btRecord.itemCount = 1;
 
                err = BTSearchRecord(fcb, btIterator, &btRecord, &btRecordSize, btIterator);
@@ -269,44 +279,26 @@ static OSErr FindExtentRecord(
                }
 
                if (err == noErr) {
                }
 
                if (err == noErr) {
-                       u_int16_t       i;
-                       
                        // Copy the found key back for the caller
                        // Copy the found key back for the caller
-                       if (foundKey) {
-                               foundKey->keyLength  = kHFSPlusExtentKeyMaximumLength;
-                               foundKey->forkType   = extentKeyPtr->forkType;
-                               foundKey->pad        = 0;
-                               foundKey->fileID     = extentKeyPtr->fileID;
-                               foundKey->startBlock = extentKeyPtr->startBlock;
-                       }
+                       if (foundKey)
+                               BlockMoveData(extentKeyPtr, foundKey, sizeof(HFSPlusExtentKey));
                        // Copy the found data back for the caller
                        // Copy the found data back for the caller
-                       foundData[0].startBlock = extentData[0].startBlock;
-                       foundData[0].blockCount = extentData[0].blockCount;
-                       foundData[1].startBlock = extentData[1].startBlock;
-                       foundData[1].blockCount = extentData[1].blockCount;
-                       foundData[2].startBlock = extentData[2].startBlock;
-                       foundData[2].blockCount = extentData[2].blockCount;
-                       
-                       for (i = 3; i < kHFSPlusExtentDensity; ++i)
-                       {
-                               foundData[i].startBlock = 0;
-                               foundData[i].blockCount = 0;
-                       }
+                       BlockMoveData(&extentData, foundData, sizeof(HFSPlusExtentRecord));
                }
        }
                }
        }
-       else {          // HFS Plus volume
-               HFSPlusExtentKey *      extentKeyPtr;
-               HFSPlusExtentRecord     extentData;
+#if CONFIG_HFS_STD
+       else { 
+               HFSExtentKey *          extentKeyPtr;
+               HFSExtentRecord         extentData;
 
 
-               extentKeyPtr = (HFSPlusExtentKey*) &btIterator->key;
-               extentKeyPtr->keyLength  = kHFSPlusExtentKeyMaximumLength;
-               extentKeyPtr->forkType   = forkType;
-               extentKeyPtr->pad                = 0;
-               extentKeyPtr->fileID     = fileID;
+               extentKeyPtr = (HFSExtentKey*) &btIterator->key;
+               extentKeyPtr->keyLength = kHFSExtentKeyMaximumLength;
+               extentKeyPtr->forkType = forkType;
+               extentKeyPtr->fileID = fileID;
                extentKeyPtr->startBlock = startBlock;
                
                btRecord.bufferAddress = &extentData;
                extentKeyPtr->startBlock = startBlock;
                
                btRecord.bufferAddress = &extentData;
-               btRecord.itemSize = sizeof(HFSPlusExtentRecord);
+               btRecord.itemSize = sizeof(HFSExtentRecord);
                btRecord.itemCount = 1;
 
                err = BTSearchRecord(fcb, btIterator, &btRecord, &btRecordSize, btIterator);
                btRecord.itemCount = 1;
 
                err = BTSearchRecord(fcb, btIterator, &btRecord, &btRecordSize, btIterator);
@@ -327,17 +319,37 @@ static OSErr FindExtentRecord(
                }
 
                if (err == noErr) {
                }
 
                if (err == noErr) {
+                       u_int16_t       i;
+                       
                        // Copy the found key back for the caller
                        // Copy the found key back for the caller
-                       if (foundKey)
-                               BlockMoveData(extentKeyPtr, foundKey, sizeof(HFSPlusExtentKey));
+                       if (foundKey) {
+                               foundKey->keyLength  = kHFSPlusExtentKeyMaximumLength;
+                               foundKey->forkType   = extentKeyPtr->forkType;
+                               foundKey->pad        = 0;
+                               foundKey->fileID     = extentKeyPtr->fileID;
+                               foundKey->startBlock = extentKeyPtr->startBlock;
+                       }
                        // Copy the found data back for the caller
                        // Copy the found data back for the caller
-                       BlockMoveData(&extentData, foundData, sizeof(HFSPlusExtentRecord));
+                       foundData[0].startBlock = extentData[0].startBlock;
+                       foundData[0].blockCount = extentData[0].blockCount;
+                       foundData[1].startBlock = extentData[1].startBlock;
+                       foundData[1].blockCount = extentData[1].blockCount;
+                       foundData[2].startBlock = extentData[2].startBlock;
+                       foundData[2].blockCount = extentData[2].blockCount;
+                       
+                       for (i = 3; i < kHFSPlusExtentDensity; ++i)
+                       {
+                               foundData[i].startBlock = 0;
+                               foundData[i].blockCount = 0;
+                       }
                }
        }
                }
        }
+#endif
 
        if (foundHint)
                *foundHint = btIterator->hint.nodeNum;
 
        if (foundHint)
                *foundHint = btIterator->hint.nodeNum;
-       FREE(btIterator, M_TEMP);       
+
+       FREE(btIterator, M_TEMP);
        return err;
 }
 
        return err;
 }
 
@@ -349,7 +361,7 @@ static OSErr CreateExtentRecord(
        HFSPlusExtentRecord     extents,
        u_int32_t                       *hint)
 {
        HFSPlusExtentRecord     extents,
        u_int32_t                       *hint)
 {
-       BTreeIterator * btIterator;
+       struct BTreeIterator *btIterator = NULL;
        FSBufferDescriptor      btRecord;
        u_int16_t  btRecordSize;
        int  lockflags;
        FSBufferDescriptor      btRecord;
        u_int16_t  btRecordSize;
        int  lockflags;
@@ -358,7 +370,10 @@ static OSErr CreateExtentRecord(
        err = noErr;
        *hint = 0;
 
        err = noErr;
        *hint = 0;
 
-       MALLOC(btIterator, BTreeIterator *, sizeof(*btIterator), M_TEMP, M_WAITOK);
+       MALLOC (btIterator, struct BTreeIterator*, sizeof(struct BTreeIterator), M_TEMP, M_WAITOK);
+       if (btIterator == NULL) {
+               return memFullErr;  // translates to ENOMEM
+       }
        bzero(btIterator, sizeof(*btIterator));
 
        /*
        bzero(btIterator, sizeof(*btIterator));
 
        /*
@@ -370,7 +385,18 @@ static OSErr CreateExtentRecord(
         */
        lockflags = hfs_systemfile_lock(vcb, SFL_EXTENTS, HFS_EXCLUSIVE_LOCK);
 
         */
        lockflags = hfs_systemfile_lock(vcb, SFL_EXTENTS, HFS_EXCLUSIVE_LOCK);
 
-       if (vcb->vcbSigWord == kHFSSigWord) {
+       /* HFS+/HFSX */
+       if (vcb->vcbSigWord != kHFSSigWord) {
+               btRecordSize = sizeof(HFSPlusExtentRecord);
+               btRecord.bufferAddress = extents;
+               btRecord.itemSize = btRecordSize;
+               btRecord.itemCount = 1;
+
+               BlockMoveData(key, &btIterator->key, sizeof(HFSPlusExtentKey));
+       }
+#if CONFIG_HFS_STD
+       else {
+               /* HFS Standard */
                HFSExtentKey *          keyPtr;
                HFSExtentRecord         data;
                
                HFSExtentKey *          keyPtr;
                HFSExtentRecord         data;
                
@@ -387,14 +413,7 @@ static OSErr CreateExtentRecord(
                
                err = HFSPlusToHFSExtents(extents, data);
        }
                
                err = HFSPlusToHFSExtents(extents, data);
        }
-       else {          // HFS Plus volume
-               btRecordSize = sizeof(HFSPlusExtentRecord);
-               btRecord.bufferAddress = extents;
-               btRecord.itemSize = btRecordSize;
-               btRecord.itemCount = 1;
-
-               BlockMoveData(key, &btIterator->key, sizeof(HFSPlusExtentKey));
-       }
+#endif
 
        if (err == noErr)
                err = BTInsertRecord(GetFileControlBlock(vcb->extentsRefNum), btIterator, &btRecord, btRecordSize);
 
        if (err == noErr)
                err = BTInsertRecord(GetFileControlBlock(vcb->extentsRefNum), btIterator, &btRecord, btRecordSize);
@@ -405,8 +424,8 @@ static OSErr CreateExtentRecord(
        (void) BTFlushPath(GetFileControlBlock(vcb->extentsRefNum));
        
        hfs_systemfile_unlock(vcb, lockflags);
        (void) BTFlushPath(GetFileControlBlock(vcb->extentsRefNum));
        
        hfs_systemfile_unlock(vcb, lockflags);
-       
-       FREE(btIterator, M_TEMP);       
+
+       FREE (btIterator, M_TEMP);      
        return err;
 }
 
        return err;
 }
 
@@ -417,38 +436,46 @@ static OSErr DeleteExtentRecord(
        u_int32_t                       fileID,
        u_int32_t                       startBlock)
 {
        u_int32_t                       fileID,
        u_int32_t                       startBlock)
 {
-       BTreeIterator * btIterator;
+       struct BTreeIterator *btIterator = NULL;
        OSErr                           err;
        
        err = noErr;
 
        OSErr                           err;
        
        err = noErr;
 
-       MALLOC(btIterator, BTreeIterator *, sizeof(*btIterator), M_TEMP, M_WAITOK);
+       MALLOC (btIterator, struct BTreeIterator*, sizeof(struct BTreeIterator), M_TEMP, M_WAITOK);
+       if (btIterator == NULL) {
+               return memFullErr;  // translates to ENOMEM
+       }
        bzero(btIterator, sizeof(*btIterator));
        
        bzero(btIterator, sizeof(*btIterator));
        
-       if (vcb->vcbSigWord == kHFSSigWord) {
-               HFSExtentKey *  keyPtr;
+       /* HFS+ / HFSX */
+       if (vcb->vcbSigWord != kHFSSigWord) {           //      HFS Plus volume
+               HFSPlusExtentKey *      keyPtr;
 
 
-               keyPtr = (HFSExtentKey*) &btIterator->key;
-               keyPtr->keyLength       = kHFSExtentKeyMaximumLength;
+               keyPtr = (HFSPlusExtentKey*) &btIterator->key;
+               keyPtr->keyLength       = kHFSPlusExtentKeyMaximumLength;
                keyPtr->forkType        = forkType;
                keyPtr->forkType        = forkType;
+               keyPtr->pad                     = 0;
                keyPtr->fileID          = fileID;
                keyPtr->startBlock      = startBlock;
        }
                keyPtr->fileID          = fileID;
                keyPtr->startBlock      = startBlock;
        }
-       else {          //      HFS Plus volume
-               HFSPlusExtentKey *      keyPtr;
+#if CONFIG_HFS_STD
+       else {
+               /* HFS standard */
+               HFSExtentKey *  keyPtr;
 
 
-               keyPtr = (HFSPlusExtentKey*) &btIterator->key;
-               keyPtr->keyLength       = kHFSPlusExtentKeyMaximumLength;
+               keyPtr = (HFSExtentKey*) &btIterator->key;
+               keyPtr->keyLength       = kHFSExtentKeyMaximumLength;
                keyPtr->forkType        = forkType;
                keyPtr->forkType        = forkType;
-               keyPtr->pad                     = 0;
                keyPtr->fileID          = fileID;
                keyPtr->startBlock      = startBlock;
        }
                keyPtr->fileID          = fileID;
                keyPtr->startBlock      = startBlock;
        }
+#endif
 
        err = BTDeleteRecord(GetFileControlBlock(vcb->extentsRefNum), btIterator);
        (void) BTFlushPath(GetFileControlBlock(vcb->extentsRefNum));
        
 
        err = BTDeleteRecord(GetFileControlBlock(vcb->extentsRefNum), btIterator);
        (void) BTFlushPath(GetFileControlBlock(vcb->extentsRefNum));
        
-       FREE(btIterator, M_TEMP);       
+
+       FREE(btIterator, M_TEMP);
        return err;
 }
 
        return err;
 }
 
@@ -462,7 +489,6 @@ static OSErr DeleteExtentRecord(
 //
 //_________________________________________________________________________________
 
 //
 //_________________________________________________________________________________
 
-__private_extern__
 OSErr MapFileBlockC (
        ExtendedVCB             *vcb,                           // volume that file resides on
        FCB                             *fcb,                           // FCB of file
 OSErr MapFileBlockC (
        ExtendedVCB             *vcb,                           // volume that file resides on
        FCB                             *fcb,                           // FCB of file
@@ -487,7 +513,7 @@ OSErr MapFileBlockC (
        off_t                           tmpOff;
 
        allocBlockSize = vcb->blockSize;
        off_t                           tmpOff;
 
        allocBlockSize = vcb->blockSize;
-       sectorSize = VCBTOHFS(vcb)->hfs_phys_block_size;
+       sectorSize = VCBTOHFS(vcb)->hfs_logical_block_size;
 
        err = SearchExtentFile(vcb, fcb, offset, &foundKey, foundData, &foundIndex, &hint, &nextFABN);
        if (err == noErr) {
 
        err = SearchExtentFile(vcb, fcb, offset, &foundKey, foundData, &foundIndex, &hint, &nextFABN);
        if (err == noErr) {
@@ -535,10 +561,19 @@ OSErr MapFileBlockC (
        if (availableBytes)
        {
                tmpOff = dataEnd - offset;
        if (availableBytes)
        {
                tmpOff = dataEnd - offset;
-               if (tmpOff > (off_t)(numberOfBytes))
+               /*
+                * Disallow negative runs.
+                */
+               if (tmpOff <= 0) {
+                       return EINVAL;
+               }
+
+               if (tmpOff > (off_t)(numberOfBytes)) {
                        *availableBytes = numberOfBytes;  // more there than they asked for, so pin the output
                        *availableBytes = numberOfBytes;  // more there than they asked for, so pin the output
-               else
+               }
+               else {
                        *availableBytes = tmpOff;
                        *availableBytes = tmpOff;
+               }
        }
 
        return noErr;
        }
 
        return noErr;
@@ -582,7 +617,7 @@ static OSErr ReleaseExtents(
                        break;
                }
 
                        break;
                }
 
-               err = BlockDeallocate( vcb, extentRecord[extentIndex].startBlock, numAllocationBlocks );
+               err = BlockDeallocate( vcb, extentRecord[extentIndex].startBlock, numAllocationBlocks , 0);
                if ( err != noErr )
                        break;
                                        
                if ( err != noErr )
                        break;
                                        
@@ -688,7 +723,6 @@ static OSErr DeallocateFork(
 //     Function:       Flushes the extent file for a specified volume
 //\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b
 
 //     Function:       Flushes the extent file for a specified volume
 //\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b
 
-__private_extern__
 OSErr FlushExtentFile( ExtendedVCB *vcb )
 {
        FCB *   fcb;
 OSErr FlushExtentFile( ExtendedVCB *vcb )
 {
        FCB *   fcb;
@@ -716,6 +750,7 @@ OSErr FlushExtentFile( ExtendedVCB *vcb )
 }
 
 
 }
 
 
+#if CONFIG_HFS_STD
 //\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b
 //     Routine:        CompareExtentKeys
 //
 //\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b
 //     Routine:        CompareExtentKeys
 //
@@ -730,9 +765,9 @@ int32_t CompareExtentKeys( const HFSExtentKey *searchKey, const HFSExtentKey *tr
        
        #if DEBUG_BUILD
                if (searchKey->keyLength != kHFSExtentKeyMaximumLength)
        
        #if DEBUG_BUILD
                if (searchKey->keyLength != kHFSExtentKeyMaximumLength)
-                       DebugStr("\pHFS: search Key is wrong length");
+                       DebugStr("HFS: search Key is wrong length");
                if (trialKey->keyLength != kHFSExtentKeyMaximumLength)
                if (trialKey->keyLength != kHFSExtentKeyMaximumLength)
-                       DebugStr("\pHFS: trial Key is wrong length");
+                       DebugStr("HFS: trial Key is wrong length");
        #endif
        
        result = -1;            //      assume searchKey < trialKey
        #endif
        
        result = -1;            //      assume searchKey < trialKey
@@ -777,7 +812,7 @@ int32_t CompareExtentKeys( const HFSExtentKey *searchKey, const HFSExtentKey *tr
        
        return( result );
 }
        
        return( result );
 }
-
+#endif
 
 
 //\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b
 
 
 //\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b
@@ -794,9 +829,9 @@ int32_t CompareExtentKeysPlus( const HFSPlusExtentKey *searchKey, const HFSPlusE
        
        #if DEBUG_BUILD
                if (searchKey->keyLength != kHFSPlusExtentKeyMaximumLength)
        
        #if DEBUG_BUILD
                if (searchKey->keyLength != kHFSPlusExtentKeyMaximumLength)
-                       DebugStr("\pHFS: search Key is wrong length");
+                       DebugStr("HFS: search Key is wrong length");
                if (trialKey->keyLength != kHFSPlusExtentKeyMaximumLength)
                if (trialKey->keyLength != kHFSPlusExtentKeyMaximumLength)
-                       DebugStr("\pHFS: trial Key is wrong length");
+                       DebugStr("HFS: trial Key is wrong length");
        #endif
        
        result = -1;            //      assume searchKey < trialKey
        #endif
        
        result = -1;            //      assume searchKey < trialKey
@@ -848,7 +883,6 @@ int32_t CompareExtentKeysPlus( const HFSPlusExtentKey *searchKey, const HFSPlusE
  * Used by hfs_extendfs to extend the volume allocation bitmap file.
  *
  */
  * Used by hfs_extendfs to extend the volume allocation bitmap file.
  *
  */
-__private_extern__
 int
 AddFileExtent(ExtendedVCB *vcb, FCB *fcb, u_int32_t startBlock, u_int32_t blockCount)
 {
 int
 AddFileExtent(ExtendedVCB *vcb, FCB *fcb, u_int32_t startBlock, u_int32_t blockCount)
 {
@@ -902,7 +936,7 @@ AddFileExtent(ExtendedVCB *vcb, FCB *fcb, u_int32_t startBlock, u_int32_t blockC
                 */
                foundData[foundIndex].startBlock = startBlock;
                foundData[foundIndex].blockCount = blockCount;
                 */
                foundData[foundIndex].startBlock = startBlock;
                foundData[foundIndex].blockCount = blockCount;
-               error = UpdateExtentRecord(vcb, fcb, &foundKey, foundData, hint);
+               error = UpdateExtentRecord(vcb, fcb, 0, &foundKey, foundData, hint);
        }
        (void) FlushExtentFile(vcb);
 
        }
        (void) FlushExtentFile(vcb);
 
@@ -918,7 +952,6 @@ AddFileExtent(ExtendedVCB *vcb, FCB *fcb, u_int32_t startBlock, u_int32_t blockC
 //
 //_________________________________________________________________________________
 
 //
 //_________________________________________________________________________________
 
-__private_extern__
 OSErr ExtendFileC (
        ExtendedVCB             *vcb,                           // volume that file resides on
        FCB                             *fcb,                           // FCB of file to truncate
 OSErr ExtendFileC (
        ExtendedVCB             *vcb,                           // volume that file resides on
        FCB                             *fcb,                           // FCB of file to truncate
@@ -942,6 +975,7 @@ OSErr ExtendFileC (
        Boolean                         wantContig;
        Boolean                         useMetaZone;
        Boolean                         needsFlush;
        Boolean                         wantContig;
        Boolean                         useMetaZone;
        Boolean                         needsFlush;
+       int                                     allowFlushTxns;
        u_int32_t                       actualStartBlock;
        u_int32_t                       actualNumBlocks;
        u_int32_t                       numExtentsPerRecord;
        u_int32_t                       actualStartBlock;
        u_int32_t                       actualNumBlocks;
        u_int32_t                       numExtentsPerRecord;
@@ -949,8 +983,8 @@ OSErr ExtendFileC (
        int64_t                         availbytes;
        int64_t                         peof;
        u_int32_t                       prevblocks;
        int64_t                         availbytes;
        int64_t                         peof;
        u_int32_t                       prevblocks;
-       
-
+       struct hfsmount *hfsmp = (struct hfsmount*)vcb; 
+       allowFlushTxns = 0;
        needsFlush = false;
        *actualBytesAdded = 0;
        volumeBlockSize = vcb->blockSize;
        needsFlush = false;
        *actualBytesAdded = 0;
        volumeBlockSize = vcb->blockSize;
@@ -958,20 +992,22 @@ OSErr ExtendFileC (
        forceContig = ((flags & kEFContigMask) != 0);
        prevblocks = fcb->ff_blocks;
 
        forceContig = ((flags & kEFContigMask) != 0);
        prevblocks = fcb->ff_blocks;
 
-       if (vcb->vcbSigWord == kHFSPlusSigWord)
+       if (vcb->vcbSigWord != kHFSSigWord) {
                numExtentsPerRecord = kHFSPlusExtentDensity;
                numExtentsPerRecord = kHFSPlusExtentDensity;
-       else
+       }
+#if CONFIG_HFS_STD
+       else {
+               /* HFS Standard */
                numExtentsPerRecord = kHFSExtentDensity;
 
                numExtentsPerRecord = kHFSExtentDensity;
 
-       //
-       //      Make sure the request and new PEOF are less than 2GB if HFS.
-       //
-       if (vcb->vcbSigWord == kHFSSigWord) {
+               /* Make sure the request and new PEOF are less than 2GB if HFS std*/
                if (bytesToAdd >=  kTwoGigabytes)
                if (bytesToAdd >=  kTwoGigabytes)
-                       goto Overflow;
+                       goto HFS_Std_Overflow;
                if ((((int64_t)fcb->ff_blocks * (int64_t)volumeBlockSize) + bytesToAdd) >= kTwoGigabytes)
                if ((((int64_t)fcb->ff_blocks * (int64_t)volumeBlockSize) + bytesToAdd) >= kTwoGigabytes)
-                       goto Overflow;
+                       goto HFS_Std_Overflow;
        }
        }
+#endif
+
        //
        //      Determine how many blocks need to be allocated.
        //      Round up the number of desired bytes to add.
        //
        //      Determine how many blocks need to be allocated.
        //      Round up the number of desired bytes to add.
@@ -986,9 +1022,9 @@ OSErr ExtendFileC (
        &&  (vcb->vcbSigWord == kHFSPlusSigWord)
        &&  (bytesToAdd < (int64_t)HFS_MAX_DEFERED_ALLOC)
        &&  (blocksToAdd < hfs_freeblks(VCBTOHFS(vcb), 1))) {
        &&  (vcb->vcbSigWord == kHFSPlusSigWord)
        &&  (bytesToAdd < (int64_t)HFS_MAX_DEFERED_ALLOC)
        &&  (blocksToAdd < hfs_freeblks(VCBTOHFS(vcb), 1))) {
-               HFS_MOUNT_LOCK(vcb, TRUE);
+               hfs_lock_mount (hfsmp);
                vcb->loanedBlocks += blocksToAdd;
                vcb->loanedBlocks += blocksToAdd;
-               HFS_MOUNT_UNLOCK(vcb, TRUE);
+               hfs_unlock_mount(hfsmp);
 
                fcb->ff_unallocblocks += blocksToAdd;
                FTOC(fcb)->c_blocks   += blocksToAdd;
 
                fcb->ff_unallocblocks += blocksToAdd;
                FTOC(fcb)->c_blocks   += blocksToAdd;
@@ -1011,9 +1047,9 @@ OSErr ExtendFileC (
                fcb->ff_blocks -= loanedBlocks;
                fcb->ff_unallocblocks  = 0;
 
                fcb->ff_blocks -= loanedBlocks;
                fcb->ff_unallocblocks  = 0;
 
-               HFS_MOUNT_LOCK(vcb, TRUE);
+               hfs_lock_mount(hfsmp);
                vcb->loanedBlocks -= loanedBlocks;
                vcb->loanedBlocks -= loanedBlocks;
-               HFS_MOUNT_UNLOCK(vcb, TRUE);
+               hfs_unlock_mount(hfsmp);
        }
 
        //
        }
 
        //
@@ -1030,18 +1066,20 @@ OSErr ExtendFileC (
                maximumBytes = bytesToAdd;
        }
        
                maximumBytes = bytesToAdd;
        }
        
+#if CONFIG_HFS_STD
        //
        //      Compute new physical EOF, rounded up to a multiple of a block.
        //
        if ( (vcb->vcbSigWord == kHFSSigWord) &&                //      Too big?
                 ((((int64_t)fcb->ff_blocks * (int64_t)volumeBlockSize) + bytesToAdd) >= kTwoGigabytes) ) {
                if (allOrNothing)                                       // Yes, must they have it all?
        //
        //      Compute new physical EOF, rounded up to a multiple of a block.
        //
        if ( (vcb->vcbSigWord == kHFSSigWord) &&                //      Too big?
                 ((((int64_t)fcb->ff_blocks * (int64_t)volumeBlockSize) + bytesToAdd) >= kTwoGigabytes) ) {
                if (allOrNothing)                                       // Yes, must they have it all?
-                       goto Overflow;                                          // Yes, can't have it
+                       goto HFS_Std_Overflow;                                          // Yes, can't have it
                else {
                        --blocksToAdd;                                          // No, give give 'em one block less
                        bytesToAdd -= volumeBlockSize;
                }
        }
                else {
                        --blocksToAdd;                                          // No, give give 'em one block less
                        bytesToAdd -= volumeBlockSize;
                }
        }
+#endif
 
        //
        //      If allocation is all-or-nothing, make sure there are
 
        //
        //      If allocation is all-or-nothing, make sure there are
@@ -1087,10 +1125,55 @@ OSErr ExtendFileC (
        //      If that fails, get whatever we can.
        //              If forceContig, then take whatever we got
        //              else, keep getting bits and pieces (non-contig)
        //      If that fails, get whatever we can.
        //              If forceContig, then take whatever we got
        //              else, keep getting bits and pieces (non-contig)
+       
+       /*
+        * Note that for sparse devices (like sparse bundle dmgs), we
+        * should only be aggressive with re-using once-allocated pieces
+        * if we're not dealing with system files.  If we're trying to operate
+        * on behalf of a system file, we need the maximum contiguous amount
+        * possible.  For non-system files we favor locality and fragmentation over
+        * contiguity as it can result in fewer blocks being needed from the underlying
+        * filesystem that the sparse image resides upon. 
+        */
        err = noErr;
        err = noErr;
-       wantContig = true;
+       if (   (vcb->hfs_flags & HFS_HAS_SPARSE_DEVICE)
+                       && (fcb->ff_cp->c_fileid >= kHFSFirstUserCatalogNodeID)
+                       && (flags & kEFMetadataMask) == 0) {
+               /*
+                * We want locality over contiguity so by default we set wantContig to 
+                * false unless we hit one of the circumstances below.
+                */ 
+               wantContig = false;
+               if (hfs_isrbtree_active(VCBTOHFS(vcb))) {
+                       /* 
+                        * If the red-black tree is acive, we can always find a suitable contiguous
+                        * chunk.  So if the user specifically requests contiguous files,  we should 
+                        * honor that no matter what kind of device it is.
+                        */
+                       if (forceContig) {
+                               wantContig = true;
+                       }
+               }
+               else {
+                       /* 
+                        * If the red-black tree is not active, then only set wantContig to true
+                        * if we have never done a contig scan on the device, which would populate
+                        * the free extent cache.  Note that the caller may explicitly unset the 
+                        * DID_CONTIG_SCAN bit in order to force us to vend a contiguous extent here
+                        * if the caller wants to get a contiguous chunk.
+                        */
+                       if ((vcb->hfs_flags & HFS_DID_CONTIG_SCAN) == 0) { 
+                               vcb->hfs_flags |= HFS_DID_CONTIG_SCAN;  
+                               wantContig = true;
+                       }
+               }
+       } 
+       else {
+               wantContig = true;
+       }
+
+
        useMetaZone = flags & kEFMetadataMask;
        useMetaZone = flags & kEFMetadataMask;
-       vcb->vcbFreeExtCnt = 0; /* For now, force rebuild of free extent list */
        do {
                if (blockHint != 0)
                        startBlock = blockHint;
        do {
                if (blockHint != 0)
                        startBlock = blockHint;
@@ -1106,23 +1189,45 @@ OSErr ExtendFileC (
                if (availbytes <= 0) {
                        err = dskFulErr;
                } else {
                if (availbytes <= 0) {
                        err = dskFulErr;
                } else {
-                       if (wantContig && (availbytes < bytesToAdd))
+                       if (wantContig && (availbytes < bytesToAdd)) {
                                err = dskFulErr;
                                err = dskFulErr;
+                       }
                        else {
                        else {
+                               uint32_t ba_flags = 0;
+
+                               if (wantContig) {
+                                       ba_flags |= HFS_ALLOC_FORCECONTIG;      
+                               }
+                               if (useMetaZone) {
+                                       ba_flags |= HFS_ALLOC_METAZONE;
+                               }
+                               if (allowFlushTxns) {
+                                       ba_flags |= HFS_ALLOC_FLUSHTXN;
+                               }
+
                                err = BlockAllocate(
                                                  vcb,
                                                  startBlock,
                                                  howmany(MIN(bytesToAdd, availbytes), volumeBlockSize),
                                                  howmany(MIN(maximumBytes, availbytes), volumeBlockSize),
                                err = BlockAllocate(
                                                  vcb,
                                                  startBlock,
                                                  howmany(MIN(bytesToAdd, availbytes), volumeBlockSize),
                                                  howmany(MIN(maximumBytes, availbytes), volumeBlockSize),
-                                                 wantContig,
-                                                 useMetaZone,
+                                                 ba_flags,
                                                  &actualStartBlock,
                                                  &actualNumBlocks);
                        }
                }
                if (err == dskFulErr) {
                                                  &actualStartBlock,
                                                  &actualNumBlocks);
                        }
                }
                if (err == dskFulErr) {
-                       if (forceContig)
-                               break;                  // AllocContig failed because not enough contiguous space
+                       if (forceContig) {
+                               if (allowFlushTxns == 0) {
+                                       /* If we're forcing contiguity, re-try but allow plucking from recently freed regions */
+                                       allowFlushTxns = 1;
+                                       wantContig = 1;
+                                       err = noErr;
+                                       continue;
+                               }
+                               else {
+                                       break;                  // AllocContig failed because not enough contiguous space
+                               }
+                       }
                        if (wantContig) {
                                //      Couldn't get one big chunk, so get whatever we can.
                                err = noErr;
                        if (wantContig) {
                                //      Couldn't get one big chunk, so get whatever we can.
                                err = noErr;
@@ -1131,12 +1236,21 @@ OSErr ExtendFileC (
                        }
                        if (actualNumBlocks != 0)
                                err = noErr;
                        }
                        if (actualNumBlocks != 0)
                                err = noErr;
+
                        if (useMetaZone == 0) {
                                /* Couldn't get anything so dip into metadat zone */
                                err = noErr;
                                useMetaZone = 1;
                                continue;
                        }
                        if (useMetaZone == 0) {
                                /* Couldn't get anything so dip into metadat zone */
                                err = noErr;
                                useMetaZone = 1;
                                continue;
                        }
+
+                       /* If we couldn't find what we needed without flushing the journal, then go ahead and do it now */
+                       if (allowFlushTxns == 0) {
+                               allowFlushTxns = 1;
+                               err = noErr;
+                               continue;
+                       }
+
                }
                if (err == noErr) {
                    if (actualNumBlocks != 0) {
                }
                if (err == noErr) {
                    if (actualNumBlocks != 0) {
@@ -1149,7 +1263,7 @@ OSErr ExtendFileC (
                        if ((actualStartBlock == startBlock) && (blockHint == 0)) {
                                //      We grew the file's last extent, so just adjust the number of blocks.
                                foundData[foundIndex].blockCount += actualNumBlocks;
                        if ((actualStartBlock == startBlock) && (blockHint == 0)) {
                                //      We grew the file's last extent, so just adjust the number of blocks.
                                foundData[foundIndex].blockCount += actualNumBlocks;
-                               err = UpdateExtentRecord(vcb, fcb, &foundKey, foundData, hint);
+                               err = UpdateExtentRecord(vcb, fcb, 0, &foundKey, foundData, hint);
                                if (err != noErr) break;
                        }
                        else {
                                if (err != noErr) break;
                        }
                        else {
@@ -1161,7 +1275,7 @@ OSErr ExtendFileC (
                                if (foundIndex == numExtentsPerRecord) {
                                        //      This record is full.  Need to create a new one.
                                        if (FTOC(fcb)->c_fileid == kHFSExtentsFileID) {
                                if (foundIndex == numExtentsPerRecord) {
                                        //      This record is full.  Need to create a new one.
                                        if (FTOC(fcb)->c_fileid == kHFSExtentsFileID) {
-                                               (void) BlockDeallocate(vcb, actualStartBlock, actualNumBlocks);
+                                               (void) BlockDeallocate(vcb, actualStartBlock, actualNumBlocks, 0);
                                                err = dskFulErr;                // Oops.  Can't extend extents file past first record.
                                                break;
                                        }
                                                err = dskFulErr;                // Oops.  Can't extend extents file past first record.
                                                break;
                                        }
@@ -1192,7 +1306,7 @@ OSErr ExtendFileC (
                                                //      We couldn't create an extent record because extents B-tree
                                                //      couldn't grow.  Dellocate the extent just allocated and
                                                //      return a disk full error.
                                                //      We couldn't create an extent record because extents B-tree
                                                //      couldn't grow.  Dellocate the extent just allocated and
                                                //      return a disk full error.
-                                               (void) BlockDeallocate(vcb, actualStartBlock, actualNumBlocks);
+                                               (void) BlockDeallocate(vcb, actualStartBlock, actualNumBlocks, 0);
                                                err = dskFulErr;
                                        }
                                        if (err != noErr) break;
                                                err = dskFulErr;
                                        }
                                        if (err != noErr) break;
@@ -1203,7 +1317,7 @@ OSErr ExtendFileC (
                                        //      Add a new extent into this record and update.
                                        foundData[foundIndex].startBlock = actualStartBlock;
                                        foundData[foundIndex].blockCount = actualNumBlocks;
                                        //      Add a new extent into this record and update.
                                        foundData[foundIndex].startBlock = actualStartBlock;
                                        foundData[foundIndex].blockCount = actualNumBlocks;
-                                       err = UpdateExtentRecord(vcb, fcb, &foundKey, foundData, hint);
+                                       err = UpdateExtentRecord(vcb, fcb, 0, &foundKey, foundData, hint);
                                        if (err != noErr) break;
                                }
                        }
                                        if (err != noErr) break;
                                }
                        }
@@ -1240,10 +1354,10 @@ Exit:
                /* Keep the roving allocator out of the metadata zone. */
                if (vcb->nextAllocation >= VCBTOHFS(vcb)->hfs_metazone_start &&
                    vcb->nextAllocation <= VCBTOHFS(vcb)->hfs_metazone_end) {
                /* Keep the roving allocator out of the metadata zone. */
                if (vcb->nextAllocation >= VCBTOHFS(vcb)->hfs_metazone_start &&
                    vcb->nextAllocation <= VCBTOHFS(vcb)->hfs_metazone_end) {
-                       HFS_MOUNT_LOCK(vcb, TRUE);
+                       hfs_lock_mount (hfsmp);
                        HFS_UPDATE_NEXT_ALLOCATION(vcb, VCBTOHFS(vcb)->hfs_metazone_end + 1);   
                        MarkVCBDirty(vcb);
                        HFS_UPDATE_NEXT_ALLOCATION(vcb, VCBTOHFS(vcb)->hfs_metazone_end + 1);   
                        MarkVCBDirty(vcb);
-                       HFS_MOUNT_UNLOCK(vcb, TRUE);
+                       hfs_unlock_mount(hfsmp);
                }
        }
        if (prevblocks < fcb->ff_blocks) {
                }
        }
        if (prevblocks < fcb->ff_blocks) {
@@ -1257,9 +1371,11 @@ Exit:
 
        return err;
 
 
        return err;
 
-Overflow:
+#if CONFIG_HFS_STD
+HFS_Std_Overflow:
        err = fileBoundsErr;
        goto ErrorExit;
        err = fileBoundsErr;
        goto ErrorExit;
+#endif
 }
 
 
 }
 
 
@@ -1275,12 +1391,15 @@ Overflow:
 //
 //_________________________________________________________________________________
 
 //
 //_________________________________________________________________________________
 
-__private_extern__
 OSErr TruncateFileC (
        ExtendedVCB             *vcb,                           // volume that file resides on
        FCB                             *fcb,                           // FCB of file to truncate
        int64_t                 peof,                           // new physical size for file
 OSErr TruncateFileC (
        ExtendedVCB             *vcb,                           // volume that file resides on
        FCB                             *fcb,                           // FCB of file to truncate
        int64_t                 peof,                           // new physical size for file
+       int                             deleted,                        // if nonzero, the file's catalog record has already been deleted.
+       int                             rsrc,                           // does this represent a resource fork or not?
+       uint32_t                fileid,                         // the fileid of the file we're manipulating.
        Boolean                 truncateToExtent)       // if true, truncate to end of extent containing newPEOF
        Boolean                 truncateToExtent)       // if true, truncate to end of extent containing newPEOF
+
 {
        OSErr                           err;
        u_int32_t                       nextBlock;              //      next file allocation block to consider
 {
        OSErr                           err;
        u_int32_t                       nextBlock;              //      next file allocation block to consider
@@ -1300,16 +1419,20 @@ OSErr TruncateFileC (
 
        recordDeleted = false;
        
 
        recordDeleted = false;
        
-       if (vcb->vcbSigWord == kHFSPlusSigWord)
+       if (vcb->vcbSigWord == kHFSPlusSigWord) {
                numExtentsPerRecord = kHFSPlusExtentDensity;
                numExtentsPerRecord = kHFSPlusExtentDensity;
-       else
+       }
+       else {
                numExtentsPerRecord = kHFSExtentDensity;
                numExtentsPerRecord = kHFSExtentDensity;
-
-       if (FORK_IS_RSRC(fcb))
+       }
+       
+       if (rsrc) {
                forkType = kResourceForkType;
                forkType = kResourceForkType;
-       else
+       }
+       else {
                forkType = kDataForkType;
                forkType = kDataForkType;
-
+       }
+       
        temp64 = fcb->ff_blocks;
        physNumBlocks = (u_int32_t)temp64;
 
        temp64 = fcb->ff_blocks;
        physNumBlocks = (u_int32_t)temp64;
 
@@ -1320,13 +1443,16 @@ OSErr TruncateFileC (
        //
        nextBlock = howmany(peof, vcb->blockSize);      // number of allocation blocks to remain in file
        peof = (int64_t)((int64_t)nextBlock * (int64_t)vcb->blockSize);                                 // number of bytes in those blocks
        //
        nextBlock = howmany(peof, vcb->blockSize);      // number of allocation blocks to remain in file
        peof = (int64_t)((int64_t)nextBlock * (int64_t)vcb->blockSize);                                 // number of bytes in those blocks
+
+#if CONFIG_HFS_STD
        if ((vcb->vcbSigWord == kHFSSigWord) && (peof >= kTwoGigabytes)) {
                #if DEBUG_BUILD
        if ((vcb->vcbSigWord == kHFSSigWord) && (peof >= kTwoGigabytes)) {
                #if DEBUG_BUILD
-                       DebugStr("\pHFS: Trying to truncate a file to 2GB or more");
+                       DebugStr("HFS: Trying to truncate a file to 2GB or more");
                #endif
                err = fileBoundsErr;
                goto ErrorExit;
        }
                #endif
                err = fileBoundsErr;
                goto ErrorExit;
        }
+#endif
 
        //
        //      Update FCB's length
 
        //
        //      Update FCB's length
@@ -1335,13 +1461,21 @@ OSErr TruncateFileC (
         * XXX Any errors could cause ff_blocks and c_blocks to get out of sync...
         */
        numBlocks = peof / vcb->blockSize;
         * XXX Any errors could cause ff_blocks and c_blocks to get out of sync...
         */
        numBlocks = peof / vcb->blockSize;
-       FTOC(fcb)->c_blocks -= (fcb->ff_blocks - numBlocks);
+       if (!deleted) {
+               FTOC(fcb)->c_blocks -= (fcb->ff_blocks - numBlocks);
+       }
        fcb->ff_blocks = numBlocks;
        fcb->ff_blocks = numBlocks;
-
+       
        // this catalog entry is modified and *must* get forced 
        // to disk when hfs_update() is called
        // this catalog entry is modified and *must* get forced 
        // to disk when hfs_update() is called
-       FTOC(fcb)->c_flag |= C_MODIFIED | C_FORCEUPDATE;
-       
+       if (!deleted) {
+               /* 
+                * If the file is already C_NOEXISTS, then the catalog record
+                * has been removed from disk already.  We wouldn't need to force 
+                * another update
+                */
+               FTOC(fcb)->c_flag |= (C_MODIFIED | C_FORCEUPDATE);
+       }
        //
        //      If the new PEOF is 0, then truncateToExtent has no meaning (we should always deallocate
        //      all storage).
        //
        //      If the new PEOF is 0, then truncateToExtent has no meaning (we should always deallocate
        //      all storage).
@@ -1350,7 +1484,7 @@ OSErr TruncateFileC (
                int i;
                
                //      Deallocate all the extents for this fork
                int i;
                
                //      Deallocate all the extents for this fork
-               err = DeallocateFork(vcb, FTOC(fcb)->c_fileid, forkType, fcb->fcbExtents, &recordDeleted);
+               err = DeallocateFork(vcb, fileid, forkType, fcb->fcbExtents, &recordDeleted);
                if (err != noErr) goto ErrorExit;       //      got some error, so return it
                
                //      Update the catalog extent record (making sure it's zeroed out)
                if (err != noErr) goto ErrorExit;       //      got some error, so return it
                
                //      Update the catalog extent record (making sure it's zeroed out)
@@ -1384,7 +1518,7 @@ OSErr TruncateFileC (
                        //      Compute first volume allocation block to free
                        startBlock = extentRecord[extentIndex].startBlock + extentRecord[extentIndex].blockCount - numBlocks;
                        //      Free the blocks in bitmap
                        //      Compute first volume allocation block to free
                        startBlock = extentRecord[extentIndex].startBlock + extentRecord[extentIndex].blockCount - numBlocks;
                        //      Free the blocks in bitmap
-                       err = BlockDeallocate(vcb, startBlock, numBlocks);
+                       err = BlockDeallocate(vcb, startBlock, numBlocks, 0);
                        if (err != noErr) goto ErrorExit;
                        //      Adjust length of this extent
                        extentRecord[extentIndex].blockCount -= numBlocks;
                        if (err != noErr) goto ErrorExit;
                        //      Adjust length of this extent
                        extentRecord[extentIndex].blockCount -= numBlocks;
@@ -1408,7 +1542,7 @@ OSErr TruncateFileC (
        while (extentIndex < numExtentsPerRecord && extentRecord[extentIndex].blockCount != 0) {
                numBlocks = extentRecord[extentIndex].blockCount;
                //      Deallocate this extent
        while (extentIndex < numExtentsPerRecord && extentRecord[extentIndex].blockCount != 0) {
                numBlocks = extentRecord[extentIndex].blockCount;
                //      Deallocate this extent
-               err = BlockDeallocate(vcb, extentRecord[extentIndex].startBlock, numBlocks);
+               err = BlockDeallocate(vcb, extentRecord[extentIndex].startBlock, numBlocks, 0);
                if (err != noErr) goto ErrorExit;
                //      Update next file allocation block number
                nextBlock += numBlocks;
                if (err != noErr) goto ErrorExit;
                //      Update next file allocation block number
                nextBlock += numBlocks;
@@ -1426,7 +1560,7 @@ OSErr TruncateFileC (
        //      record (in the FCB, or extents file).
        //
        if (extentChanged) {
        //      record (in the FCB, or extents file).
        //
        if (extentChanged) {
-               err = UpdateExtentRecord(vcb, fcb, &key, extentRecord, hint);
+               err = UpdateExtentRecord(vcb, fcb, deleted, &key, extentRecord, hint);
                if (err != noErr) goto ErrorExit;
        }
        
                if (err != noErr) goto ErrorExit;
        }
        
@@ -1436,7 +1570,7 @@ OSErr TruncateFileC (
        //      blocks.
        //
        if (nextBlock < physNumBlocks)
        //      blocks.
        //
        if (nextBlock < physNumBlocks)
-               err = TruncateExtents(vcb, forkType, FTOC(fcb)->c_fileid, nextBlock, &recordDeleted);
+               err = TruncateExtents(vcb, forkType, fileid, nextBlock, &recordDeleted);
 
 Done:
 ErrorExit:
 
 Done:
 ErrorExit:
@@ -1451,7 +1585,6 @@ ErrorExit:
  * HFS Plus only
  *
  */
  * HFS Plus only
  *
  */
-__private_extern__
 OSErr HeadTruncateFile (
        ExtendedVCB  *vcb,
        FCB  *fcb,
 OSErr HeadTruncateFile (
        ExtendedVCB  *vcb,
        FCB  *fcb,
@@ -1488,7 +1621,7 @@ OSErr HeadTruncateFile (
                        break;  /* end of extents */
 
                if (blksfreed < headblks) {
                        break;  /* end of extents */
 
                if (blksfreed < headblks) {
-                       error = BlockDeallocate(vcb, fcb->fcbExtents[i].startBlock, blkcnt);
+                       error = BlockDeallocate(vcb, fcb->fcbExtents[i].startBlock, blkcnt, 0);
                        /*
                         * Any errors after the first BlockDeallocate
                         * must be ignored so we can put the file in
                        /*
                         * Any errors after the first BlockDeallocate
                         * must be ignored so we can put the file in
@@ -1499,7 +1632,7 @@ OSErr HeadTruncateFile (
                                        goto ErrorExit;  /* uh oh */
                                else {
                                        error = 0;
                                        goto ErrorExit;  /* uh oh */
                                else {
                                        error = 0;
-                                       printf("HeadTruncateFile: problems deallocating %s (%d)\n",
+                                       printf("hfs: HeadTruncateFile: problems deallocating %s (%d)\n",
                                               FTOC(fcb)->c_desc.cd_nameptr ? (const char *)FTOC(fcb)->c_desc.cd_nameptr : "", error);
                                }
                        }
                                               FTOC(fcb)->c_desc.cd_nameptr ? (const char *)FTOC(fcb)->c_desc.cd_nameptr : "", error);
                                }
                        }
@@ -1534,7 +1667,7 @@ OSErr HeadTruncateFile (
                         * a known state.
                         */
                        if (error != btNotFound)
                         * a known state.
                         */
                        if (error != btNotFound)
-                               printf("HeadTruncateFile: problems finding extents %s (%d)\n",
+                               printf("hfs: HeadTruncateFile: problems finding extents %s (%d)\n",
                                       FTOC(fcb)->c_desc.cd_nameptr ? (const char *)FTOC(fcb)->c_desc.cd_nameptr : "", error);
                        error = 0;
                        break;
                                       FTOC(fcb)->c_desc.cd_nameptr ? (const char *)FTOC(fcb)->c_desc.cd_nameptr : "", error);
                        error = 0;
                        break;
@@ -1546,9 +1679,9 @@ OSErr HeadTruncateFile (
                                break;  /* end of extents */
 
                        if (blksfreed < headblks) {
                                break;  /* end of extents */
 
                        if (blksfreed < headblks) {
-                               error = BlockDeallocate(vcb, extents[i].startBlock, blkcnt);
+                               error = BlockDeallocate(vcb, extents[i].startBlock, blkcnt, 0);
                                if (error) {
                                if (error) {
-                                       printf("HeadTruncateFile: problems deallocating %s (%d)\n",
+                                       printf("hfs: HeadTruncateFile: problems deallocating %s (%d)\n",
                                               FTOC(fcb)->c_desc.cd_nameptr ? (const char *)FTOC(fcb)->c_desc.cd_nameptr : "", error);
                                        error = 0;
                                }
                                               FTOC(fcb)->c_desc.cd_nameptr ? (const char *)FTOC(fcb)->c_desc.cd_nameptr : "", error);
                                        error = 0;
                                }
@@ -1563,7 +1696,7 @@ OSErr HeadTruncateFile (
                
                error = DeleteExtentRecord(vcb, forkType, fileID, startblk);
                if (error) {
                
                error = DeleteExtentRecord(vcb, forkType, fileID, startblk);
                if (error) {
-                       printf("HeadTruncateFile: problems deallocating %s (%d)\n",
+                       printf("hfs: HeadTruncateFile: problems deallocating %s (%d)\n",
                                FTOC(fcb)->c_desc.cd_nameptr ? (const char *)FTOC(fcb)->c_desc.cd_nameptr : "", error);
                        error = 0;
                }
                                FTOC(fcb)->c_desc.cd_nameptr ? (const char *)FTOC(fcb)->c_desc.cd_nameptr : "", error);
                        error = 0;
                }
@@ -1627,7 +1760,8 @@ static OSErr SearchExtentRecord(
 {
        OSErr   err = noErr;
        u_int32_t       extentIndex;
 {
        OSErr   err = noErr;
        u_int32_t       extentIndex;
-       u_int32_t       numberOfExtents;
+       /* Set it to the HFS std value */
+       u_int32_t       numberOfExtents = kHFSExtentDensity;
        u_int32_t       numAllocationBlocks;
        Boolean foundExtent;
        
        u_int32_t       numAllocationBlocks;
        Boolean foundExtent;
        
@@ -1635,10 +1769,10 @@ static OSErr SearchExtentRecord(
        *noMoreExtents          = false;
        foundExtent                     = false;
 
        *noMoreExtents          = false;
        foundExtent                     = false;
 
-       if (vcb->vcbSigWord == kHFSPlusSigWord)
+       /* Override numberOfExtents for HFS+/HFSX */
+       if (vcb->vcbSigWord != kHFSSigWord) {
                numberOfExtents = kHFSPlusExtentDensity;
                numberOfExtents = kHFSPlusExtentDensity;
-       else
-               numberOfExtents = kHFSExtentDensity;
+       }
        
        for( extentIndex = 0; extentIndex < numberOfExtents; ++extentIndex )
        {
        
        for( extentIndex = 0; extentIndex < numberOfExtents; ++extentIndex )
        {
@@ -1810,6 +1944,7 @@ Exit:
 //
 //     Input:          vcb                                             -       the volume containing the extents
 //                             fcb                                             -       the file that owns the extents
 //
 //     Input:          vcb                                             -       the volume containing the extents
 //                             fcb                                             -       the file that owns the extents
+//                             deleted                                 -       whether or not the file is already deleted
 //                             extentFileKey                   -       pointer to extent key record (xkr)
 //                                             If the key length is 0, then the extents are actually part
 //                                             of the catalog record, stored in the FCB.
 //                             extentFileKey                   -       pointer to extent key record (xkr)
 //                                             If the key length is 0, then the extents are actually part
 //                                             of the catalog record, stored in the FCB.
@@ -1820,21 +1955,21 @@ Exit:
 //                             (other) = error from BTree
 //============================================================================
 
 //                             (other) = error from BTree
 //============================================================================
 
-static OSErr UpdateExtentRecord (
-       ExtendedVCB  *vcb,
-       FCB  *fcb,
-       const HFSPlusExtentKey  *extentFileKey,
-       const HFSPlusExtentRecord  extentData,
-       u_int32_t  extentBTreeHint)
+static OSErr UpdateExtentRecord (ExtendedVCB *vcb, FCB  *fcb, int deleted,
+                                                                const HFSPlusExtentKey  *extentFileKey,
+                                                                const HFSPlusExtentRecord  extentData,
+                                                                u_int32_t  extentBTreeHint) 
 {
     OSErr err = noErr;
        
        if (extentFileKey->keyLength == 0) {    // keyLength == 0 means the FCB's extent record
                BlockMoveData(extentData, fcb->fcbExtents, sizeof(HFSPlusExtentRecord));
 {
     OSErr err = noErr;
        
        if (extentFileKey->keyLength == 0) {    // keyLength == 0 means the FCB's extent record
                BlockMoveData(extentData, fcb->fcbExtents, sizeof(HFSPlusExtentRecord));
-               FTOC(fcb)->c_flag |= C_MODIFIED;
+               if (!deleted) {
+                       FTOC(fcb)->c_flag |= C_MODIFIED;
+               }
        }
        else {
        }
        else {
-               BTreeIterator * btIterator;
+               struct BTreeIterator *btIterator = NULL;
                FSBufferDescriptor btRecord;
                u_int16_t btRecordSize;
                FCB * btFCB;
                FSBufferDescriptor btRecord;
                u_int16_t btRecordSize;
                FCB * btFCB;
@@ -1844,8 +1979,11 @@ static OSErr UpdateExtentRecord (
                //      Need to find and change a record in Extents BTree
                //
                btFCB = GetFileControlBlock(vcb->extentsRefNum);
                //      Need to find and change a record in Extents BTree
                //
                btFCB = GetFileControlBlock(vcb->extentsRefNum);
-
-               MALLOC(btIterator, BTreeIterator *, sizeof(*btIterator), M_TEMP, M_WAITOK);
+               
+               MALLOC (btIterator, struct BTreeIterator*, sizeof(struct BTreeIterator), M_TEMP, M_WAITOK);
+               if (btIterator == NULL) {
+                       return memFullErr;  // translates to ENOMEM
+               }
                bzero(btIterator, sizeof(*btIterator));
 
                /*
                bzero(btIterator, sizeof(*btIterator));
 
                /*
@@ -1857,7 +1995,30 @@ static OSErr UpdateExtentRecord (
                 */
                lockflags = hfs_systemfile_lock(vcb, SFL_EXTENTS, HFS_EXCLUSIVE_LOCK);
 
                 */
                lockflags = hfs_systemfile_lock(vcb, SFL_EXTENTS, HFS_EXCLUSIVE_LOCK);
 
-               if (vcb->vcbSigWord == kHFSSigWord) {
+               /* HFS+/HFSX */
+               if (vcb->vcbSigWord != kHFSSigWord) {           //      HFS Plus volume
+                       HFSPlusExtentRecord     foundData;              // The extent data actually found
+
+                       BlockMoveData(extentFileKey, &btIterator->key, sizeof(HFSPlusExtentKey));
+
+                       btIterator->hint.index = 0;
+                       btIterator->hint.nodeNum = extentBTreeHint;
+
+                       btRecord.bufferAddress = &foundData;
+                       btRecord.itemSize = sizeof(HFSPlusExtentRecord);
+                       btRecord.itemCount = 1;
+
+                       err = BTSearchRecord(btFCB, btIterator, &btRecord, &btRecordSize, btIterator);
+       
+                       if (err == noErr) {
+                               BlockMoveData(extentData, &foundData, sizeof(HFSPlusExtentRecord));
+                               err = BTReplaceRecord(btFCB, btIterator, &btRecord, btRecordSize);
+                       }
+                       (void) BTFlushPath(btFCB);
+               }
+#if CONFIG_HFS_STD
+               else {
+                       /* HFS Standard */
                        HFSExtentKey *  key;                            // Actual extent key used on disk in HFS
                        HFSExtentRecord foundData;                      // The extent data actually found
 
                        HFSExtentKey *  key;                            // Actual extent key used on disk in HFS
                        HFSExtentRecord foundData;                      // The extent data actually found
 
@@ -1875,36 +2036,20 @@ static OSErr UpdateExtentRecord (
                        btRecord.itemCount = 1;
 
                        err = BTSearchRecord(btFCB, btIterator, &btRecord, &btRecordSize, btIterator);
                        btRecord.itemCount = 1;
 
                        err = BTSearchRecord(btFCB, btIterator, &btRecord, &btRecordSize, btIterator);
-                       
+
                        if (err == noErr)
                                err = HFSPlusToHFSExtents(extentData, (HFSExtentDescriptor *)&foundData);
 
                        if (err == noErr)
                                err = BTReplaceRecord(btFCB, btIterator, &btRecord, btRecordSize);
                        (void) BTFlushPath(btFCB);
                        if (err == noErr)
                                err = HFSPlusToHFSExtents(extentData, (HFSExtentDescriptor *)&foundData);
 
                        if (err == noErr)
                                err = BTReplaceRecord(btFCB, btIterator, &btRecord, btRecordSize);
                        (void) BTFlushPath(btFCB);
-               }
-               else {          //      HFS Plus volume
-                       HFSPlusExtentRecord     foundData;              // The extent data actually found
-
-                       BlockMoveData(extentFileKey, &btIterator->key, sizeof(HFSPlusExtentKey));
 
 
-                       btIterator->hint.index = 0;
-                       btIterator->hint.nodeNum = extentBTreeHint;
-
-                       btRecord.bufferAddress = &foundData;
-                       btRecord.itemSize = sizeof(HFSPlusExtentRecord);
-                       btRecord.itemCount = 1;
-
-                       err = BTSearchRecord(btFCB, btIterator, &btRecord, &btRecordSize, btIterator);
-       
-                       if (err == noErr) {
-                               BlockMoveData(extentData, &foundData, sizeof(HFSPlusExtentRecord));
-                               err = BTReplaceRecord(btFCB, btIterator, &btRecord, btRecordSize);
-                       }
-                       (void) BTFlushPath(btFCB);
                }
                }
+#endif
+
                hfs_systemfile_unlock(vcb, lockflags);
                hfs_systemfile_unlock(vcb, lockflags);
-               FREE(btIterator, M_TEMP);       
+
+               FREE(btIterator, M_TEMP);
        }
        
        return err;
        }
        
        return err;
@@ -1912,7 +2057,7 @@ static OSErr UpdateExtentRecord (
 
 
 
 
 
 
-
+#if CONFIG_HFS_STD
 static OSErr HFSPlusToHFSExtents(
        const HFSPlusExtentRecord       oldExtents,
        HFSExtentRecord         newExtents)
 static OSErr HFSPlusToHFSExtents(
        const HFSPlusExtentRecord       oldExtents,
        HFSExtentRecord         newExtents)
@@ -1931,14 +2076,14 @@ static OSErr HFSPlusToHFSExtents(
 
        #if DEBUG_BUILD
                if (oldExtents[3].startBlock || oldExtents[3].blockCount) {
 
        #if DEBUG_BUILD
                if (oldExtents[3].startBlock || oldExtents[3].blockCount) {
-                       DebugStr("\pExtentRecord with > 3 extents is invalid for HFS");
+                       DebugStr("ExtentRecord with > 3 extents is invalid for HFS");
                        err = fsDSIntErr;
                }
        #endif
        
        return err;
 }
                        err = fsDSIntErr;
                }
        #endif
        
        return err;
 }
-
+#endif
 
 
 
 
 
 
@@ -2001,7 +2146,6 @@ static Boolean ExtentsAreIntegral(
 //                             Called by BTOpenPath during volume mount
 //_________________________________________________________________________________
 
 //                             Called by BTOpenPath during volume mount
 //_________________________________________________________________________________
 
-__private_extern__
 Boolean NodesAreContiguous(
        ExtendedVCB     *vcb,
        FCB                     *fcb,
 Boolean NodesAreContiguous(
        ExtendedVCB     *vcb,
        FCB                     *fcb,