2 * Copyright (c) 2000, 2002, 2005 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include "../headers/BTreesPrivate.h"
33 static OSErr
CheckBTreeKey(const BTreeKey
*key
, const BTreeControlBlock
*btcb
);
34 static Boolean
ValidHFSRecord(const void *record
, const BTreeControlBlock
*btcb
, u_int16_t recordSize
);
39 OSErr
SearchBTreeRecord(__unused FileReference refNum
, __unused
const void* key
, __unused u_int32_t hint
, __unused
void* foundKey
, __unused
void* data
, __unused u_int16_t
*dataSize
, __unused u_int32_t
*newHint
)
41 panic("SearchBTreeRecord is dead code!");
44 FSBufferDescriptor btRecord
;
45 BTreeIterator searchIterator
;
47 BTreeControlBlock
*btcb
;
51 fcb
= GetFileControlBlock(refNum
);
52 btcb
= (BTreeControlBlock
*) fcb
->fcbBTCBPtr
;
54 btRecord
.bufferAddress
= data
;
55 btRecord
.itemCount
= 1;
56 if ( btcb
->maxKeyLength
== kHFSExtentKeyMaximumLength
)
57 btRecord
.itemSize
= sizeof(HFSExtentRecord
);
58 else if ( btcb
->maxKeyLength
== kHFSPlusExtentKeyMaximumLength
)
59 btRecord
.itemSize
= sizeof(HFSPlusExtentRecord
);
61 btRecord
.itemSize
= sizeof(CatalogRecord
);
63 searchIterator
.hint
.writeCount
= 0; // clear these out for debugging...
64 searchIterator
.hint
.reserved1
= 0;
65 searchIterator
.hint
.reserved2
= 0;
67 searchIterator
.hint
.nodeNum
= hint
;
68 searchIterator
.hint
.index
= 0;
70 result
= CheckBTreeKey((BTreeKey
*) key
, btcb
);
73 BlockMoveData(key
, &searchIterator
.key
, CalcKeySize(btcb
, (BTreeKey
*) key
)); //\80\80 should we range check against maxkeylen?
75 result
= BTSearchRecord( fcb
, &searchIterator
, &btRecord
, dataSize
, &searchIterator
);
79 *newHint
= searchIterator
.hint
.nodeNum
;
81 result
= CheckBTreeKey(&searchIterator
.key
, btcb
);
84 BlockMoveData(&searchIterator
.key
, foundKey
, CalcKeySize(btcb
, &searchIterator
.key
)); //\80\80 warning, this could overflow user's buffer!!!
86 if ( DEBUG_BUILD
&& !ValidHFSRecord(data
, btcb
, *dataSize
) )
87 DebugStr("\pSearchBTreeRecord: bad record?");
97 OSErr
ReplaceBTreeRecord(FileReference refNum
, const void* key
, u_int32_t hint
, void *newData
, u_int16_t dataSize
, u_int32_t
*newHint
)
99 FSBufferDescriptor btRecord
;
100 BTreeIterator iterator
;
102 BTreeControlBlock
*btcb
;
106 fcb
= GetFileControlBlock(refNum
);
107 btcb
= (BTreeControlBlock
*) fcb
->fcbBTCBPtr
;
109 btRecord
.bufferAddress
= newData
;
110 btRecord
.itemSize
= dataSize
;
111 btRecord
.itemCount
= 1;
113 iterator
.hint
.nodeNum
= hint
;
115 result
= CheckBTreeKey((const BTreeKey
*) key
, btcb
);
118 BlockMoveData(key
, &iterator
.key
, CalcKeySize(btcb
, (const BTreeKey
*) key
)); //\80\80 should we range check against maxkeylen?
120 if ( DEBUG_BUILD
&& !ValidHFSRecord(newData
, btcb
, dataSize
) )
121 DebugStr("\pReplaceBTreeRecord: bad record?");
123 result
= BTReplaceRecord( fcb
, &iterator
, &btRecord
, dataSize
);
125 *newHint
= iterator
.hint
.nodeNum
;
127 //\80\80 do we need to invalidate the iterator?
136 static OSErr
CheckBTreeKey(const BTreeKey
*key
, const BTreeControlBlock
*btcb
)
140 if ( btcb
->attributes
& kBTBigKeysMask
)
141 keyLen
= key
->length16
;
143 keyLen
= key
->length8
;
145 if ( (keyLen
< 6) || (keyLen
> btcb
->maxKeyLength
) )
148 DebugStr("\pCheckBTreeKey: bad key length!");
149 return fsBTInvalidKeyLengthErr
;
156 static Boolean
ValidHFSRecord(const void *record
, const BTreeControlBlock
*btcb
, u_int16_t recordSize
)
160 if ( btcb
->maxKeyLength
== kHFSExtentKeyMaximumLength
)
162 return ( recordSize
== sizeof(HFSExtentRecord
) );
164 else if (btcb
->maxKeyLength
== kHFSPlusExtentKeyMaximumLength
)
166 return ( recordSize
== sizeof(HFSPlusExtentRecord
) );
168 else // Catalog record
170 const CatalogRecord
*catalogRecord
= (const CatalogRecord
*) record
;
172 switch(catalogRecord
->recordType
)
174 case kHFSFolderRecord
:
176 if ( recordSize
!= sizeof(HFSCatalogFolder
) )
178 if ( catalogRecord
->hfsFolder
.flags
!= 0 )
180 if ( catalogRecord
->hfsFolder
.valence
> 0x7FFF )
183 cNodeID
= catalogRecord
->hfsFolder
.folderID
;
185 if ( (cNodeID
== 0) || (cNodeID
< 16 && cNodeID
> 2) )
190 case kHFSPlusFolderRecord
:
192 if ( recordSize
!= sizeof(HFSPlusCatalogFolder
) )
194 if ( catalogRecord
->hfsPlusFolder
.flags
!= 0 )
196 if ( catalogRecord
->hfsPlusFolder
.valence
> 0x7FFF )
199 cNodeID
= catalogRecord
->hfsPlusFolder
.folderID
;
201 if ( (cNodeID
== 0) || (cNodeID
< 16 && cNodeID
> 2) )
209 HFSExtentDescriptor
*dataExtent
;
210 HFSExtentDescriptor
*rsrcExtent
;
212 if ( recordSize
!= sizeof(HFSCatalogFile
) )
214 if ( (catalogRecord
->hfsFile
.flags
& ~(0x83)) != 0 )
217 cNodeID
= catalogRecord
->hfsFile
.fileID
;
222 // make sure 0 ¾ LEOF ¾ PEOF for both forks
224 if ( catalogRecord
->hfsFile
.dataLogicalSize
< 0 )
226 if ( catalogRecord
->hfsFile
.dataPhysicalSize
< catalogRecord
->hfsFile
.dataLogicalSize
)
228 if ( catalogRecord
->hfsFile
.rsrcLogicalSize
< 0 )
230 if ( catalogRecord
->hfsFile
.rsrcPhysicalSize
< catalogRecord
->hfsFile
.rsrcLogicalSize
)
233 dataExtent
= (HFSExtentDescriptor
*) &catalogRecord
->hfsFile
.dataExtents
;
234 rsrcExtent
= (HFSExtentDescriptor
*) &catalogRecord
->hfsFile
.rsrcExtents
;
237 for (i
= 0; i
< kHFSExtentDensity
; ++i
)
239 if ( (dataExtent
[i
].blockCount
> 0) && (dataExtent
[i
].startBlock
== 0) )
241 if ( (rsrcExtent
[i
].blockCount
> 0) && (rsrcExtent
[i
].startBlock
== 0) )
248 case kHFSPlusFileRecord
:
251 HFSPlusExtentDescriptor
*dataExtent
;
252 HFSPlusExtentDescriptor
*rsrcExtent
;
254 if ( recordSize
!= sizeof(HFSPlusCatalogFile
) )
256 if ( (catalogRecord
->hfsPlusFile
.flags
& ~(0x83)) != 0 )
259 cNodeID
= catalogRecord
->hfsPlusFile
.fileID
;
264 // make sure 0 ¾ LEOF ¾ PEOF for both forks
266 dataExtent
= (HFSPlusExtentDescriptor
*) &catalogRecord
->hfsPlusFile
.dataFork
.extents
;
267 rsrcExtent
= (HFSPlusExtentDescriptor
*) &catalogRecord
->hfsPlusFile
.resourceFork
.extents
;
270 for (i
= 0; i
< kHFSPlusExtentDensity
; ++i
)
272 if ( (dataExtent
[i
].blockCount
> 0) && (dataExtent
[i
].startBlock
== 0) )
274 if ( (rsrcExtent
[i
].blockCount
> 0) && (rsrcExtent
[i
].startBlock
== 0) )
281 case kHFSFolderThreadRecord
:
282 case kHFSFileThreadRecord
:
284 if ( recordSize
!= sizeof(HFSCatalogThread
) )
287 cNodeID
= catalogRecord
->hfsThread
.parentID
;
288 if ( (cNodeID
== 0) || (cNodeID
< 16 && cNodeID
> 2) )
291 if ( (catalogRecord
->hfsThread
.nodeName
[0] == 0) ||
292 (catalogRecord
->hfsThread
.nodeName
[0] > 31) )
297 case kHFSPlusFolderThreadRecord
:
298 case kHFSPlusFileThreadRecord
:
300 if ( recordSize
> sizeof(HFSPlusCatalogThread
) || recordSize
< (sizeof(HFSPlusCatalogThread
) - sizeof(HFSUniStr255
)))
303 cNodeID
= catalogRecord
->hfsPlusThread
.parentID
;
304 if ( (cNodeID
== 0) || (cNodeID
< 16 && cNodeID
> 2) )
307 if ( (catalogRecord
->hfsPlusThread
.nodeName
.length
== 0) ||
308 (catalogRecord
->hfsPlusThread
.nodeName
.length
> 255) )
318 return true; // record appears to be OK