]> git.saurik.com Git - apple/xnu.git/blob - bsd/hfs/hfscommon/Misc/BTreeWrapper.c
xnu-517.tar.gz
[apple/xnu.git] / bsd / hfs / hfscommon / Misc / BTreeWrapper.c
1 /*
2 * Copyright (c) 2000,2002 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25
26 #include "../headers/BTreesPrivate.h"
27
28
29 // local routines
30 static OSErr CheckBTreeKey(const BTreeKey *key, const BTreeControlBlock *btcb);
31 static Boolean ValidHFSRecord(const void *record, const BTreeControlBlock *btcb, UInt16 recordSize);
32
33
34
35
36 OSErr SearchBTreeRecord(FileReference refNum, const void* key, UInt32 hint, void* foundKey, void* data, UInt16 *dataSize, UInt32 *newHint)
37 {
38 panic("SearchBTreeRecord is dead code!");
39 return (-1);
40 #if 0
41 FSBufferDescriptor btRecord;
42 BTreeIterator searchIterator;
43 FCB *fcb;
44 BTreeControlBlock *btcb;
45 OSStatus result;
46
47
48 fcb = GetFileControlBlock(refNum);
49 btcb = (BTreeControlBlock*) fcb->fcbBTCBPtr;
50
51 btRecord.bufferAddress = data;
52 btRecord.itemCount = 1;
53 if ( btcb->maxKeyLength == kHFSExtentKeyMaximumLength )
54 btRecord.itemSize = sizeof(HFSExtentRecord);
55 else if ( btcb->maxKeyLength == kHFSPlusExtentKeyMaximumLength )
56 btRecord.itemSize = sizeof(HFSPlusExtentRecord);
57 else
58 btRecord.itemSize = sizeof(CatalogRecord);
59
60 searchIterator.hint.writeCount = 0; // clear these out for debugging...
61 searchIterator.hint.reserved1 = 0;
62 searchIterator.hint.reserved2 = 0;
63
64 searchIterator.hint.nodeNum = hint;
65 searchIterator.hint.index = 0;
66
67 result = CheckBTreeKey((BTreeKey *) key, btcb);
68 ExitOnError(result);
69
70 BlockMoveData(key, &searchIterator.key, CalcKeySize(btcb, (BTreeKey *) key)); //\80\80 should we range check against maxkeylen?
71
72 result = BTSearchRecord( fcb, &searchIterator, &btRecord, dataSize, &searchIterator );
73
74 if (result == noErr)
75 {
76 *newHint = searchIterator.hint.nodeNum;
77
78 result = CheckBTreeKey(&searchIterator.key, btcb);
79 ExitOnError(result);
80
81 BlockMoveData(&searchIterator.key, foundKey, CalcKeySize(btcb, &searchIterator.key)); //\80\80 warning, this could overflow user's buffer!!!
82
83 if ( DEBUG_BUILD && !ValidHFSRecord(data, btcb, *dataSize) )
84 DebugStr("\pSearchBTreeRecord: bad record?");
85 }
86
87 ErrorExit:
88
89 return result;
90 #endif
91 }
92
93
94 OSErr ReplaceBTreeRecord(FileReference refNum, const void* key, UInt32 hint, void *newData, UInt16 dataSize, UInt32 *newHint)
95 {
96 FSBufferDescriptor btRecord;
97 BTreeIterator iterator;
98 FCB *fcb;
99 BTreeControlBlock *btcb;
100 OSStatus result;
101
102
103 fcb = GetFileControlBlock(refNum);
104 btcb = (BTreeControlBlock*) fcb->fcbBTCBPtr;
105
106 btRecord.bufferAddress = newData;
107 btRecord.itemSize = dataSize;
108 btRecord.itemCount = 1;
109
110 iterator.hint.nodeNum = hint;
111
112 result = CheckBTreeKey((BTreeKey *) key, btcb);
113 ExitOnError(result);
114
115 BlockMoveData(key, &iterator.key, CalcKeySize(btcb, (BTreeKey *) key)); //\80\80 should we range check against maxkeylen?
116
117 if ( DEBUG_BUILD && !ValidHFSRecord(newData, btcb, dataSize) )
118 DebugStr("\pReplaceBTreeRecord: bad record?");
119
120 result = BTReplaceRecord( fcb, &iterator, &btRecord, dataSize );
121
122 *newHint = iterator.hint.nodeNum;
123
124 //\80\80 do we need to invalidate the iterator?
125
126 ErrorExit:
127
128 return result;
129 }
130
131
132
133 static OSErr CheckBTreeKey(const BTreeKey *key, const BTreeControlBlock *btcb)
134 {
135 UInt16 keyLen;
136
137 if ( btcb->attributes & kBTBigKeysMask )
138 keyLen = key->length16;
139 else
140 keyLen = key->length8;
141
142 if ( (keyLen < 6) || (keyLen > btcb->maxKeyLength) )
143 {
144 if ( DEBUG_BUILD )
145 DebugStr("\pCheckBTreeKey: bad key length!");
146 return fsBTInvalidKeyLengthErr;
147 }
148
149 return noErr;
150 }
151
152
153 static Boolean ValidHFSRecord(const void *record, const BTreeControlBlock *btcb, UInt16 recordSize)
154 {
155 UInt32 cNodeID;
156
157 if ( btcb->maxKeyLength == kHFSExtentKeyMaximumLength )
158 {
159 return ( recordSize == sizeof(HFSExtentRecord) );
160 }
161 else if (btcb->maxKeyLength == kHFSPlusExtentKeyMaximumLength )
162 {
163 return ( recordSize == sizeof(HFSPlusExtentRecord) );
164 }
165 else // Catalog record
166 {
167 CatalogRecord *catalogRecord = (CatalogRecord*) record;
168
169 switch(catalogRecord->recordType)
170 {
171 case kHFSFolderRecord:
172 {
173 if ( recordSize != sizeof(HFSCatalogFolder) )
174 return false;
175 if ( catalogRecord->hfsFolder.flags != 0 )
176 return false;
177 if ( catalogRecord->hfsFolder.valence > 0x7FFF )
178 return false;
179
180 cNodeID = catalogRecord->hfsFolder.folderID;
181
182 if ( (cNodeID == 0) || (cNodeID < 16 && cNodeID > 2) )
183 return false;
184 }
185 break;
186
187 case kHFSPlusFolderRecord:
188 {
189 if ( recordSize != sizeof(HFSPlusCatalogFolder) )
190 return false;
191 if ( catalogRecord->hfsPlusFolder.flags != 0 )
192 return false;
193 if ( catalogRecord->hfsPlusFolder.valence > 0x7FFF )
194 return false;
195
196 cNodeID = catalogRecord->hfsPlusFolder.folderID;
197
198 if ( (cNodeID == 0) || (cNodeID < 16 && cNodeID > 2) )
199 return false;
200 }
201 break;
202
203 case kHFSFileRecord:
204 {
205 // UInt16 i;
206 HFSExtentDescriptor *dataExtent;
207 HFSExtentDescriptor *rsrcExtent;
208
209 if ( recordSize != sizeof(HFSCatalogFile) )
210 return false;
211 if ( (catalogRecord->hfsFile.flags & ~(0x83)) != 0 )
212 return false;
213
214 cNodeID = catalogRecord->hfsFile.fileID;
215
216 if ( cNodeID < 16 )
217 return false;
218
219 // make sure 0 ¾ LEOF ¾ PEOF for both forks
220
221 if ( catalogRecord->hfsFile.dataLogicalSize < 0 )
222 return false;
223 if ( catalogRecord->hfsFile.dataPhysicalSize < catalogRecord->hfsFile.dataLogicalSize )
224 return false;
225 if ( catalogRecord->hfsFile.rsrcLogicalSize < 0 )
226 return false;
227 if ( catalogRecord->hfsFile.rsrcPhysicalSize < catalogRecord->hfsFile.rsrcLogicalSize )
228 return false;
229
230 dataExtent = (HFSExtentDescriptor*) &catalogRecord->hfsFile.dataExtents;
231 rsrcExtent = (HFSExtentDescriptor*) &catalogRecord->hfsFile.rsrcExtents;
232
233 #if 0
234 for (i = 0; i < kHFSExtentDensity; ++i)
235 {
236 if ( (dataExtent[i].blockCount > 0) && (dataExtent[i].startBlock == 0) )
237 return false;
238 if ( (rsrcExtent[i].blockCount > 0) && (rsrcExtent[i].startBlock == 0) )
239 return false;
240 }
241 #endif
242 }
243 break;
244
245 case kHFSPlusFileRecord:
246 {
247 // UInt16 i;
248 HFSPlusExtentDescriptor *dataExtent;
249 HFSPlusExtentDescriptor *rsrcExtent;
250
251 if ( recordSize != sizeof(HFSPlusCatalogFile) )
252 return false;
253 if ( (catalogRecord->hfsPlusFile.flags & ~(0x83)) != 0 )
254 return false;
255
256 cNodeID = catalogRecord->hfsPlusFile.fileID;
257
258 if ( cNodeID < 16 )
259 return false;
260
261 // make sure 0 ¾ LEOF ¾ PEOF for both forks
262
263 dataExtent = (HFSPlusExtentDescriptor*) &catalogRecord->hfsPlusFile.dataFork.extents;
264 rsrcExtent = (HFSPlusExtentDescriptor*) &catalogRecord->hfsPlusFile.resourceFork.extents;
265
266 #if 0
267 for (i = 0; i < kHFSPlusExtentDensity; ++i)
268 {
269 if ( (dataExtent[i].blockCount > 0) && (dataExtent[i].startBlock == 0) )
270 return false;
271 if ( (rsrcExtent[i].blockCount > 0) && (rsrcExtent[i].startBlock == 0) )
272 return false;
273 }
274 #endif
275 }
276 break;
277
278 case kHFSFolderThreadRecord:
279 case kHFSFileThreadRecord:
280 {
281 if ( recordSize != sizeof(HFSCatalogThread) )
282 return false;
283
284 cNodeID = catalogRecord->hfsThread.parentID;
285 if ( (cNodeID == 0) || (cNodeID < 16 && cNodeID > 2) )
286 return false;
287
288 if ( (catalogRecord->hfsThread.nodeName[0] == 0) ||
289 (catalogRecord->hfsThread.nodeName[0] > 31) )
290 return false;
291 }
292 break;
293
294 case kHFSPlusFolderThreadRecord:
295 case kHFSPlusFileThreadRecord:
296 {
297 if ( recordSize > sizeof(HFSPlusCatalogThread) || recordSize < (sizeof(HFSPlusCatalogThread) - sizeof(HFSUniStr255)))
298 return false;
299
300 cNodeID = catalogRecord->hfsPlusThread.parentID;
301 if ( (cNodeID == 0) || (cNodeID < 16 && cNodeID > 2) )
302 return false;
303
304 if ( (catalogRecord->hfsPlusThread.nodeName.length == 0) ||
305 (catalogRecord->hfsPlusThread.nodeName.length > 255) )
306 return false;
307 }
308 break;
309
310 default:
311 return false;
312 }
313 }
314
315 return true; // record appears to be OK
316 }