/*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
*
- * @APPLE_LICENSE_HEADER_START@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License"). You may not use this file except in compliance with the
- * License. Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
*
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
*
- * @APPLE_LICENSE_HEADER_END@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
-/*
- File: FileIDServices.c
-
- Contains: File ID manipulating routines.
-
- Version: HFS Plus 1.0
-
- Written by: Deric Horn
-
- Copyright: © 1996-1999 by Apple Computer, Inc., all rights reserved.
-
- File Ownership:
-
- DRI: Deric Horn
-
- Other Contact: xxx put other contact here xxx
-
- Technology: xxx put technology here xxx
-
- Writers:
-
- (JL) Jim Luther
- (msd) Mark Day
- (djb) Don Brady
- (DSH) Deric Horn
-
- Change History (most recent first):
- <MacOSX> 3/2/98 djb Fix extents corruption bug in MoveExtents (radar #2309434).
- <MacOSX> 11/20/98 djb Add support for UTF-8 names.
- <MacOSX> 4/2/98 djb Switch over to real BTree interface in MoveExtents and DeleteExtents.
- <MacOSX> 3/31/98 djb Sync up with final HFSVolumes.h header file.
-
- <CS21> 11/17/97 djb PrepareInputName routine now returns an error.
- <CS20> 11/13/97 djb Radar #2001699 ResolveFileID needs to use CMNotFound error.
- <CS19> 10/31/97 JL #2000184 - CreateFileThreadID and ExchangeFiles now return the
- WDCBRecPtr or NULL for external file systems. ExchangeFiles no
- longer returns length of FCB table to caller since that wasn't
- ever needed.
- <18> 10/23/97 DSH 1685058, Fix ExchangeFiles by invalidating the node cache before
- switching the files.
- <CS17> 10/19/97 msd Bug 1684586. GetCatInfo and SetCatInfo use only contentModDate.
- <CS16> 10/16/97 DSH Return badFidErr in ResolveFileID if LocateCatalogThread fails
- <CS15> 10/15/97 DSH CreateFileThreadID(), remap btExists to fidExists.
- <CS14> 9/7/97 djb Turn off some DebugStr calls.
- <CS13> 9/4/97 msd Remove call to PropertyExchangeObjects.
- <CS12> 8/14/97 djb Remove hard link support.
- <CS11> 7/18/97 msd Include LowMemPriv.h.
- <CS10> 7/16/97 DSH FilesInternal.i renamed FileMgrInternal.i to avoid name
- collision
- <CS9> 7/8/97 DSH Loading PrecompiledHeaders from define passed in on C line
- <CS8> 6/24/97 djb Add hard link support to ResolveFileID and CreateFileIDRef.
- <CS7> 6/20/97 msd Use contentModDate and attributeModDate fields instead of
- modifyDate.
- <CS6> 6/13/97 djb Switch over from PrepareOutputName to ConvertUnicodeToHFSName.
- PrepareInputName now takes an encoding.
- <CS5> 5/28/97 msd Move the declaration of FindFileName to FilesInternal.i.
- <CS4> 5/19/97 djb No longer need to invalidate vcbDirIDM field.
- <CS3> 5/16/97 msd In ExchangeFiles, change srcNamePtr from char * to StringPtr
- (fixes warnings).
- <CS2> 4/28/97 djb (DSH) Added VolumeWritable check back into CreateFileIDThread.
- <CS1> 4/24/97 djb first checked in
- <HFS23> 4/11/97 DSH Use extended VCB fields catalogRefNum, and extentsRefNum.
- <HFS22> 4/9/97 msd Rewrite CreateFileThreadID so that it properly handles
- pathnames, and doesn't overwrite the ioNamePtr. The data field
- of FindFileNameGlueRec points to a CatalogNodeData, not
- CatalogRecord.
- <HFS21> 4/4/97 djb Get in sync with volume format changes.
- <HFS20> 3/31/97 djb Change ClearMem to ClearMemory.
- <HFS19> 3/17/97 DSH C_FlushCache prototype to FilesInternal.h
- <HFS18> 3/5/97 msd ExchangeFiles needs to call PropertyExchangeObjects.
- <HFS17> 2/13/97 msd Fix MoveExtents and DeleteExtents to work with HFS+ extent
- records.
- <HFS16> 1/31/97 msd In MoveExtents, when a record isn't found and you want the next
- record in order, use the "next record" offset = 1 instead of
- "current record" offset = 0. DeleteExtents would always exit
- without doing anything because it was searching for an invalid
- key. Removed several DebugStrs that were used as cheap code
- coverage.
- <HFS15> 1/15/97 DSH Resolve wasn't passing the name back for HFS
- <HFS14> 1/13/97 djb LocateCatalogThread now passes back the thread record size.
- <HFS13> 1/11/97 DSH HFS+, fixed some Unicode/Pascal strings related bugs for use on
- HFS+ volumes.
- <HFS12> 1/9/97 DSH Fix ExchangeFiles extents
- <HFS11> 1/6/97 DSH pass VCB in CloseFile() routine.
- <HFS10> 1/6/97 djb Fixed ResolveFileID - it was not returning a directory ID!
- <HFS9> 1/3/97 msd Fix prototype for C_FlushCache. Fix prototype for
- TrashFileBlocks.
- <HFS8> 1/3/97 djb Integrate latest HFSVolumesPriv.h changes.
- <HFS7> 1/2/97 DSH C port of ExchangeFileIDs
- <HFS6> 12/20/96 djb Fixed bug in CreateFileID.
- <HFS5> 12/19/96 DSH All refs to VCB are now refs to ExtendedVCB
- <HFS4> 12/19/96 msd Use kFileThreadExistsMask (from HFSVolumesPriv.h) instead of
- kFileThreadMask (from FilesInternal.h) since the latter was
- incorrectly defined and has now been removed.
- <HFS3> 12/19/96 djb Updated for new B-tree Manager interface.
- <HFS2> 12/18/96 msd GetFileThreadID was using a bitwise-OR (|) instead of
- bitwise-AND (&) to test for a bit being set.
- <HFS1> 12/12/96 DSH first checked in
-
-*/
#include "../../hfs_macos_defs.h"
#include "../../hfs_format.h"
#include "../headers/FileMgrInternal.h"
#include "../headers/HFSUnicodeWrappers.h"
#include "../headers/CatalogPrivate.h"
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <libkern/libkern.h>
struct ExtentsRecBuffer {
- ExtentKey extentKey;
+ ExtentKey extentKey;
ExtentRecord extentData;
};
typedef struct ExtentsRecBuffer ExtentsRecBuffer;
-OSErr CreateFileID( ExtendedVCB *vcb, HFSCatalogNodeID fileID, CatalogName *name, HFSCatalogNodeID *threadID );
-OSErr GetFileThreadID( ExtendedVCB *vcb, HFSCatalogNodeID id, const CatalogName *name, Boolean isHFSPlus, UInt32 *threadID );
+static u_int32_t CheckExtents( void *extents, u_int32_t blocks, Boolean isHFSPlus );
+static OSErr DeleteExtents( ExtendedVCB *vcb, u_int32_t fileNumber, int quitEarly, u_int8_t forkType, Boolean isHFSPlus );
+static OSErr MoveExtents( ExtendedVCB *vcb, u_int32_t srcFileID, u_int32_t destFileID, int quitEarly, u_int8_t forkType, Boolean isHFSPlus );
-UInt32 CheckExtents( void *extents, UInt32 blocks, Boolean isHFSPlus );
-OSErr DeleteExtents( ExtendedVCB *vcb, UInt32 fileNumber, Boolean isHFSPlus );
-OSErr MoveExtents( ExtendedVCB *vcb, UInt32 srcFileID, UInt32 destFileID, Boolean isHFSPlus );
-void CopyCatalogNodeInfo( CatalogRecord *src, CatalogRecord *dest );
-void CopyBigCatalogNodeInfo( CatalogRecord *src, CatalogRecord *dest );
+#if CONFIG_HFS_STD
+static void CopyCatalogNodeInfo( CatalogRecord *src, CatalogRecord *dest );
+#endif
-void CopyExtentInfo( ExtentKey *key, ExtentRecord *data, ExtentsRecBuffer *buffer, UInt16 bufferCount );
-extern void TrashFileBlocks( ExtendedVCB *vcb, UInt32 fileNumber );
+static void CopyBigCatalogNodeInfo( CatalogRecord *src, CatalogRecord *dest );
+static void CopyExtentInfo( ExtentKey *key, ExtentRecord *data, ExtentsRecBuffer *buffer, u_int16_t bufferCount );
+/*
+ * This function moves the overflow extents associated with srcID into the file associated with dstID.
+ * We should have already verified that 'srcID' has overflow extents. So now we move all of the overflow
+ * extent records.
+ */
+OSErr MoveData( ExtendedVCB *vcb, HFSCatalogNodeID srcID, HFSCatalogNodeID destID, int rsrc) {
+
+ OSErr err;
+
+ /*
+ * Only the source file should have extents, so we just track those.
+ * We operate on the fork represented by the open FD that was used to call into this
+ * function
+ */
+ if (rsrc) {
+ /* Copy the extent overflow blocks. */
+ err = MoveExtents( vcb, srcID, destID, 1, (u_int8_t)0xff, 1);
+ if ( err != noErr ) {
+ if ( err != dskFulErr ) {
+ return( err );
+ }
+ /*
+ * In case of error, we would have probably run into problems
+ * growing the extents b-tree. Since the move is actually a copy + delete
+ * just delete the new entries. Same for below.
+ */
+ err = DeleteExtents( vcb, destID, 1, (u_int8_t)0xff, 1);
+ ReturnIfError( err ); // we are doomed. Just QUIT!
+ goto FlushAndReturn;
+ }
+ }
+ else {
+ /* Copy the extent overflow blocks. */
+ err = MoveExtents( vcb, srcID, destID, 1, 0, 1);
+ if ( err != noErr ) {
+ if ( err != dskFulErr ) {
+ return( err );
+ }
+ err = DeleteExtents( vcb, destID, 1, 0, 1);
+ ReturnIfError( err ); // we are doomed. Just QUIT!
+ goto FlushAndReturn;
+ }
+ }
+
+FlushAndReturn:
+ /* Write out the catalog and extent overflow B-Tree changes */
+ err = FlushCatalog( vcb );
+ err = FlushExtentFile( vcb );
+
+ return( err );
+}
-OSErr ExchangeFileIDs( ExtendedVCB *vcb, ConstUTF8Param srcName, ConstUTF8Param destName, HFSCatalogNodeID srcID, HFSCatalogNodeID destID, UInt32 srcHint, UInt32 destHint )
+OSErr ExchangeFileIDs( ExtendedVCB *vcb, ConstUTF8Param srcName, ConstUTF8Param destName, HFSCatalogNodeID srcID, HFSCatalogNodeID destID, u_int32_t srcHint, u_int32_t destHint )
{
- CatalogKey srcKey; // 518 bytes
+ CatalogKey srcKey; // 518 bytes
+ CatalogKey destKey; // 518 bytes
CatalogRecord srcData; // 520 bytes
- CatalogKey destKey; // 518 bytes
CatalogRecord destData; // 520 bytes
CatalogRecord swapData; // 520 bytes
- SInt16 numSrcExtentBlocks;
- SInt16 numDestExtentBlocks;
- UInt32 textEncoding;
- OSErr err;
- Boolean isHFSPlus = ( vcb->vcbSigWord == kHFSPlusSigWord );
-
- TrashCatalogIterator(vcb, srcID); // invalidate any iterators for this parentID
- TrashCatalogIterator(vcb, destID); // invalidate any iterators for this parentID
+ int16_t numSrcExtentBlocks;
+ int16_t numDestExtentBlocks;
+ OSErr err;
+ Boolean isHFSPlus = ( vcb->vcbSigWord == kHFSPlusSigWord );
- err = BuildCatalogKeyUTF8(vcb, srcID, srcName, kUndefinedStrLen, &srcKey, &textEncoding);
+ err = BuildCatalogKeyUTF8(vcb, srcID, srcName, kUndefinedStrLen, &srcKey, NULL);
ReturnIfError(err);
- err = BuildCatalogKeyUTF8(vcb, destID, destName, kUndefinedStrLen, &destKey, &textEncoding);
+ err = BuildCatalogKeyUTF8(vcb, destID, destName, kUndefinedStrLen, &destKey, NULL);
ReturnIfError(err);
if ( isHFSPlus )
//-- Step 2: Exchange the Extent key in the extent file
//-- Exchange the extents key in the extent file
- err = DeleteExtents( vcb, kHFSBogusExtentFileID, isHFSPlus );
+ err = DeleteExtents( vcb, kHFSBogusExtentFileID, 0, 0, isHFSPlus );
ReturnIfError( err );
if ( numSrcExtentBlocks && numDestExtentBlocks ) // if both files have extents
{
//-- Change the source extents file ids to our known bogus value
- err = MoveExtents( vcb, srcData.hfsPlusFile.fileID, kHFSBogusExtentFileID, isHFSPlus );
+ err = MoveExtents( vcb, srcData.hfsPlusFile.fileID, kHFSBogusExtentFileID, 0,0, isHFSPlus );
if ( err != noErr )
{
- if ( err != dskFulErr )
+ if ( err != dskFulErr ) {
return( err );
- else
- goto ExUndo1a;
+ }
+ else {
+ err = DeleteExtents( vcb, kHFSBogusExtentFileID, 0, 0, isHFSPlus );
+ ReturnIfError( err ); // we are doomed. Just QUIT!
+
+ err = FlushCatalog( vcb ); // flush the catalog
+ err = FlushExtentFile( vcb ); // flush the extent file (unneeded for common case, but it's cheap)
+ return( dskFulErr );
+ }
}
//-- Change the destination extents file id's to the source id's
- err = MoveExtents( vcb, destData.hfsPlusFile.fileID, srcData.hfsPlusFile.fileID, isHFSPlus );
+ err = MoveExtents( vcb, destData.hfsPlusFile.fileID, srcData.hfsPlusFile.fileID, 0, 0, isHFSPlus );
if ( err != noErr )
{
if ( err != dskFulErr )
return( err );
-ExUndo2aPlus: err = DeleteExtents( vcb, srcData.hfsPlusFile.fileID, isHFSPlus );
+ExUndo2aPlus: err = DeleteExtents( vcb, srcData.hfsPlusFile.fileID, 0, 0, isHFSPlus );
ReturnIfError( err ); // we are doomed. Just QUIT!
- err = MoveExtents( vcb, kHFSBogusExtentFileID, srcData.hfsPlusFile.fileID, isHFSPlus ); // Move the extents back
+ err = MoveExtents( vcb, kHFSBogusExtentFileID, srcData.hfsPlusFile.fileID, 0, 0, isHFSPlus ); // Move the extents back
ReturnIfError( err ); // we are doomed. Just QUIT!
- goto ExUndo1a;
+ err = DeleteExtents( vcb, kHFSBogusExtentFileID, 0, 0, isHFSPlus );
+ ReturnIfError( err ); // we are doomed. Just QUIT!
+
+ err = FlushCatalog( vcb ); // flush the catalog
+ err = FlushExtentFile( vcb ); // flush the extent file (unneeded for common case, but it's cheap)
+ return( dskFulErr );
+
}
//-- Change the bogus extents file id's to the dest id's
- err = MoveExtents( vcb, kHFSBogusExtentFileID, destData.hfsPlusFile.fileID, isHFSPlus );
+ err = MoveExtents( vcb, kHFSBogusExtentFileID, destData.hfsPlusFile.fileID, 0, 0, isHFSPlus );
if ( err != noErr )
{
if ( err != dskFulErr )
return( err );
- err = DeleteExtents( vcb, destData.hfsPlusFile.fileID, isHFSPlus );
+ err = DeleteExtents( vcb, destData.hfsPlusFile.fileID, 0, 0, isHFSPlus );
ReturnIfError( err ); // we are doomed. Just QUIT!
- err = MoveExtents( vcb, srcData.hfsPlusFile.fileID, destData.hfsPlusFile.fileID, isHFSPlus ); // Move the extents back
+ err = MoveExtents( vcb, srcData.hfsPlusFile.fileID, destData.hfsPlusFile.fileID, 0, 0, isHFSPlus ); // Move the extents back
ReturnIfError( err ); // we are doomed. Just QUIT!
goto ExUndo2aPlus;
}
else if ( numSrcExtentBlocks ) // just the source file has extents
{
- err = MoveExtents( vcb, srcData.hfsPlusFile.fileID, destData.hfsPlusFile.fileID, isHFSPlus );
+ err = MoveExtents( vcb, srcData.hfsPlusFile.fileID, destData.hfsPlusFile.fileID, 0, 0, isHFSPlus );
if ( err != noErr )
{
if ( err != dskFulErr )
return( err );
- err = DeleteExtents( vcb, srcData.hfsPlusFile.fileID, isHFSPlus );
+ err = DeleteExtents( vcb, srcData.hfsPlusFile.fileID, 0, 0, isHFSPlus );
ReturnIfError( err ); // we are doomed. Just QUIT!
goto FlushAndReturn;
}
else if ( numDestExtentBlocks ) // just the destination file has extents
{
- err = MoveExtents( vcb, destData.hfsPlusFile.fileID, srcData.hfsPlusFile.fileID, isHFSPlus );
+ err = MoveExtents( vcb, destData.hfsPlusFile.fileID, srcData.hfsPlusFile.fileID, 0, 0, isHFSPlus );
if ( err != noErr )
{
if ( err != dskFulErr )
return( err );
- err = DeleteExtents( vcb, destData.hfsPlusFile.fileID, isHFSPlus );
+ err = DeleteExtents( vcb, destData.hfsPlusFile.fileID, 0, 0, isHFSPlus );
ReturnIfError( err ); // we are doomed. Just QUIT!
goto FlushAndReturn;
err = ReplaceBTreeRecord( vcb->catalogRefNum, &destKey, destHint, &destData, sizeof(HFSPlusCatalogFile), &destHint );
ReturnIfError( err );
}
+#if CONFIG_HFS_STD
else // HFS //
{
//-- Step 1: Check the catalog nodes for extents
//-- Step 2: Exchange the Extent key in the extent file
//-- Exchange the extents key in the extent file
- err = DeleteExtents( vcb, kHFSBogusExtentFileID, isHFSPlus );
+ err = DeleteExtents( vcb, kHFSBogusExtentFileID, 0, 0, isHFSPlus );
ReturnIfError( err );
if ( numSrcExtentBlocks && numDestExtentBlocks ) // if both files have extents
{
//-- Change the source extents file ids to our known bogus value
- err = MoveExtents( vcb, srcData.hfsFile.fileID, kHFSBogusExtentFileID, isHFSPlus );
+ err = MoveExtents( vcb, srcData.hfsFile.fileID, kHFSBogusExtentFileID, 0, 0, isHFSPlus );
if ( err != noErr )
{
if ( err != dskFulErr )
return( err );
-ExUndo1a: err = DeleteExtents( vcb, kHFSBogusExtentFileID, isHFSPlus );
+ExUndo1a: err = DeleteExtents( vcb, kHFSBogusExtentFileID, 0, 0, isHFSPlus );
ReturnIfError( err ); // we are doomed. Just QUIT!
err = FlushCatalog( vcb ); // flush the catalog
}
//-- Change the destination extents file id's to the source id's
- err = MoveExtents( vcb, destData.hfsFile.fileID, srcData.hfsFile.fileID, isHFSPlus );
+ err = MoveExtents( vcb, destData.hfsFile.fileID, srcData.hfsFile.fileID, 0, 0, isHFSPlus );
if ( err != noErr )
{
if ( err != dskFulErr )
return( err );
-ExUndo2a: err = DeleteExtents( vcb, srcData.hfsFile.fileID, isHFSPlus );
+ExUndo2a: err = DeleteExtents( vcb, srcData.hfsFile.fileID, 0, 0, isHFSPlus );
ReturnIfError( err ); // we are doomed. Just QUIT!
- err = MoveExtents( vcb, kHFSBogusExtentFileID, srcData.hfsFile.fileID, isHFSPlus ); // Move the extents back
+ err = MoveExtents( vcb, kHFSBogusExtentFileID, srcData.hfsFile.fileID, 0, 0, isHFSPlus ); // Move the extents back
ReturnIfError( err ); // we are doomed. Just QUIT!
goto ExUndo1a;
}
//-- Change the bogus extents file id's to the dest id's
- err = MoveExtents( vcb, kHFSBogusExtentFileID, destData.hfsFile.fileID, isHFSPlus );
+ err = MoveExtents( vcb, kHFSBogusExtentFileID, destData.hfsFile.fileID, 0, 0, isHFSPlus );
if ( err != noErr )
{
if ( err != dskFulErr )
return( err );
- err = DeleteExtents( vcb, destData.hfsFile.fileID, isHFSPlus );
+ err = DeleteExtents( vcb, destData.hfsFile.fileID, 0, 0, isHFSPlus );
ReturnIfError( err ); // we are doomed. Just QUIT!
- err = MoveExtents( vcb, srcData.hfsFile.fileID, destData.hfsFile.fileID, isHFSPlus ); // Move the extents back
+ err = MoveExtents( vcb, srcData.hfsFile.fileID, destData.hfsFile.fileID, 0, 0, isHFSPlus ); // Move the extents back
ReturnIfError( err ); // we are doomed. Just QUIT!
goto ExUndo2a;
}
else if ( numSrcExtentBlocks ) // just the source file has extents
{
- err = MoveExtents( vcb, srcData.hfsFile.fileID, destData.hfsFile.fileID, isHFSPlus );
+ err = MoveExtents( vcb, srcData.hfsFile.fileID, destData.hfsFile.fileID, 0, 0, isHFSPlus );
if ( err != noErr )
{
if ( err != dskFulErr )
return( err );
- err = DeleteExtents( vcb, srcData.hfsFile.fileID, isHFSPlus );
+ err = DeleteExtents( vcb, srcData.hfsFile.fileID, 0, 0, isHFSPlus );
ReturnIfError( err ); // we are doomed. Just QUIT!
goto FlushAndReturn;
}
else if ( numDestExtentBlocks ) // just the destination file has extents
{
- err = MoveExtents( vcb, destData.hfsFile.fileID, srcData.hfsFile.fileID, isHFSPlus );
+ err = MoveExtents( vcb, destData.hfsFile.fileID, srcData.hfsFile.fileID, 0, 0, isHFSPlus );
if ( err != noErr )
{
if ( err != dskFulErr )
return( err );
- err = DeleteExtents( vcb, destData.hfsFile.fileID, isHFSPlus );
+ err = DeleteExtents( vcb, destData.hfsFile.fileID, 0, 0, isHFSPlus );
ReturnIfError( err ); // we are doomed. Just QUIT!
goto FlushAndReturn;
err = ReplaceBTreeRecord( vcb->catalogRefNum, &destKey, destHint, &destData, sizeof(HFSCatalogFile), &destHint );
ReturnIfError( err );
}
-
+#endif
+
err = noErr;
//-- Step 4: Error Handling section
}
-void CopyCatalogNodeInfo( CatalogRecord *src, CatalogRecord *dest )
+#if CONFIG_HFS_STD
+static void CopyCatalogNodeInfo( CatalogRecord *src, CatalogRecord *dest )
{
-// dest->hfsFile.filStBlk = src->hfsFile.filStBlk;
dest->hfsFile.dataLogicalSize = src->hfsFile.dataLogicalSize;
dest->hfsFile.dataPhysicalSize = src->hfsFile.dataPhysicalSize;
-// dest->hfsFile.filRStBlk = src->hfsFile.filRStBlk;
dest->hfsFile.rsrcLogicalSize = src->hfsFile.rsrcLogicalSize;
dest->hfsFile.rsrcPhysicalSize = src->hfsFile.rsrcPhysicalSize;
dest->hfsFile.modifyDate = src->hfsFile.modifyDate;
BlockMoveData( src->hfsFile.dataExtents, dest->hfsFile.dataExtents, sizeof(HFSExtentRecord) );
BlockMoveData( src->hfsFile.rsrcExtents, dest->hfsFile.rsrcExtents, sizeof(HFSExtentRecord) );
}
+#endif
-void CopyBigCatalogNodeInfo( CatalogRecord *src, CatalogRecord *dest )
+static void CopyBigCatalogNodeInfo( CatalogRecord *src, CatalogRecord *dest )
{
BlockMoveData( &src->hfsPlusFile.dataFork, &dest->hfsPlusFile.dataFork, sizeof(HFSPlusForkData) );
BlockMoveData( &src->hfsPlusFile.resourceFork, &dest->hfsPlusFile.resourceFork, sizeof(HFSPlusForkData) );
}
-OSErr MoveExtents( ExtendedVCB *vcb, UInt32 srcFileID, UInt32 destFileID, Boolean isHFSPlus )
+static OSErr MoveExtents( ExtendedVCB *vcb, u_int32_t srcFileID, u_int32_t destFileID, int quitEarly, u_int8_t forkType, Boolean isHFSPlus )
{
FCB * fcb;
ExtentsRecBuffer extentsBuffer[kNumExtentsToCache];
ExtentKey * extentKeyPtr;
ExtentRecord extentData;
- BTreeIterator btIterator;
+ struct BTreeIterator *btIterator = NULL;
+ struct BTreeIterator *tmpIterator = NULL;
FSBufferDescriptor btRecord;
- UInt16 btKeySize;
- UInt16 btRecordSize;
- SInt16 i, j;
+ u_int16_t btKeySize;
+ u_int16_t btRecordSize;
+ int16_t i, j;
OSErr err;
+ MALLOC (btIterator, struct BTreeIterator*, sizeof(struct BTreeIterator), M_TEMP, M_WAITOK);
+ if (btIterator == NULL) {
+ return memFullErr; // translates to ENOMEM
+ }
+
+
+ MALLOC (tmpIterator, struct BTreeIterator*, sizeof(struct BTreeIterator), M_TEMP, M_WAITOK);
+ if (tmpIterator == NULL) {
+ FREE (btIterator, M_TEMP);
+ return memFullErr; // translates to ENOMEM
+ }
+
+ bzero(btIterator, sizeof(*btIterator));
+ bzero (tmpIterator, sizeof(*tmpIterator));
+
fcb = GetFileControlBlock(vcb->extentsRefNum);
- (void) BTInvalidateHint(&btIterator);
- extentKeyPtr = (ExtentKey*) &btIterator.key;
+ (void) BTInvalidateHint(btIterator);
+ extentKeyPtr = (ExtentKey*) &btIterator->key;
btRecord.bufferAddress = &extentData;
btRecord.itemCount = 1;
btKeySize = sizeof(HFSPlusExtentKey);
extentKeyPtr->hfsPlus.keyLength = kHFSPlusExtentKeyMaximumLength;
- extentKeyPtr->hfsPlus.forkType = 0;
+ extentKeyPtr->hfsPlus.forkType = forkType;
extentKeyPtr->hfsPlus.pad = 0;
extentKeyPtr->hfsPlus.fileID = srcFileID;
extentKeyPtr->hfsPlus.startBlock = 0;
}
+#if CONFIG_HFS_STD
else {
btRecord.itemSize = sizeof(HFSExtentRecord);
btKeySize = sizeof(HFSExtentKey);
extentKeyPtr->hfs.fileID = srcFileID;
extentKeyPtr->hfs.startBlock = 0;
}
+#else
+ else {
+ return cmBadNews;
+ }
+#endif
//
// We do an initial BTSearchRecord to position the BTree's iterator just before any extent
// we found, so that BTIterateRecord would get the next one (the first we haven't processed).
//
- err = BTSearchRecord(fcb, &btIterator, kInvalidMRUCacheKey, &btRecord, &btRecordSize, &btIterator);
+ err = BTSearchRecord(fcb, btIterator, &btRecord, &btRecordSize, btIterator);
// We expect a btNotFound here, since there shouldn't be an extent record with FABN = 0.
if (err != btNotFound)
{
if ( DEBUG_BUILD )
- DebugStr("\pUnexpected error from SearchBTreeRecord");
+ DebugStr("Unexpected error from SearchBTreeRecord");
if (err == noErr) // If we found such a bogus extent record, then the tree is really messed up
err = cmBadNews; // so return an error that conveys the disk is hosed.
+ FREE (tmpIterator, M_TEMP);
+ FREE (btIterator, M_TEMP);
return err;
}
for ( i=0 ; i<kNumExtentsToCache ; i++ )
{
- HFSCatalogNodeID foundFileID;
-
- err = BTIterateRecord(fcb, kBTreeNextRecord, &btIterator, &btRecord, &btRecordSize);
+ HFSCatalogNodeID foundFileID = 0;
+
+ err = BTIterateRecord(fcb, kBTreeNextRecord, btIterator, &btRecord, &btRecordSize);
if ( err == btNotFound ) // Did we run out of extent records in the extents tree?
break; // if xkrFNum(A0) is cleared on this error, then this test is bogus!
- else if ( err != noErr )
+ else if ( err != noErr ) {
+ FREE (btIterator, M_TEMP);
+ FREE (tmpIterator, M_TEMP);
return( err ); // must be ioError
-
- foundFileID = isHFSPlus ? extentKeyPtr->hfsPlus.fileID : extentKeyPtr->hfs.fileID;
- if ( foundFileID == srcFileID )
- {
+ }
+ if (isHFSPlus) {
+ foundFileID = extentKeyPtr->hfsPlus.fileID;
+ }
+#if CONFIG_HFS_STD
+ else {
+ foundFileID = extentKeyPtr->hfs.fileID;
+ }
+#endif
+ if ( foundFileID == srcFileID ) {
+ /* Check if we need to quit early. */
+ if (quitEarly && isHFSPlus) {
+ if (extentKeyPtr->hfsPlus.forkType != forkType) {
+ break;
+ }
+ }
CopyExtentInfo(extentKeyPtr, &extentData, extentsBuffer, i);
}
- else
- {
+ else{
+ /* The fileID's are of a different file. We're done here. */
break;
}
}
+
+
//-- edit each extent key, and reinsert each extent record in the extent file
if (isHFSPlus)
btRecordSize = sizeof(HFSPlusExtentRecord);
+#if CONFIG_HFS_STD
else
btRecordSize = sizeof(HFSExtentRecord);
-
+#endif
+
for ( j=0 ; j<i ; j++ )
{
- BTreeIterator tmpIterator;
if (isHFSPlus)
extentsBuffer[j].extentKey.hfsPlus.fileID = destFileID; // change only the id in the key to dest ID
+#if CONFIG_HFS_STD
else
extentsBuffer[j].extentKey.hfs.fileID = destFileID; // change only the id in the key to dest ID
-
+#endif
+
// get iterator and buffer descriptor ready...
- (void) BTInvalidateHint(&tmpIterator);
- BlockMoveData(&(extentsBuffer[j].extentKey), &tmpIterator.key, btKeySize);
+ (void) BTInvalidateHint(tmpIterator);
+ BlockMoveData(&(extentsBuffer[j].extentKey), &tmpIterator->key, btKeySize);
btRecord.bufferAddress = &(extentsBuffer[j].extentData);
- err = BTInsertRecord(fcb, &tmpIterator, &btRecord, btRecordSize);
- if ( err != noErr )
- { // parse the error
+ err = BTInsertRecord(fcb, tmpIterator, &btRecord, btRecordSize);
+ if ( err != noErr ) {
+ /* Parse the error and free iterators */
+ FREE (btIterator, M_TEMP);
+ FREE (tmpIterator, M_TEMP);
if ( err == btExists )
{
- if ( DEBUG_BUILD )
- DebugStr("\pCan't insert record -- already exists");
+ if ( DEBUG_BUILD ) {
+ DebugStr("Can't insert record -- already exists");
+ }
return( cmBadNews );
}
- else
+ else {
return( err );
+ }
}
}
-
+
//-- okay, done with this buffered batch, go get the next set of extent records
// If our buffer is not full, we must be done, or recieved an error
if ( i != kNumExtentsToCache ) // if the buffer is not full, we must be done
{
- err = DeleteExtents( vcb, srcFileID, isHFSPlus ); // Now delete all the extent entries with the sourceID
+ err = DeleteExtents( vcb, srcFileID, quitEarly, forkType, isHFSPlus ); // Now delete all the extent entries with the sourceID
if ( DEBUG_BUILD && err != noErr )
- DebugStr("\pError from DeleteExtents");
+ DebugStr("Error from DeleteExtents");
break; // we're done!
}
} while ( true );
+ FREE (tmpIterator, M_TEMP);
+ FREE (btIterator, M_TEMP);
+
return( err );
}
-void CopyExtentInfo( ExtentKey *key, ExtentRecord *data, ExtentsRecBuffer *buffer, UInt16 bufferCount )
+static void CopyExtentInfo( ExtentKey *key, ExtentRecord *data, ExtentsRecBuffer *buffer, u_int16_t bufferCount )
{
BlockMoveData( key, &(buffer[bufferCount].extentKey), sizeof( ExtentKey ) );
BlockMoveData( data, &(buffer[bufferCount].extentData), sizeof( ExtentRecord ) );
//-- Delete all extents in extent file that have the ID given.
-OSErr DeleteExtents( ExtendedVCB *vcb, UInt32 fileID, Boolean isHFSPlus )
+static OSErr DeleteExtents( ExtendedVCB *vcb, u_int32_t fileID, int quitEarly, u_int8_t forkType, Boolean isHFSPlus )
{
FCB * fcb;
ExtentKey * extentKeyPtr;
ExtentRecord extentData;
- BTreeIterator btIterator;
+ struct BTreeIterator *btIterator = NULL;
+ struct BTreeIterator *tmpIterator = NULL;
FSBufferDescriptor btRecord;
- UInt16 btRecordSize;
+ u_int16_t btRecordSize;
OSErr err;
+ MALLOC (btIterator, struct BTreeIterator*, sizeof(struct BTreeIterator),
+ M_TEMP, M_WAITOK | M_ZERO);
+
+ MALLOC (tmpIterator, struct BTreeIterator*, sizeof(struct BTreeIterator),
+ M_TEMP, M_WAITOK | M_ZERO);
+
fcb = GetFileControlBlock(vcb->extentsRefNum);
- (void) BTInvalidateHint(&btIterator);
- extentKeyPtr = (ExtentKey*) &btIterator.key;
+ (void) BTInvalidateHint(btIterator);
+ extentKeyPtr = (ExtentKey*) &btIterator->key;
btRecord.bufferAddress = &extentData;
btRecord.itemCount = 1;
btRecord.itemSize = sizeof(HFSPlusExtentRecord);
extentKeyPtr->hfsPlus.keyLength = kHFSPlusExtentKeyMaximumLength;
- extentKeyPtr->hfsPlus.forkType = 0;
+ extentKeyPtr->hfsPlus.forkType = forkType;
extentKeyPtr->hfsPlus.pad = 0;
extentKeyPtr->hfsPlus.fileID = fileID;
extentKeyPtr->hfsPlus.startBlock = 0;
}
+#if CONFIG_HFS_STD
else {
btRecord.itemSize = sizeof(HFSExtentRecord);
extentKeyPtr->hfs.keyLength = kHFSExtentKeyMaximumLength;
- extentKeyPtr->hfs.forkType = 0;
+ extentKeyPtr->hfs.forkType = forkType;
extentKeyPtr->hfs.fileID = fileID;
extentKeyPtr->hfs.startBlock = 0;
}
+#else
+ else {
+ err = cmBadNews;
+ goto exit;
+ }
+#endif
- err = BTSearchRecord(fcb, &btIterator, kInvalidMRUCacheKey, &btRecord, &btRecordSize, &btIterator);
+ err = BTSearchRecord(fcb, btIterator, &btRecord, &btRecordSize, btIterator);
if ( err != btNotFound )
{
if (err == noErr) { // Did we find a bogus extent record?
err = cmBadNews; // Yes, so indicate things are messed up.
}
-
- return err; // Got some unexpected error, so return it
+
+ goto exit;
}
do
{
- BTreeIterator tmpIterator;
- HFSCatalogNodeID foundFileID;
+ HFSCatalogNodeID foundFileID = 0;
- err = BTIterateRecord(fcb, kBTreeNextRecord, &btIterator, &btRecord, &btRecordSize);
+ err = BTIterateRecord(fcb, kBTreeNextRecord, btIterator, &btRecord, &btRecordSize);
if ( err != noErr )
{
if (err == btNotFound) // If we hit the end of the BTree
break; // We're done now.
}
-
- foundFileID = isHFSPlus ? extentKeyPtr->hfsPlus.fileID : extentKeyPtr->hfs.fileID;
- if ( foundFileID != fileID )
+ if (isHFSPlus) {
+ foundFileID = extentKeyPtr->hfsPlus.fileID;
+ }
+#if CONFIG_HFS_STD
+ else {
+ foundFileID = extentKeyPtr->hfs.fileID;
+ }
+#endif
+
+ if ( foundFileID != fileID ) {
break; // numbers don't match, we must be done
-
- tmpIterator = btIterator;
- err = BTDeleteRecord( fcb, &tmpIterator );
+ }
+ if (quitEarly && isHFSPlus) {
+ /* If we're only deleting one type of fork, then quit early if it doesn't match */
+ if (extentKeyPtr->hfsPlus.forkType != forkType) {
+ break;
+ }
+ }
+
+ *tmpIterator = *btIterator;
+ err = BTDeleteRecord( fcb, tmpIterator );
if (err != noErr)
break;
} while ( true );
+
+exit:
+ FREE (tmpIterator, M_TEMP);
+ FREE (btIterator, M_TEMP);
+
return( err );
}
// Check if there are extents represented in the extents overflow file.
-UInt32 CheckExtents( void *extents, UInt32 totalBlocks, Boolean isHFSPlus )
+static u_int32_t CheckExtents( void *extents, u_int32_t totalBlocks, Boolean isHFSPlus )
{
- UInt32 extentAllocationBlocks;
- UInt16 i;
+ u_int32_t extentAllocationBlocks;
+ u_int16_t i;
if ( totalBlocks == 0 )
return( 0 );
}
}
+#if CONFIG_HFS_STD
else
{
for ( i = 0 ; i < kHFSExtentDensity ; i++ )
return( 0 );
}
}
+#endif
return( extentAllocationBlocks );
}