2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
26 * This file implements endian swapping routines for the HFS/HFS Plus
30 #include <architecture/byte_order.h>
32 #include "hfs_endian.h"
37 /* Private swapping routines */
38 int hfs_swap_HFSPlusBTInternalNode (BlockDescriptor
*src
, HFSCatalogNodeID fileID
, int unswap
);
39 int hfs_swap_HFSBTInternalNode (BlockDescriptor
*src
, HFSCatalogNodeID fileID
, int unswap
);
42 * hfs_swap_HFSPlusForkData
44 * There's still a few spots where we still need to swap the fork data.
47 hfs_swap_HFSPlusForkData (
53 DBG_FUNC_NAME("hfs_swap_HFSPlusForkData");
54 DBG_PRINT_FUNC_NAME();
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
;
87 DBG_FUNC_NAME("hfs_swap_BTNode");
88 DBG_PRINT_FUNC_NAME();
92 printf ("BE -> LE Swap\n");
93 } else if (unswap
== 1) {
94 printf ("LE -> BE Swap\n");
95 } else if (unswap
== 3) {
96 printf ("Not swapping descriptors\n");
98 panic ("%s This is impossible", "hfs_swap_BTNode:");
102 /* If we are doing a swap */
104 /* Swap the node descriptor */
105 srcDesc
->fLink
= SWAP_BE32 (srcDesc
->fLink
);
106 srcDesc
->bLink
= SWAP_BE32 (srcDesc
->bLink
);
108 /* Don't swap srcDesc->kind */
109 /* Don't swap srcDesc->height */
110 /* Don't swap srcDesc->reserved */
112 srcDesc
->numRecords
= SWAP_BE16 (srcDesc
->numRecords
);
114 /* Swap the node offsets (including the free space one!) */
115 srcOffs
= (UInt16
*)((char *)src
->buffer
+ (src
->blockSize
- ((srcDesc
->numRecords
+ 1) * sizeof (UInt16
))));
118 if ((char *)srcOffs
> ((char *)src
->buffer
+ src
->blockSize
)) {
119 panic ("%s Too many records in the B-Tree node", "hfs_swap_BTNode:");
122 for (i
= 0; i
< srcDesc
->numRecords
+ 1; i
++) {
123 srcOffs
[i
] = SWAP_BE16 (srcOffs
[i
]);
126 if (srcOffs
[i
] >= src
->blockSize
) {
127 panic ("%s B-Tree node offset out of range", "hfs_swap_BTNode:");
132 /* Swap the records (ordered by frequency of access) */
133 /* Swap a B-Tree internal node */
134 if ((srcDesc
->kind
== kBTIndexNode
) ||
135 (srcDesc
-> kind
== kBTLeafNode
)) {
138 error
= hfs_swap_HFSPlusBTInternalNode (src
, fileID
, unswap
);
140 error
= hfs_swap_HFSBTInternalNode (src
, fileID
, unswap
);
143 /* Swap a B-Tree map node */
144 } else if (srcDesc
-> kind
== kBTMapNode
) {
145 /* Don't swap the bitmaps, they'll be done in the bitmap routines */
147 /* Swap a B-Tree header node */
148 } else if (srcDesc
-> kind
== kBTHeaderNode
) {
149 /* The header's offset is hard-wired because we cannot trust the offset pointers */
150 BTHeaderRec
*srcHead
= (BTHeaderRec
*)((char *)src
->buffer
+ 14);
152 srcHead
->treeDepth
= SWAP_BE16 (srcHead
->treeDepth
);
154 srcHead
->rootNode
= SWAP_BE32 (srcHead
->rootNode
);
155 srcHead
->leafRecords
= SWAP_BE32 (srcHead
->leafRecords
);
156 srcHead
->firstLeafNode
= SWAP_BE32 (srcHead
->firstLeafNode
);
157 srcHead
->lastLeafNode
= SWAP_BE32 (srcHead
->lastLeafNode
);
159 srcHead
->nodeSize
= SWAP_BE16 (srcHead
->nodeSize
);
160 srcHead
->maxKeyLength
= SWAP_BE16 (srcHead
->maxKeyLength
);
162 srcHead
->totalNodes
= SWAP_BE32 (srcHead
->totalNodes
);
163 srcHead
->freeNodes
= SWAP_BE32 (srcHead
->freeNodes
);
165 srcHead
->clumpSize
= SWAP_BE32 (srcHead
->clumpSize
);
166 srcHead
->attributes
= SWAP_BE32 (srcHead
->attributes
);
168 /* Don't swap srcHead->reserved1 */
169 /* Don't swap srcHead->btreeType */
170 /* Don't swap srcHead->reserved2 */
171 /* Don't swap srcHead->reserved3 */
172 /* Don't swap bitmap */
175 /* If we are doing an unswap */
177 /* Swap the node descriptor */
178 srcDesc
->fLink
= SWAP_BE32 (srcDesc
->fLink
);
179 srcDesc
->bLink
= SWAP_BE32 (srcDesc
->bLink
);
181 /* Don't swap srcDesc->kind */
182 /* Don't swap srcDesc->height */
183 /* Don't swap srcDesc->reserved */
185 /* Swap the node offsets (including the free space one!) */
186 srcOffs
= (UInt16
*)((char *)src
->buffer
+ (src
->blockSize
- ((srcDesc
->numRecords
+ 1) * sizeof (UInt16
))));
189 if ((char *)srcOffs
> ((char *)src
->buffer
+ src
->blockSize
)) {
190 panic ("%s Too many records in the B-Tree node", "hfs_swap_BTNode:");
193 for (i
= 0; i
< srcDesc
->numRecords
+ 1; i
++) {
195 if (srcOffs
[i
] >= src
->blockSize
) {
196 panic ("%s B-Tree node offset out of range", "hfs_swap_BTNode:");
199 srcOffs
[i
] = SWAP_BE16 (srcOffs
[i
]);
202 srcDesc
->numRecords
= SWAP_BE16 (srcDesc
->numRecords
);
209 hfs_swap_HFSPlusBTInternalNode (
210 BlockDescriptor
*src
,
211 HFSCatalogNodeID fileID
,
215 BTNodeDescriptor
*srcDesc
= src
->buffer
;
216 UInt16
*srcOffs
= (UInt16
*)((char *)src
->buffer
+ (src
->blockSize
- (srcDesc
->numRecords
* sizeof (UInt16
))));
221 DBG_FUNC_NAME("hfs_swap_HFSPlusBTInternalNode");
222 DBG_PRINT_FUNC_NAME();
224 if (fileID
== kHFSExtentsFileID
) {
225 HFSPlusExtentKey
*srcKey
;
226 HFSPlusExtentDescriptor
*srcRec
;
228 for (i
= 0; i
< srcDesc
->numRecords
; i
++) {
229 srcKey
= (HFSPlusExtentKey
*)((char *)src
->buffer
+ srcOffs
[i
]);
231 if (!unswap
) srcKey
->keyLength
= SWAP_BE16 (srcKey
->keyLength
);
232 srcRec
= (HFSPlusExtentDescriptor
*)((char *)srcKey
+ srcKey
->keyLength
+ 2);
233 if (unswap
) srcKey
->keyLength
= SWAP_BE16 (srcKey
->keyLength
);
235 /* Don't swap srcKey->forkType */
236 /* Don't swap srcKey->pad */
238 srcKey
->fileID
= SWAP_BE32 (srcKey
->fileID
);
239 srcKey
->startBlock
= SWAP_BE32 (srcKey
->startBlock
);
241 /* Stop if this is just an index node */
242 if (srcDesc
->kind
== kBTIndexNode
) {
243 *((UInt32
*)srcRec
) = SWAP_BE32 (*((UInt32
*)srcRec
));
247 /* Swap the extent data */
249 /* Swap each extent */
250 for (j
= 0; j
< kHFSPlusExtentDensity
; j
++) {
251 srcRec
[j
].startBlock
= SWAP_BE32 (srcRec
[j
].startBlock
);
252 srcRec
[j
].blockCount
= SWAP_BE32 (srcRec
[j
].blockCount
);
256 } else if (fileID
== kHFSCatalogFileID
) {
257 HFSPlusCatalogKey
*srcKey
;
260 for (i
= 0; i
< srcDesc
->numRecords
; i
++) {
261 srcKey
= (HFSPlusCatalogKey
*)((char *)src
->buffer
+ srcOffs
[i
]);
263 if (!unswap
) srcKey
->keyLength
= SWAP_BE16 (srcKey
->keyLength
);
264 srcPtr
= (SInt16
*)((char *)srcKey
+ srcKey
->keyLength
+ 2);
265 if (unswap
) srcKey
->keyLength
= SWAP_BE16 (srcKey
->keyLength
);
267 srcKey
->parentID
= SWAP_BE32 (srcKey
->parentID
);
269 if (!unswap
) srcKey
->nodeName
.length
= SWAP_BE16 (srcKey
->nodeName
.length
);
270 for (j
= 0; j
< srcKey
->nodeName
.length
; j
++) {
271 srcKey
->nodeName
.unicode
[j
] = SWAP_BE16 (srcKey
->nodeName
.unicode
[j
]);
273 if (unswap
) srcKey
->nodeName
.length
= SWAP_BE16 (srcKey
->nodeName
.length
);
275 /* Stop if this is just an index node */
276 if (srcDesc
->kind
== kBTIndexNode
) {
277 *((UInt32
*)srcPtr
) = SWAP_BE32 (*((UInt32
*)srcPtr
));
281 /* Swap the recordType field, if unswapping, leave to later */
282 if (!unswap
) srcPtr
[0] = SWAP_BE16 (srcPtr
[0]);
284 if (srcPtr
[0] == kHFSPlusFolderRecord
) {
285 HFSPlusCatalogFolder
*srcRec
= (HFSPlusCatalogFolder
*)srcPtr
;
287 srcRec
->flags
= SWAP_BE16 (srcRec
->flags
);
288 srcRec
->valence
= SWAP_BE32 (srcRec
->valence
);
289 srcRec
->folderID
= SWAP_BE32 (srcRec
->folderID
);
290 srcRec
->createDate
= SWAP_BE32 (srcRec
->createDate
);
291 srcRec
->contentModDate
= SWAP_BE32 (srcRec
->contentModDate
);
292 srcRec
->attributeModDate
= SWAP_BE32 (srcRec
->attributeModDate
);
293 srcRec
->accessDate
= SWAP_BE32 (srcRec
->accessDate
);
294 srcRec
->backupDate
= SWAP_BE32 (srcRec
->backupDate
);
296 srcRec
->bsdInfo
.ownerID
= SWAP_BE32 (srcRec
->bsdInfo
.ownerID
);
297 srcRec
->bsdInfo
.groupID
= SWAP_BE32 (srcRec
->bsdInfo
.groupID
);
299 /* Don't swap srcRec->bsdInfo.adminFlags */
300 /* Don't swap srcRec->bsdInfo.ownerFlags */
302 srcRec
->bsdInfo
.fileMode
= SWAP_BE16 (srcRec
->bsdInfo
.fileMode
);
303 srcRec
->bsdInfo
.special
.iNodeNum
= SWAP_BE32 (srcRec
->bsdInfo
.special
.iNodeNum
);
305 srcRec
->textEncoding
= SWAP_BE32 (srcRec
->textEncoding
);
307 /* Don't swap srcRec->userInfo */
308 /* Don't swap srcRec->finderInfo */
309 /* Don't swap srcRec->reserved */
311 } else if (srcPtr
[0] == kHFSPlusFileRecord
) {
312 HFSPlusCatalogFile
*srcRec
= (HFSPlusCatalogFile
*)srcPtr
;
314 srcRec
->flags
= SWAP_BE16 (srcRec
->flags
);
316 srcRec
->fileID
= SWAP_BE32 (srcRec
->fileID
);
318 srcRec
->createDate
= SWAP_BE32 (srcRec
->createDate
);
319 srcRec
->contentModDate
= SWAP_BE32 (srcRec
->contentModDate
);
320 srcRec
->attributeModDate
= SWAP_BE32 (srcRec
->attributeModDate
);
321 srcRec
->accessDate
= SWAP_BE32 (srcRec
->accessDate
);
322 srcRec
->backupDate
= SWAP_BE32 (srcRec
->backupDate
);
324 srcRec
->bsdInfo
.ownerID
= SWAP_BE32 (srcRec
->bsdInfo
.ownerID
);
325 srcRec
->bsdInfo
.groupID
= SWAP_BE32 (srcRec
->bsdInfo
.groupID
);
327 /* Don't swap srcRec->bsdInfo.adminFlags */
328 /* Don't swap srcRec->bsdInfo.ownerFlags */
330 srcRec
->bsdInfo
.fileMode
= SWAP_BE16 (srcRec
->bsdInfo
.fileMode
);
331 srcRec
->bsdInfo
.special
.iNodeNum
= SWAP_BE32 (srcRec
->bsdInfo
.special
.iNodeNum
);
333 srcRec
->textEncoding
= SWAP_BE32 (srcRec
->textEncoding
);
335 /* Don't swap srcRec->reserved1 */
336 /* Don't swap srcRec->userInfo */
337 /* Don't swap srcRec->finderInfo */
338 /* Don't swap srcRec->reserved2 */
340 hfs_swap_HFSPlusForkData (&srcRec
->dataFork
);
341 hfs_swap_HFSPlusForkData (&srcRec
->resourceFork
);
343 } else if ((srcPtr
[0] == kHFSPlusFolderThreadRecord
) ||
344 (srcPtr
[0] == kHFSPlusFileThreadRecord
)) {
346 HFSPlusCatalogThread
*srcRec
= (HFSPlusCatalogThread
*)srcPtr
;
348 /* Don't swap srcRec->reserved */
350 srcRec
->parentID
= SWAP_BE32 (srcRec
->parentID
);
352 if (!unswap
) srcRec
->nodeName
.length
= SWAP_BE16 (srcRec
->nodeName
.length
);
353 for (j
= 0; j
< srcRec
->nodeName
.length
; j
++) {
354 srcRec
->nodeName
.unicode
[j
] = SWAP_BE16 (srcRec
->nodeName
.unicode
[j
]);
356 if (unswap
) srcRec
->nodeName
.length
= SWAP_BE16 (srcRec
->nodeName
.length
);
359 panic ("%s unrecognized catalog record type", "hfs_swap_BTNode:");
362 /* If unswapping, we can safely unswap type field now */
363 if (unswap
) srcPtr
[0] = SWAP_BE16 (srcPtr
[0]);
367 panic ("%s unrecognized B-Tree type", "hfs_swap_BTNode:");
374 hfs_swap_HFSBTInternalNode (
375 BlockDescriptor
*src
,
376 HFSCatalogNodeID fileID
,
380 BTNodeDescriptor
*srcDesc
= src
->buffer
;
381 UInt16
*srcOffs
= (UInt16
*)((char *)src
->buffer
+ (src
->blockSize
- (srcDesc
->numRecords
* sizeof (UInt16
))));
386 DBG_FUNC_NAME("hfs_swap_HFSBTInternalNode");
387 DBG_PRINT_FUNC_NAME();
389 if (fileID
== kHFSExtentsFileID
) {
390 HFSExtentKey
*srcKey
;
391 HFSExtentDescriptor
*srcRec
;
393 for (i
= 0; i
< srcDesc
->numRecords
; i
++) {
394 srcKey
= (HFSExtentKey
*)((char *)src
->buffer
+ srcOffs
[i
]);
396 /* Don't swap srcKey->keyLength */
397 /* Don't swap srcKey->forkType */
399 srcKey
->fileID
= SWAP_BE32 (srcKey
->fileID
);
400 srcKey
->startBlock
= SWAP_BE16 (srcKey
->startBlock
);
402 /* Point to record data (round up to even byte boundary) */
403 srcRec
= (HFSExtentDescriptor
*)((char *)srcKey
+ ((srcKey
->keyLength
+ 2) & ~1));
405 /* Stop if this is just an index node */
406 if (srcDesc
->kind
== kBTIndexNode
) {
407 *((UInt32
*)srcRec
) = SWAP_BE32 (*((UInt32
*)srcRec
));
411 /* Swap each extent */
412 for (j
= 0; j
< kHFSExtentDensity
; j
++) {
413 srcRec
[j
].startBlock
= SWAP_BE16 (srcRec
[j
].startBlock
);
414 srcRec
[j
].blockCount
= SWAP_BE16 (srcRec
[j
].blockCount
);
418 } else if (fileID
== kHFSCatalogFileID
) {
419 HFSCatalogKey
*srcKey
;
422 for (i
= 0; i
< srcDesc
->numRecords
; i
++) {
423 srcKey
= (HFSCatalogKey
*)((char *)src
->buffer
+ srcOffs
[i
]);
425 /* Don't swap srcKey->keyLength */
426 /* Don't swap srcKey->reserved */
428 srcKey
->parentID
= SWAP_BE32 (srcKey
->parentID
);
430 /* Don't swap srcKey->nodeName */
432 /* Point to record data (round up to even byte boundary) */
433 srcPtr
= (SInt16
*)((char *)srcKey
+ ((srcKey
->keyLength
+ 2) & ~1));
435 /* Stop if this is just an index node */
436 if (srcDesc
->kind
== kBTIndexNode
) {
437 *((UInt32
*)srcPtr
) = SWAP_BE32 (*((UInt32
*)srcPtr
));
441 /* Swap the recordType field, if unswapping, leave to later */
442 if (!unswap
) srcPtr
[0] = SWAP_BE16 (srcPtr
[0]);
444 if (srcPtr
[0] == kHFSFolderRecord
) {
445 HFSCatalogFolder
*srcRec
= (HFSCatalogFolder
*)srcPtr
;
447 srcRec
->flags
= SWAP_BE16 (srcRec
->flags
);
448 srcRec
->valence
= SWAP_BE16 (srcRec
->valence
);
450 srcRec
->folderID
= SWAP_BE32 (srcRec
->folderID
);
451 srcRec
->createDate
= SWAP_BE32 (srcRec
->createDate
);
452 srcRec
->modifyDate
= SWAP_BE32 (srcRec
->modifyDate
);
453 srcRec
->backupDate
= SWAP_BE32 (srcRec
->backupDate
);
455 /* Don't swap srcRec->userInfo */
456 /* Don't swap srcRec->finderInfo */
457 /* Don't swap resserved array */
459 } else if (srcPtr
[0] == kHFSFileRecord
) {
460 HFSCatalogFile
*srcRec
= (HFSCatalogFile
*)srcPtr
;
462 srcRec
->flags
= srcRec
->flags
;
463 srcRec
->fileType
= srcRec
->fileType
;
465 /* Don't swap srcRec->userInfo */
467 srcRec
->fileID
= SWAP_BE32 (srcRec
->fileID
);
469 srcRec
->dataStartBlock
= SWAP_BE16 (srcRec
->dataStartBlock
);
470 srcRec
->dataLogicalSize
= SWAP_BE32 (srcRec
->dataLogicalSize
);
471 srcRec
->dataPhysicalSize
= SWAP_BE32 (srcRec
->dataPhysicalSize
);
473 srcRec
->rsrcStartBlock
= SWAP_BE16 (srcRec
->rsrcStartBlock
);
474 srcRec
->rsrcLogicalSize
= SWAP_BE32 (srcRec
->rsrcLogicalSize
);
475 srcRec
->rsrcPhysicalSize
= SWAP_BE32 (srcRec
->rsrcPhysicalSize
);
477 srcRec
->createDate
= SWAP_BE32 (srcRec
->createDate
);
478 srcRec
->modifyDate
= SWAP_BE32 (srcRec
->modifyDate
);
479 srcRec
->backupDate
= SWAP_BE32 (srcRec
->backupDate
);
481 /* Don't swap srcRec->finderInfo */
483 srcRec
->clumpSize
= SWAP_BE16 (srcRec
->clumpSize
);
485 /* Swap the two sets of extents as an array of six (three each) UInt16 */
486 for (j
= 0; j
< kHFSExtentDensity
* 2; j
++) {
487 srcRec
->dataExtents
[j
].startBlock
= SWAP_BE16 (srcRec
->dataExtents
[j
].startBlock
);
488 srcRec
->dataExtents
[j
].blockCount
= SWAP_BE16 (srcRec
->dataExtents
[j
].blockCount
);
491 /* Don't swap srcRec->reserved */
493 } else if ((srcPtr
[0] == kHFSFolderThreadRecord
) ||
494 (srcPtr
[0] == kHFSFileThreadRecord
)) {
496 HFSCatalogThread
*srcRec
= (HFSCatalogThread
*)srcPtr
;
498 /* Don't swap srcRec->reserved array */
500 srcRec
->parentID
= SWAP_BE32 (srcRec
->parentID
);
502 /* Don't swap srcRec->nodeName */
505 panic ("%s unrecognized catalog record type", "hfs_swap_BTNode:");
508 /* If unswapping, we can safely swap type now */
509 if (unswap
) srcPtr
[0] = SWAP_BE16 (srcPtr
[0]);
513 panic ("%s unrecognized B-Tree type", "hfs_swap_BTNode:");