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