2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
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
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.
23 * @APPLE_LICENSE_HEADER_END@
29 * This file implements endian swapping routines for the HFS/HFS Plus
33 #include <architecture/byte_order.h>
35 #include "hfs_endian.h"
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
);
45 * hfs_swap_HFSPlusForkData
47 * There's still a few spots where we still need to swap the fork data.
50 hfs_swap_HFSPlusForkData (
56 src
->logicalSize
= SWAP_BE64 (src
->logicalSize
);
58 src
->clumpSize
= SWAP_BE32 (src
->clumpSize
);
59 src
->totalBlocks
= SWAP_BE32 (src
->totalBlocks
);
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
);
70 * NOTE: This operation is not naturally symmetric.
71 * We have to determine which way we're swapping things.
77 HFSCatalogNodeID fileID
,
81 BTNodeDescriptor
*srcDesc
= src
->buffer
;
82 UInt16
*srcOffs
= NULL
;
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");
96 panic ("%s This is impossible", "hfs_swap_BTNode:");
100 /* If we are doing a swap */
102 /* Swap the node descriptor */
103 srcDesc
->fLink
= SWAP_BE32 (srcDesc
->fLink
);
104 srcDesc
->bLink
= SWAP_BE32 (srcDesc
->bLink
);
106 /* Don't swap srcDesc->kind */
107 /* Don't swap srcDesc->height */
108 /* Don't swap srcDesc->reserved */
110 srcDesc
->numRecords
= SWAP_BE16 (srcDesc
->numRecords
);
112 /* Swap the node offsets (including the free space one!) */
113 srcOffs
= (UInt16
*)((char *)src
->buffer
+ (src
->blockSize
- ((srcDesc
->numRecords
+ 1) * sizeof (UInt16
))));
116 if ((char *)srcOffs
> ((char *)src
->buffer
+ src
->blockSize
)) {
117 panic ("%s Too many records in the B-Tree node", "hfs_swap_BTNode:");
120 for (i
= 0; i
< srcDesc
->numRecords
+ 1; i
++) {
121 srcOffs
[i
] = SWAP_BE16 (srcOffs
[i
]);
124 if (srcOffs
[i
] >= src
->blockSize
) {
125 panic ("%s B-Tree node offset out of range", "hfs_swap_BTNode:");
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
)) {
136 error
= hfs_swap_HFSPlusBTInternalNode (src
, fileID
, unswap
);
138 error
= hfs_swap_HFSBTInternalNode (src
, fileID
, unswap
);
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 */
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);
150 srcHead
->treeDepth
= SWAP_BE16 (srcHead
->treeDepth
);
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
);
157 srcHead
->nodeSize
= SWAP_BE16 (srcHead
->nodeSize
);
158 srcHead
->maxKeyLength
= SWAP_BE16 (srcHead
->maxKeyLength
);
160 srcHead
->totalNodes
= SWAP_BE32 (srcHead
->totalNodes
);
161 srcHead
->freeNodes
= SWAP_BE32 (srcHead
->freeNodes
);
163 srcHead
->clumpSize
= SWAP_BE32 (srcHead
->clumpSize
);
164 srcHead
->attributes
= SWAP_BE32 (srcHead
->attributes
);
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 */
173 /* If we are doing an unswap */
175 /* Swap the node descriptor */
176 srcDesc
->fLink
= SWAP_BE32 (srcDesc
->fLink
);
177 srcDesc
->bLink
= SWAP_BE32 (srcDesc
->bLink
);
179 /* Don't swap srcDesc->kind */
180 /* Don't swap srcDesc->height */
181 /* Don't swap srcDesc->reserved */
183 /* Swap the node offsets (including the free space one!) */
184 srcOffs
= (UInt16
*)((char *)src
->buffer
+ (src
->blockSize
- ((srcDesc
->numRecords
+ 1) * sizeof (UInt16
))));
187 if ((char *)srcOffs
> ((char *)src
->buffer
+ src
->blockSize
)) {
188 panic ("%s Too many records in the B-Tree node", "hfs_swap_BTNode:");
191 for (i
= 0; i
< srcDesc
->numRecords
+ 1; i
++) {
193 if (srcOffs
[i
] >= src
->blockSize
) {
194 panic ("%s B-Tree node offset out of range", "hfs_swap_BTNode:");
197 srcOffs
[i
] = SWAP_BE16 (srcOffs
[i
]);
200 srcDesc
->numRecords
= SWAP_BE16 (srcDesc
->numRecords
);
207 hfs_swap_HFSPlusBTInternalNode (
208 BlockDescriptor
*src
,
209 HFSCatalogNodeID fileID
,
213 BTNodeDescriptor
*srcDesc
= src
->buffer
;
214 UInt16
*srcOffs
= (UInt16
*)((char *)src
->buffer
+ (src
->blockSize
- (srcDesc
->numRecords
* sizeof (UInt16
))));
219 if (fileID
== kHFSExtentsFileID
) {
220 HFSPlusExtentKey
*srcKey
;
221 HFSPlusExtentDescriptor
*srcRec
;
223 for (i
= 0; i
< srcDesc
->numRecords
; i
++) {
224 srcKey
= (HFSPlusExtentKey
*)((char *)src
->buffer
+ srcOffs
[i
]);
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
);
230 /* Don't swap srcKey->forkType */
231 /* Don't swap srcKey->pad */
233 srcKey
->fileID
= SWAP_BE32 (srcKey
->fileID
);
234 srcKey
->startBlock
= SWAP_BE32 (srcKey
->startBlock
);
236 /* Stop if this is just an index node */
237 if (srcDesc
->kind
== kBTIndexNode
) {
238 *((UInt32
*)srcRec
) = SWAP_BE32 (*((UInt32
*)srcRec
));
242 /* Swap the extent data */
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
);
251 } else if (fileID
== kHFSCatalogFileID
) {
252 HFSPlusCatalogKey
*srcKey
;
255 for (i
= 0; i
< srcDesc
->numRecords
; i
++) {
256 srcKey
= (HFSPlusCatalogKey
*)((char *)src
->buffer
+ srcOffs
[i
]);
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
);
262 srcKey
->parentID
= SWAP_BE32 (srcKey
->parentID
);
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
]);
268 if (unswap
) srcKey
->nodeName
.length
= SWAP_BE16 (srcKey
->nodeName
.length
);
270 /* Stop if this is just an index node */
271 if (srcDesc
->kind
== kBTIndexNode
) {
272 *((UInt32
*)srcPtr
) = SWAP_BE32 (*((UInt32
*)srcPtr
));
276 /* Swap the recordType field, if unswapping, leave to later */
277 if (!unswap
) srcPtr
[0] = SWAP_BE16 (srcPtr
[0]);
279 if (srcPtr
[0] == kHFSPlusFolderRecord
) {
280 HFSPlusCatalogFolder
*srcRec
= (HFSPlusCatalogFolder
*)srcPtr
;
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
);
291 srcRec
->bsdInfo
.ownerID
= SWAP_BE32 (srcRec
->bsdInfo
.ownerID
);
292 srcRec
->bsdInfo
.groupID
= SWAP_BE32 (srcRec
->bsdInfo
.groupID
);
294 /* Don't swap srcRec->bsdInfo.adminFlags */
295 /* Don't swap srcRec->bsdInfo.ownerFlags */
297 srcRec
->bsdInfo
.fileMode
= SWAP_BE16 (srcRec
->bsdInfo
.fileMode
);
298 srcRec
->bsdInfo
.special
.iNodeNum
= SWAP_BE32 (srcRec
->bsdInfo
.special
.iNodeNum
);
300 srcRec
->textEncoding
= SWAP_BE32 (srcRec
->textEncoding
);
302 /* Don't swap srcRec->userInfo */
303 /* Don't swap srcRec->finderInfo */
304 /* Don't swap srcRec->reserved */
306 } else if (srcPtr
[0] == kHFSPlusFileRecord
) {
307 HFSPlusCatalogFile
*srcRec
= (HFSPlusCatalogFile
*)srcPtr
;
309 srcRec
->flags
= SWAP_BE16 (srcRec
->flags
);
311 srcRec
->fileID
= SWAP_BE32 (srcRec
->fileID
);
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
);
319 srcRec
->bsdInfo
.ownerID
= SWAP_BE32 (srcRec
->bsdInfo
.ownerID
);
320 srcRec
->bsdInfo
.groupID
= SWAP_BE32 (srcRec
->bsdInfo
.groupID
);
322 /* Don't swap srcRec->bsdInfo.adminFlags */
323 /* Don't swap srcRec->bsdInfo.ownerFlags */
325 srcRec
->bsdInfo
.fileMode
= SWAP_BE16 (srcRec
->bsdInfo
.fileMode
);
326 srcRec
->bsdInfo
.special
.iNodeNum
= SWAP_BE32 (srcRec
->bsdInfo
.special
.iNodeNum
);
328 srcRec
->textEncoding
= SWAP_BE32 (srcRec
->textEncoding
);
330 /* Don't swap srcRec->reserved1 */
331 /* Don't swap srcRec->userInfo */
332 /* Don't swap srcRec->finderInfo */
333 /* Don't swap srcRec->reserved2 */
335 hfs_swap_HFSPlusForkData (&srcRec
->dataFork
);
336 hfs_swap_HFSPlusForkData (&srcRec
->resourceFork
);
338 } else if ((srcPtr
[0] == kHFSPlusFolderThreadRecord
) ||
339 (srcPtr
[0] == kHFSPlusFileThreadRecord
)) {
341 HFSPlusCatalogThread
*srcRec
= (HFSPlusCatalogThread
*)srcPtr
;
343 /* Don't swap srcRec->reserved */
345 srcRec
->parentID
= SWAP_BE32 (srcRec
->parentID
);
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
]);
351 if (unswap
) srcRec
->nodeName
.length
= SWAP_BE16 (srcRec
->nodeName
.length
);
354 panic ("%s unrecognized catalog record type", "hfs_swap_BTNode:");
357 /* If unswapping, we can safely unswap type field now */
358 if (unswap
) srcPtr
[0] = SWAP_BE16 (srcPtr
[0]);
361 } else if (fileID
> kHFSFirstUserCatalogNodeID
) {
365 for (i
= 0; i
< srcDesc
->numRecords
; i
++) {
366 srcKey
= (HotFileKey
*)((char *)src
->buffer
+ srcOffs
[i
]);
369 srcKey
->keyLength
= SWAP_BE16 (srcKey
->keyLength
);
370 srcRec
= (u_int32_t
*)((char *)srcKey
+ srcKey
->keyLength
+ 2);
372 srcKey
->keyLength
= SWAP_BE16 (srcKey
->keyLength
);
374 /* Don't swap srcKey->forkType */
375 /* Don't swap srcKey->pad */
377 srcKey
->temperature
= SWAP_BE32 (srcKey
->temperature
);
378 srcKey
->fileID
= SWAP_BE32 (srcKey
->fileID
);
380 *((UInt32
*)srcRec
) = SWAP_BE32 (*((UInt32
*)srcRec
));
383 panic ("%s unrecognized B-Tree type", "hfs_swap_BTNode:");
391 hfs_swap_HFSBTInternalNode (
392 BlockDescriptor
*src
,
393 HFSCatalogNodeID fileID
,
397 BTNodeDescriptor
*srcDesc
= src
->buffer
;
398 UInt16
*srcOffs
= (UInt16
*)((char *)src
->buffer
+ (src
->blockSize
- (srcDesc
->numRecords
* sizeof (UInt16
))));
403 if (fileID
== kHFSExtentsFileID
) {
404 HFSExtentKey
*srcKey
;
405 HFSExtentDescriptor
*srcRec
;
407 for (i
= 0; i
< srcDesc
->numRecords
; i
++) {
408 srcKey
= (HFSExtentKey
*)((char *)src
->buffer
+ srcOffs
[i
]);
410 /* Don't swap srcKey->keyLength */
411 /* Don't swap srcKey->forkType */
413 srcKey
->fileID
= SWAP_BE32 (srcKey
->fileID
);
414 srcKey
->startBlock
= SWAP_BE16 (srcKey
->startBlock
);
416 /* Point to record data (round up to even byte boundary) */
417 srcRec
= (HFSExtentDescriptor
*)((char *)srcKey
+ ((srcKey
->keyLength
+ 2) & ~1));
419 /* Stop if this is just an index node */
420 if (srcDesc
->kind
== kBTIndexNode
) {
421 *((UInt32
*)srcRec
) = SWAP_BE32 (*((UInt32
*)srcRec
));
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
);
432 } else if (fileID
== kHFSCatalogFileID
) {
433 HFSCatalogKey
*srcKey
;
436 for (i
= 0; i
< srcDesc
->numRecords
; i
++) {
437 srcKey
= (HFSCatalogKey
*)((char *)src
->buffer
+ srcOffs
[i
]);
439 /* Don't swap srcKey->keyLength */
440 /* Don't swap srcKey->reserved */
442 srcKey
->parentID
= SWAP_BE32 (srcKey
->parentID
);
444 /* Don't swap srcKey->nodeName */
446 /* Point to record data (round up to even byte boundary) */
447 srcPtr
= (SInt16
*)((char *)srcKey
+ ((srcKey
->keyLength
+ 2) & ~1));
449 /* Stop if this is just an index node */
450 if (srcDesc
->kind
== kBTIndexNode
) {
451 *((UInt32
*)srcPtr
) = SWAP_BE32 (*((UInt32
*)srcPtr
));
455 /* Swap the recordType field, if unswapping, leave to later */
456 if (!unswap
) srcPtr
[0] = SWAP_BE16 (srcPtr
[0]);
458 if (srcPtr
[0] == kHFSFolderRecord
) {
459 HFSCatalogFolder
*srcRec
= (HFSCatalogFolder
*)srcPtr
;
461 srcRec
->flags
= SWAP_BE16 (srcRec
->flags
);
462 srcRec
->valence
= SWAP_BE16 (srcRec
->valence
);
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
);
469 /* Don't swap srcRec->userInfo */
470 /* Don't swap srcRec->finderInfo */
471 /* Don't swap resserved array */
473 } else if (srcPtr
[0] == kHFSFileRecord
) {
474 HFSCatalogFile
*srcRec
= (HFSCatalogFile
*)srcPtr
;
476 srcRec
->flags
= srcRec
->flags
;
477 srcRec
->fileType
= srcRec
->fileType
;
479 /* Don't swap srcRec->userInfo */
481 srcRec
->fileID
= SWAP_BE32 (srcRec
->fileID
);
483 srcRec
->dataStartBlock
= SWAP_BE16 (srcRec
->dataStartBlock
);
484 srcRec
->dataLogicalSize
= SWAP_BE32 (srcRec
->dataLogicalSize
);
485 srcRec
->dataPhysicalSize
= SWAP_BE32 (srcRec
->dataPhysicalSize
);
487 srcRec
->rsrcStartBlock
= SWAP_BE16 (srcRec
->rsrcStartBlock
);
488 srcRec
->rsrcLogicalSize
= SWAP_BE32 (srcRec
->rsrcLogicalSize
);
489 srcRec
->rsrcPhysicalSize
= SWAP_BE32 (srcRec
->rsrcPhysicalSize
);
491 srcRec
->createDate
= SWAP_BE32 (srcRec
->createDate
);
492 srcRec
->modifyDate
= SWAP_BE32 (srcRec
->modifyDate
);
493 srcRec
->backupDate
= SWAP_BE32 (srcRec
->backupDate
);
495 /* Don't swap srcRec->finderInfo */
497 srcRec
->clumpSize
= SWAP_BE16 (srcRec
->clumpSize
);
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
);
505 /* Don't swap srcRec->reserved */
507 } else if ((srcPtr
[0] == kHFSFolderThreadRecord
) ||
508 (srcPtr
[0] == kHFSFileThreadRecord
)) {
510 HFSCatalogThread
*srcRec
= (HFSCatalogThread
*)srcPtr
;
512 /* Don't swap srcRec->reserved array */
514 srcRec
->parentID
= SWAP_BE32 (srcRec
->parentID
);
516 /* Don't swap srcRec->nodeName */
519 panic ("%s unrecognized catalog record type", "hfs_swap_BTNode:");
522 /* If unswapping, we can safely swap type now */
523 if (unswap
) srcPtr
[0] = SWAP_BE16 (srcPtr
[0]);
527 panic ("%s unrecognized B-Tree type", "hfs_swap_BTNode:");