]> git.saurik.com Git - apple/xnu.git/blob - bsd/hfs/hfs_endian.c
xnu-517.3.15.tar.gz
[apple/xnu.git] / bsd / hfs / hfs_endian.c
1 /*
2 * Copyright (c) 2000 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 /*
27 * hfs_endian.c
28 *
29 * This file implements endian swapping routines for the HFS/HFS Plus
30 * volume format.
31 */
32
33 #include <architecture/byte_order.h>
34
35 #include "hfs_endian.h"
36 #include "hfs_dbg.h"
37
38 #undef ENDIAN_DEBUG
39
40 /* Private swapping routines */
41 int hfs_swap_HFSPlusBTInternalNode (BlockDescriptor *src, HFSCatalogNodeID fileID, int unswap);
42 int hfs_swap_HFSBTInternalNode (BlockDescriptor *src, HFSCatalogNodeID fileID, int unswap);
43
44 /*
45 * hfs_swap_HFSPlusForkData
46 *
47 * There's still a few spots where we still need to swap the fork data.
48 */
49 void
50 hfs_swap_HFSPlusForkData (
51 HFSPlusForkData *src
52 )
53 {
54 int i;
55
56 src->logicalSize = SWAP_BE64 (src->logicalSize);
57
58 src->clumpSize = SWAP_BE32 (src->clumpSize);
59 src->totalBlocks = SWAP_BE32 (src->totalBlocks);
60
61 for (i = 0; i < kHFSPlusExtentDensity; i++) {
62 src->extents[i].startBlock = SWAP_BE32 (src->extents[i].startBlock);
63 src->extents[i].blockCount = SWAP_BE32 (src->extents[i].blockCount);
64 }
65 }
66
67 /*
68 * hfs_swap_BTNode
69 *
70 * NOTE: This operation is not naturally symmetric.
71 * We have to determine which way we're swapping things.
72 */
73 int
74 hfs_swap_BTNode (
75 BlockDescriptor *src,
76 int isHFSPlus,
77 HFSCatalogNodeID fileID,
78 int unswap
79 )
80 {
81 BTNodeDescriptor *srcDesc = src->buffer;
82 UInt16 *srcOffs = NULL;
83
84 UInt32 i;
85 int error = 0;
86
87
88 #ifdef ENDIAN_DEBUG
89 if (unswap == 0) {
90 printf ("BE -> LE Swap\n");
91 } else if (unswap == 1) {
92 printf ("LE -> BE Swap\n");
93 } else if (unswap == 3) {
94 printf ("Not swapping descriptors\n");
95 } else {
96 panic ("%s This is impossible", "hfs_swap_BTNode:");
97 }
98 #endif
99
100 /* If we are doing a swap */
101 if (unswap == 0) {
102 /* Swap the node descriptor */
103 srcDesc->fLink = SWAP_BE32 (srcDesc->fLink);
104 srcDesc->bLink = SWAP_BE32 (srcDesc->bLink);
105
106 /* Don't swap srcDesc->kind */
107 /* Don't swap srcDesc->height */
108 /* Don't swap srcDesc->reserved */
109
110 srcDesc->numRecords = SWAP_BE16 (srcDesc->numRecords);
111
112 /* Swap the node offsets (including the free space one!) */
113 srcOffs = (UInt16 *)((char *)src->buffer + (src->blockSize - ((srcDesc->numRecords + 1) * sizeof (UInt16))));
114
115 /* Sanity check */
116 if ((char *)srcOffs > ((char *)src->buffer + src->blockSize)) {
117 panic ("%s Too many records in the B-Tree node", "hfs_swap_BTNode:");
118 }
119
120 for (i = 0; i < srcDesc->numRecords + 1; i++) {
121 srcOffs[i] = SWAP_BE16 (srcOffs[i]);
122
123 /* Sanity check */
124 if (srcOffs[i] >= src->blockSize) {
125 panic ("%s B-Tree node offset out of range", "hfs_swap_BTNode:");
126 }
127 }
128 }
129
130 /* Swap the records (ordered by frequency of access) */
131 /* Swap a B-Tree internal node */
132 if ((srcDesc->kind == kBTIndexNode) ||
133 (srcDesc-> kind == kBTLeafNode)) {
134
135 if (isHFSPlus) {
136 error = hfs_swap_HFSPlusBTInternalNode (src, fileID, unswap);
137 } else {
138 error = hfs_swap_HFSBTInternalNode (src, fileID, unswap);
139 }
140
141 /* Swap a B-Tree map node */
142 } else if (srcDesc-> kind == kBTMapNode) {
143 /* Don't swap the bitmaps, they'll be done in the bitmap routines */
144
145 /* Swap a B-Tree header node */
146 } else if (srcDesc-> kind == kBTHeaderNode) {
147 /* The header's offset is hard-wired because we cannot trust the offset pointers */
148 BTHeaderRec *srcHead = (BTHeaderRec *)((char *)src->buffer + 14);
149
150 srcHead->treeDepth = SWAP_BE16 (srcHead->treeDepth);
151
152 srcHead->rootNode = SWAP_BE32 (srcHead->rootNode);
153 srcHead->leafRecords = SWAP_BE32 (srcHead->leafRecords);
154 srcHead->firstLeafNode = SWAP_BE32 (srcHead->firstLeafNode);
155 srcHead->lastLeafNode = SWAP_BE32 (srcHead->lastLeafNode);
156
157 srcHead->nodeSize = SWAP_BE16 (srcHead->nodeSize);
158 srcHead->maxKeyLength = SWAP_BE16 (srcHead->maxKeyLength);
159
160 srcHead->totalNodes = SWAP_BE32 (srcHead->totalNodes);
161 srcHead->freeNodes = SWAP_BE32 (srcHead->freeNodes);
162
163 srcHead->clumpSize = SWAP_BE32 (srcHead->clumpSize);
164 srcHead->attributes = SWAP_BE32 (srcHead->attributes);
165
166 /* Don't swap srcHead->reserved1 */
167 /* Don't swap srcHead->btreeType */
168 /* Don't swap srcHead->reserved2 */
169 /* Don't swap srcHead->reserved3 */
170 /* Don't swap bitmap */
171 }
172
173 /* If we are doing an unswap */
174 if (unswap == 1) {
175 /* Swap the node descriptor */
176 srcDesc->fLink = SWAP_BE32 (srcDesc->fLink);
177 srcDesc->bLink = SWAP_BE32 (srcDesc->bLink);
178
179 /* Don't swap srcDesc->kind */
180 /* Don't swap srcDesc->height */
181 /* Don't swap srcDesc->reserved */
182
183 /* Swap the node offsets (including the free space one!) */
184 srcOffs = (UInt16 *)((char *)src->buffer + (src->blockSize - ((srcDesc->numRecords + 1) * sizeof (UInt16))));
185
186 /* Sanity check */
187 if ((char *)srcOffs > ((char *)src->buffer + src->blockSize)) {
188 panic ("%s Too many records in the B-Tree node", "hfs_swap_BTNode:");
189 }
190
191 for (i = 0; i < srcDesc->numRecords + 1; i++) {
192 /* Sanity check */
193 if (srcOffs[i] >= src->blockSize) {
194 panic ("%s B-Tree node offset out of range", "hfs_swap_BTNode:");
195 }
196
197 srcOffs[i] = SWAP_BE16 (srcOffs[i]);
198 }
199
200 srcDesc->numRecords = SWAP_BE16 (srcDesc->numRecords);
201 }
202
203 return (error);
204 }
205
206 int
207 hfs_swap_HFSPlusBTInternalNode (
208 BlockDescriptor *src,
209 HFSCatalogNodeID fileID,
210 int unswap
211 )
212 {
213 BTNodeDescriptor *srcDesc = src->buffer;
214 UInt16 *srcOffs = (UInt16 *)((char *)src->buffer + (src->blockSize - (srcDesc->numRecords * sizeof (UInt16))));
215
216 UInt32 i;
217 UInt32 j;
218
219 if (fileID == kHFSExtentsFileID) {
220 HFSPlusExtentKey *srcKey;
221 HFSPlusExtentDescriptor *srcRec;
222
223 for (i = 0; i < srcDesc->numRecords; i++) {
224 srcKey = (HFSPlusExtentKey *)((char *)src->buffer + srcOffs[i]);
225
226 if (!unswap) srcKey->keyLength = SWAP_BE16 (srcKey->keyLength);
227 srcRec = (HFSPlusExtentDescriptor *)((char *)srcKey + srcKey->keyLength + 2);
228 if (unswap) srcKey->keyLength = SWAP_BE16 (srcKey->keyLength);
229
230 /* Don't swap srcKey->forkType */
231 /* Don't swap srcKey->pad */
232
233 srcKey->fileID = SWAP_BE32 (srcKey->fileID);
234 srcKey->startBlock = SWAP_BE32 (srcKey->startBlock);
235
236 /* Stop if this is just an index node */
237 if (srcDesc->kind == kBTIndexNode) {
238 *((UInt32 *)srcRec) = SWAP_BE32 (*((UInt32 *)srcRec));
239 continue;
240 }
241
242 /* Swap the extent data */
243
244 /* Swap each extent */
245 for (j = 0; j < kHFSPlusExtentDensity; j++) {
246 srcRec[j].startBlock = SWAP_BE32 (srcRec[j].startBlock);
247 srcRec[j].blockCount = SWAP_BE32 (srcRec[j].blockCount);
248 }
249 }
250
251 } else if (fileID == kHFSCatalogFileID) {
252 HFSPlusCatalogKey *srcKey;
253 SInt16 *srcPtr;
254
255 for (i = 0; i < srcDesc->numRecords; i++) {
256 srcKey = (HFSPlusCatalogKey *)((char *)src->buffer + srcOffs[i]);
257
258 if (!unswap) srcKey->keyLength = SWAP_BE16 (srcKey->keyLength);
259 srcPtr = (SInt16 *)((char *)srcKey + srcKey->keyLength + 2);
260 if (unswap) srcKey->keyLength = SWAP_BE16 (srcKey->keyLength);
261
262 srcKey->parentID = SWAP_BE32 (srcKey->parentID);
263
264 if (!unswap) srcKey->nodeName.length = SWAP_BE16 (srcKey->nodeName.length);
265 for (j = 0; j < srcKey->nodeName.length; j++) {
266 srcKey->nodeName.unicode[j] = SWAP_BE16 (srcKey->nodeName.unicode[j]);
267 }
268 if (unswap) srcKey->nodeName.length = SWAP_BE16 (srcKey->nodeName.length);
269
270 /* Stop if this is just an index node */
271 if (srcDesc->kind == kBTIndexNode) {
272 *((UInt32 *)srcPtr) = SWAP_BE32 (*((UInt32 *)srcPtr));
273 continue;
274 }
275
276 /* Swap the recordType field, if unswapping, leave to later */
277 if (!unswap) srcPtr[0] = SWAP_BE16 (srcPtr[0]);
278
279 if (srcPtr[0] == kHFSPlusFolderRecord) {
280 HFSPlusCatalogFolder *srcRec = (HFSPlusCatalogFolder *)srcPtr;
281
282 srcRec->flags = SWAP_BE16 (srcRec->flags);
283 srcRec->valence = SWAP_BE32 (srcRec->valence);
284 srcRec->folderID = SWAP_BE32 (srcRec->folderID);
285 srcRec->createDate = SWAP_BE32 (srcRec->createDate);
286 srcRec->contentModDate = SWAP_BE32 (srcRec->contentModDate);
287 srcRec->attributeModDate = SWAP_BE32 (srcRec->attributeModDate);
288 srcRec->accessDate = SWAP_BE32 (srcRec->accessDate);
289 srcRec->backupDate = SWAP_BE32 (srcRec->backupDate);
290
291 srcRec->bsdInfo.ownerID = SWAP_BE32 (srcRec->bsdInfo.ownerID);
292 srcRec->bsdInfo.groupID = SWAP_BE32 (srcRec->bsdInfo.groupID);
293
294 /* Don't swap srcRec->bsdInfo.adminFlags */
295 /* Don't swap srcRec->bsdInfo.ownerFlags */
296
297 srcRec->bsdInfo.fileMode = SWAP_BE16 (srcRec->bsdInfo.fileMode);
298 srcRec->bsdInfo.special.iNodeNum = SWAP_BE32 (srcRec->bsdInfo.special.iNodeNum);
299
300 srcRec->textEncoding = SWAP_BE32 (srcRec->textEncoding);
301
302 /* Don't swap srcRec->userInfo */
303 /* Don't swap srcRec->finderInfo */
304 /* Don't swap srcRec->reserved */
305
306 } else if (srcPtr[0] == kHFSPlusFileRecord) {
307 HFSPlusCatalogFile *srcRec = (HFSPlusCatalogFile *)srcPtr;
308
309 srcRec->flags = SWAP_BE16 (srcRec->flags);
310
311 srcRec->fileID = SWAP_BE32 (srcRec->fileID);
312
313 srcRec->createDate = SWAP_BE32 (srcRec->createDate);
314 srcRec->contentModDate = SWAP_BE32 (srcRec->contentModDate);
315 srcRec->attributeModDate = SWAP_BE32 (srcRec->attributeModDate);
316 srcRec->accessDate = SWAP_BE32 (srcRec->accessDate);
317 srcRec->backupDate = SWAP_BE32 (srcRec->backupDate);
318
319 srcRec->bsdInfo.ownerID = SWAP_BE32 (srcRec->bsdInfo.ownerID);
320 srcRec->bsdInfo.groupID = SWAP_BE32 (srcRec->bsdInfo.groupID);
321
322 /* Don't swap srcRec->bsdInfo.adminFlags */
323 /* Don't swap srcRec->bsdInfo.ownerFlags */
324
325 srcRec->bsdInfo.fileMode = SWAP_BE16 (srcRec->bsdInfo.fileMode);
326 srcRec->bsdInfo.special.iNodeNum = SWAP_BE32 (srcRec->bsdInfo.special.iNodeNum);
327
328 srcRec->textEncoding = SWAP_BE32 (srcRec->textEncoding);
329
330 /* Don't swap srcRec->reserved1 */
331 /* Don't swap srcRec->userInfo */
332 /* Don't swap srcRec->finderInfo */
333 /* Don't swap srcRec->reserved2 */
334
335 hfs_swap_HFSPlusForkData (&srcRec->dataFork);
336 hfs_swap_HFSPlusForkData (&srcRec->resourceFork);
337
338 } else if ((srcPtr[0] == kHFSPlusFolderThreadRecord) ||
339 (srcPtr[0] == kHFSPlusFileThreadRecord)) {
340
341 HFSPlusCatalogThread *srcRec = (HFSPlusCatalogThread *)srcPtr;
342
343 /* Don't swap srcRec->reserved */
344
345 srcRec->parentID = SWAP_BE32 (srcRec->parentID);
346
347 if (!unswap) srcRec->nodeName.length = SWAP_BE16 (srcRec->nodeName.length);
348 for (j = 0; j < srcRec->nodeName.length; j++) {
349 srcRec->nodeName.unicode[j] = SWAP_BE16 (srcRec->nodeName.unicode[j]);
350 }
351 if (unswap) srcRec->nodeName.length = SWAP_BE16 (srcRec->nodeName.length);
352
353 } else {
354 panic ("%s unrecognized catalog record type", "hfs_swap_BTNode:");
355 }
356
357 /* If unswapping, we can safely unswap type field now */
358 if (unswap) srcPtr[0] = SWAP_BE16 (srcPtr[0]);
359 }
360
361 } else if (fileID > kHFSFirstUserCatalogNodeID) {
362 HotFileKey *srcKey;
363 UInt32 *srcRec;
364
365 for (i = 0; i < srcDesc->numRecords; i++) {
366 srcKey = (HotFileKey *)((char *)src->buffer + srcOffs[i]);
367
368 if (!unswap)
369 srcKey->keyLength = SWAP_BE16 (srcKey->keyLength);
370 srcRec = (u_int32_t *)((char *)srcKey + srcKey->keyLength + 2);
371 if (unswap)
372 srcKey->keyLength = SWAP_BE16 (srcKey->keyLength);
373
374 /* Don't swap srcKey->forkType */
375 /* Don't swap srcKey->pad */
376
377 srcKey->temperature = SWAP_BE32 (srcKey->temperature);
378 srcKey->fileID = SWAP_BE32 (srcKey->fileID);
379
380 *((UInt32 *)srcRec) = SWAP_BE32 (*((UInt32 *)srcRec));
381 }
382 } else {
383 panic ("%s unrecognized B-Tree type", "hfs_swap_BTNode:");
384 }
385
386
387 return (0);
388 }
389
390 int
391 hfs_swap_HFSBTInternalNode (
392 BlockDescriptor *src,
393 HFSCatalogNodeID fileID,
394 int unswap
395 )
396 {
397 BTNodeDescriptor *srcDesc = src->buffer;
398 UInt16 *srcOffs = (UInt16 *)((char *)src->buffer + (src->blockSize - (srcDesc->numRecords * sizeof (UInt16))));
399
400 UInt32 i;
401 UInt32 j;
402
403 if (fileID == kHFSExtentsFileID) {
404 HFSExtentKey *srcKey;
405 HFSExtentDescriptor *srcRec;
406
407 for (i = 0; i < srcDesc->numRecords; i++) {
408 srcKey = (HFSExtentKey *)((char *)src->buffer + srcOffs[i]);
409
410 /* Don't swap srcKey->keyLength */
411 /* Don't swap srcKey->forkType */
412
413 srcKey->fileID = SWAP_BE32 (srcKey->fileID);
414 srcKey->startBlock = SWAP_BE16 (srcKey->startBlock);
415
416 /* Point to record data (round up to even byte boundary) */
417 srcRec = (HFSExtentDescriptor *)((char *)srcKey + ((srcKey->keyLength + 2) & ~1));
418
419 /* Stop if this is just an index node */
420 if (srcDesc->kind == kBTIndexNode) {
421 *((UInt32 *)srcRec) = SWAP_BE32 (*((UInt32 *)srcRec));
422 continue;
423 }
424
425 /* Swap each extent */
426 for (j = 0; j < kHFSExtentDensity; j++) {
427 srcRec[j].startBlock = SWAP_BE16 (srcRec[j].startBlock);
428 srcRec[j].blockCount = SWAP_BE16 (srcRec[j].blockCount);
429 }
430 }
431
432 } else if (fileID == kHFSCatalogFileID) {
433 HFSCatalogKey *srcKey;
434 SInt16 *srcPtr;
435
436 for (i = 0; i < srcDesc->numRecords; i++) {
437 srcKey = (HFSCatalogKey *)((char *)src->buffer + srcOffs[i]);
438
439 /* Don't swap srcKey->keyLength */
440 /* Don't swap srcKey->reserved */
441
442 srcKey->parentID = SWAP_BE32 (srcKey->parentID);
443
444 /* Don't swap srcKey->nodeName */
445
446 /* Point to record data (round up to even byte boundary) */
447 srcPtr = (SInt16 *)((char *)srcKey + ((srcKey->keyLength + 2) & ~1));
448
449 /* Stop if this is just an index node */
450 if (srcDesc->kind == kBTIndexNode) {
451 *((UInt32 *)srcPtr) = SWAP_BE32 (*((UInt32 *)srcPtr));
452 continue;
453 }
454
455 /* Swap the recordType field, if unswapping, leave to later */
456 if (!unswap) srcPtr[0] = SWAP_BE16 (srcPtr[0]);
457
458 if (srcPtr[0] == kHFSFolderRecord) {
459 HFSCatalogFolder *srcRec = (HFSCatalogFolder *)srcPtr;
460
461 srcRec->flags = SWAP_BE16 (srcRec->flags);
462 srcRec->valence = SWAP_BE16 (srcRec->valence);
463
464 srcRec->folderID = SWAP_BE32 (srcRec->folderID);
465 srcRec->createDate = SWAP_BE32 (srcRec->createDate);
466 srcRec->modifyDate = SWAP_BE32 (srcRec->modifyDate);
467 srcRec->backupDate = SWAP_BE32 (srcRec->backupDate);
468
469 /* Don't swap srcRec->userInfo */
470 /* Don't swap srcRec->finderInfo */
471 /* Don't swap resserved array */
472
473 } else if (srcPtr[0] == kHFSFileRecord) {
474 HFSCatalogFile *srcRec = (HFSCatalogFile *)srcPtr;
475
476 srcRec->flags = srcRec->flags;
477 srcRec->fileType = srcRec->fileType;
478
479 /* Don't swap srcRec->userInfo */
480
481 srcRec->fileID = SWAP_BE32 (srcRec->fileID);
482
483 srcRec->dataStartBlock = SWAP_BE16 (srcRec->dataStartBlock);
484 srcRec->dataLogicalSize = SWAP_BE32 (srcRec->dataLogicalSize);
485 srcRec->dataPhysicalSize = SWAP_BE32 (srcRec->dataPhysicalSize);
486
487 srcRec->rsrcStartBlock = SWAP_BE16 (srcRec->rsrcStartBlock);
488 srcRec->rsrcLogicalSize = SWAP_BE32 (srcRec->rsrcLogicalSize);
489 srcRec->rsrcPhysicalSize = SWAP_BE32 (srcRec->rsrcPhysicalSize);
490
491 srcRec->createDate = SWAP_BE32 (srcRec->createDate);
492 srcRec->modifyDate = SWAP_BE32 (srcRec->modifyDate);
493 srcRec->backupDate = SWAP_BE32 (srcRec->backupDate);
494
495 /* Don't swap srcRec->finderInfo */
496
497 srcRec->clumpSize = SWAP_BE16 (srcRec->clumpSize);
498
499 /* Swap the two sets of extents as an array of six (three each) UInt16 */
500 for (j = 0; j < kHFSExtentDensity * 2; j++) {
501 srcRec->dataExtents[j].startBlock = SWAP_BE16 (srcRec->dataExtents[j].startBlock);
502 srcRec->dataExtents[j].blockCount = SWAP_BE16 (srcRec->dataExtents[j].blockCount);
503 }
504
505 /* Don't swap srcRec->reserved */
506
507 } else if ((srcPtr[0] == kHFSFolderThreadRecord) ||
508 (srcPtr[0] == kHFSFileThreadRecord)) {
509
510 HFSCatalogThread *srcRec = (HFSCatalogThread *)srcPtr;
511
512 /* Don't swap srcRec->reserved array */
513
514 srcRec->parentID = SWAP_BE32 (srcRec->parentID);
515
516 /* Don't swap srcRec->nodeName */
517
518 } else {
519 panic ("%s unrecognized catalog record type", "hfs_swap_BTNode:");
520 }
521
522 /* If unswapping, we can safely swap type now */
523 if (unswap) srcPtr[0] = SWAP_BE16 (srcPtr[0]);
524 }
525
526 } else {
527 panic ("%s unrecognized B-Tree type", "hfs_swap_BTNode:");
528 }
529
530 return (0);
531 }