X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/0b4e3aa066abc0728aacb4bbeb86f53f9737156e..7e41aa883dd258f888d0470250eead40a53ef1f5:/bsd/hfs/hfscommon/Catalog/FileIDsServices.c diff --git a/bsd/hfs/hfscommon/Catalog/FileIDsServices.c b/bsd/hfs/hfscommon/Catalog/FileIDsServices.c index 43cdd2a22..fa7e210d0 100644 --- a/bsd/hfs/hfscommon/Catalog/FileIDsServices.c +++ b/bsd/hfs/hfscommon/Catalog/FileIDsServices.c @@ -1,124 +1,30 @@ /* - * 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): - 3/2/98 djb Fix extents corruption bug in MoveExtents (radar #2309434). - 11/20/98 djb Add support for UTF-8 names. - 4/2/98 djb Switch over to real BTree interface in MoveExtents and DeleteExtents. - 3/31/98 djb Sync up with final HFSVolumes.h header file. - - 11/17/97 djb PrepareInputName routine now returns an error. - 11/13/97 djb Radar #2001699 ResolveFileID needs to use CMNotFound error. - 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. - 10/19/97 msd Bug 1684586. GetCatInfo and SetCatInfo use only contentModDate. - 10/16/97 DSH Return badFidErr in ResolveFileID if LocateCatalogThread fails - 10/15/97 DSH CreateFileThreadID(), remap btExists to fidExists. - 9/7/97 djb Turn off some DebugStr calls. - 9/4/97 msd Remove call to PropertyExchangeObjects. - 8/14/97 djb Remove hard link support. - 7/18/97 msd Include LowMemPriv.h. - 7/16/97 DSH FilesInternal.i renamed FileMgrInternal.i to avoid name - collision - 7/8/97 DSH Loading PrecompiledHeaders from define passed in on C line - 6/24/97 djb Add hard link support to ResolveFileID and CreateFileIDRef. - 6/20/97 msd Use contentModDate and attributeModDate fields instead of - modifyDate. - 6/13/97 djb Switch over from PrepareOutputName to ConvertUnicodeToHFSName. - PrepareInputName now takes an encoding. - 5/28/97 msd Move the declaration of FindFileName to FilesInternal.i. - 5/19/97 djb No longer need to invalidate vcbDirIDM field. - 5/16/97 msd In ExchangeFiles, change srcNamePtr from char * to StringPtr - (fixes warnings). - 4/28/97 djb (DSH) Added VolumeWritable check back into CreateFileIDThread. - 4/24/97 djb first checked in - 4/11/97 DSH Use extended VCB fields catalogRefNum, and extentsRefNum. - 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. - 4/4/97 djb Get in sync with volume format changes. - 3/31/97 djb Change ClearMem to ClearMemory. - 3/17/97 DSH C_FlushCache prototype to FilesInternal.h - 3/5/97 msd ExchangeFiles needs to call PropertyExchangeObjects. - 2/13/97 msd Fix MoveExtents and DeleteExtents to work with HFS+ extent - records. - 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. - 1/15/97 DSH Resolve wasn't passing the name back for HFS - 1/13/97 djb LocateCatalogThread now passes back the thread record size. - 1/11/97 DSH HFS+, fixed some Unicode/Pascal strings related bugs for use on - HFS+ volumes. - 1/9/97 DSH Fix ExchangeFiles extents - 1/6/97 DSH pass VCB in CloseFile() routine. - 1/6/97 djb Fixed ResolveFileID - it was not returning a directory ID! - 1/3/97 msd Fix prototype for C_FlushCache. Fix prototype for - TrashFileBlocks. - 1/3/97 djb Integrate latest HFSVolumesPriv.h changes. - 1/2/97 DSH C port of ExchangeFileIDs - 12/20/96 djb Fixed bug in CreateFileID. - 12/19/96 DSH All refs to VCB are now refs to ExtendedVCB - 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. - 12/19/96 djb Updated for new B-tree Manager interface. - 12/18/96 msd GetFileThreadID was using a bitwise-OR (|) instead of - bitwise-AND (&) to test for a bit being set. - 12/12/96 DSH first checked in - -*/ #include "../../hfs_macos_defs.h" #include "../../hfs_format.h" @@ -126,43 +32,93 @@ #include "../headers/FileMgrInternal.h" #include "../headers/HFSUnicodeWrappers.h" #include "../headers/CatalogPrivate.h" +#include +#include +#include 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; - 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, NULL); ReturnIfError(err); @@ -201,48 +157,61 @@ OSErr ExchangeFileIDs( ExtendedVCB *vcb, ConstUTF8Param srcName, ConstUTF8Param //-- 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; @@ -251,13 +220,13 @@ ExUndo2aPlus: err = DeleteExtents( vcb, srcData.hfsPlusFile.fileID, isHFSPlus ); } 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; @@ -265,13 +234,13 @@ ExUndo2aPlus: err = DeleteExtents( vcb, srcData.hfsPlusFile.fileID, isHFSPlus ); } 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; @@ -300,6 +269,7 @@ ExUndo2aPlus: err = DeleteExtents( vcb, srcData.hfsPlusFile.fileID, isHFSPlus ); 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 @@ -337,19 +307,19 @@ ExUndo2aPlus: err = DeleteExtents( vcb, srcData.hfsPlusFile.fileID, 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.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 @@ -358,32 +328,32 @@ ExUndo1a: err = DeleteExtents( vcb, kHFSBogusExtentFileID, isHFSPlus ); } //-- 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; @@ -392,13 +362,13 @@ ExUndo2a: err = DeleteExtents( vcb, srcData.hfsFile.fileID, isHFSPlus ); } 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; @@ -406,13 +376,13 @@ ExUndo2a: err = DeleteExtents( vcb, srcData.hfsFile.fileID, isHFSPlus ); } 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; @@ -443,7 +413,8 @@ ExUndo2a: err = DeleteExtents( vcb, srcData.hfsFile.fileID, isHFSPlus ); err = ReplaceBTreeRecord( vcb->catalogRefNum, &destKey, destHint, &destData, sizeof(HFSCatalogFile), &destHint ); ReturnIfError( err ); } - +#endif + err = noErr; //-- Step 4: Error Handling section @@ -456,20 +427,20 @@ FlushAndReturn: } -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) ); @@ -477,24 +448,40 @@ void CopyBigCatalogNodeInfo( CatalogRecord *src, CatalogRecord *dest ) } -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; @@ -514,11 +501,12 @@ OSErr MoveExtents( ExtendedVCB *vcb, UInt32 srcFileID, UInt32 destFileID, Boolea 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); @@ -528,6 +516,11 @@ OSErr MoveExtents( ExtendedVCB *vcb, UInt32 srcFileID, UInt32 destFileID, Boolea 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 @@ -545,17 +538,19 @@ OSErr MoveExtents( ExtendedVCB *vcb, UInt32 srcFileID, UInt32 destFileID, Boolea // 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; } @@ -566,76 +561,102 @@ OSErr MoveExtents( ExtendedVCB *vcb, UInt32 srcFileID, UInt32 destFileID, Boolea for ( i=0 ; ihfsPlus.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 ; jkey, 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 ) ); @@ -643,20 +664,27 @@ void CopyExtentInfo( ExtentKey *key, ExtentRecord *data, ExtentsRecBuffer *buffe //-- 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; @@ -668,36 +696,42 @@ OSErr DeleteExtents( ExtendedVCB *vcb, UInt32 fileID, Boolean isHFSPlus ) 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 @@ -705,26 +739,45 @@ OSErr DeleteExtents( ExtendedVCB *vcb, UInt32 fileID, Boolean isHFSPlus ) 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 ) @@ -741,6 +794,7 @@ UInt32 CheckExtents( void *extents, UInt32 totalBlocks, Boolean isHFSPlus ) return( 0 ); } } +#if CONFIG_HFS_STD else { for ( i = 0 ; i < kHFSExtentDensity ; i++ ) @@ -750,6 +804,7 @@ UInt32 CheckExtents( void *extents, UInt32 totalBlocks, Boolean isHFSPlus ) return( 0 ); } } +#endif return( extentAllocationBlocks ); }