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 src
->logicalSize
= SWAP_BE64 (src
->logicalSize
);
55 src
->clumpSize
= SWAP_BE32 (src
->clumpSize
);
56 src
->totalBlocks
= SWAP_BE32 (src
->totalBlocks
);
58 for (i
= 0; i
< kHFSPlusExtentDensity
; i
++) {
59 src
->extents
[i
].startBlock
= SWAP_BE32 (src
->extents
[i
].startBlock
);
60 src
->extents
[i
].blockCount
= SWAP_BE32 (src
->extents
[i
].blockCount
);
67 * NOTE: This operation is not naturally symmetric.
68 * We have to determine which way we're swapping things.
74 HFSCatalogNodeID fileID
,
78 BTNodeDescriptor
*srcDesc
= src
->buffer
;
79 UInt16
*srcOffs
= NULL
;
87 printf ("BE -> LE Swap\n");
88 } else if (unswap
== 1) {
89 printf ("LE -> BE Swap\n");
90 } else if (unswap
== 3) {
91 printf ("Not swapping descriptors\n");
93 panic ("%s This is impossible", "hfs_swap_BTNode:");
97 /* If we are doing a swap */
99 /* Swap the node descriptor */
100 srcDesc
->fLink
= SWAP_BE32 (srcDesc
->fLink
);
101 srcDesc
->bLink
= SWAP_BE32 (srcDesc
->bLink
);
103 /* Don't swap srcDesc->kind */
104 /* Don't swap srcDesc->height */
105 /* Don't swap srcDesc->reserved */
107 srcDesc
->numRecords
= SWAP_BE16 (srcDesc
->numRecords
);
109 /* Swap the node offsets (including the free space one!) */
110 srcOffs
= (UInt16
*)((char *)src
->buffer
+ (src
->blockSize
- ((srcDesc
->numRecords
+ 1) * sizeof (UInt16
))));
113 if ((char *)srcOffs
> ((char *)src
->buffer
+ src
->blockSize
)) {
114 panic ("%s Too many records in the B-Tree node", "hfs_swap_BTNode:");
117 for (i
= 0; i
< srcDesc
->numRecords
+ 1; i
++) {
118 srcOffs
[i
] = SWAP_BE16 (srcOffs
[i
]);
121 if (srcOffs
[i
] >= src
->blockSize
) {
122 panic ("%s B-Tree node offset out of range", "hfs_swap_BTNode:");
127 /* Swap the records (ordered by frequency of access) */
128 /* Swap a B-Tree internal node */
129 if ((srcDesc
->kind
== kBTIndexNode
) ||
130 (srcDesc
-> kind
== kBTLeafNode
)) {
133 error
= hfs_swap_HFSPlusBTInternalNode (src
, fileID
, unswap
);
135 error
= hfs_swap_HFSBTInternalNode (src
, fileID
, unswap
);
138 /* Swap a B-Tree map node */
139 } else if (srcDesc
-> kind
== kBTMapNode
) {
140 /* Don't swap the bitmaps, they'll be done in the bitmap routines */
142 /* Swap a B-Tree header node */
143 } else if (srcDesc
-> kind
== kBTHeaderNode
) {
144 /* The header's offset is hard-wired because we cannot trust the offset pointers */
145 BTHeaderRec
*srcHead
= (BTHeaderRec
*)((char *)src
->buffer
+ 14);
147 srcHead
->treeDepth
= SWAP_BE16 (srcHead
->treeDepth
);
149 srcHead
->rootNode
= SWAP_BE32 (srcHead
->rootNode
);
150 srcHead
->leafRecords
= SWAP_BE32 (srcHead
->leafRecords
);
151 srcHead
->firstLeafNode
= SWAP_BE32 (srcHead
->firstLeafNode
);
152 srcHead
->lastLeafNode
= SWAP_BE32 (srcHead
->lastLeafNode
);
154 srcHead
->nodeSize
= SWAP_BE16 (srcHead
->nodeSize
);
155 srcHead
->maxKeyLength
= SWAP_BE16 (srcHead
->maxKeyLength
);
157 srcHead
->totalNodes
= SWAP_BE32 (srcHead
->totalNodes
);
158 srcHead
->freeNodes
= SWAP_BE32 (srcHead
->freeNodes
);
160 srcHead
->clumpSize
= SWAP_BE32 (srcHead
->clumpSize
);
161 srcHead
->attributes
= SWAP_BE32 (srcHead
->attributes
);
163 /* Don't swap srcHead->reserved1 */
164 /* Don't swap srcHead->btreeType */
165 /* Don't swap srcHead->reserved2 */
166 /* Don't swap srcHead->reserved3 */
167 /* Don't swap bitmap */
170 /* If we are doing an unswap */
172 /* Swap the node descriptor */
173 srcDesc
->fLink
= SWAP_BE32 (srcDesc
->fLink
);
174 srcDesc
->bLink
= SWAP_BE32 (srcDesc
->bLink
);
176 /* Don't swap srcDesc->kind */
177 /* Don't swap srcDesc->height */
178 /* Don't swap srcDesc->reserved */
180 /* Swap the node offsets (including the free space one!) */
181 srcOffs
= (UInt16
*)((char *)src
->buffer
+ (src
->blockSize
- ((srcDesc
->numRecords
+ 1) * sizeof (UInt16
))));
184 if ((char *)srcOffs
> ((char *)src
->buffer
+ src
->blockSize
)) {
185 panic ("%s Too many records in the B-Tree node", "hfs_swap_BTNode:");
188 for (i
= 0; i
< srcDesc
->numRecords
+ 1; i
++) {
190 if (srcOffs
[i
] >= src
->blockSize
) {
191 panic ("%s B-Tree node offset out of range", "hfs_swap_BTNode:");
194 srcOffs
[i
] = SWAP_BE16 (srcOffs
[i
]);
197 srcDesc
->numRecords
= SWAP_BE16 (srcDesc
->numRecords
);
204 hfs_swap_HFSPlusBTInternalNode (
205 BlockDescriptor
*src
,
206 HFSCatalogNodeID fileID
,
210 BTNodeDescriptor
*srcDesc
= src
->buffer
;
211 UInt16
*srcOffs
= (UInt16
*)((char *)src
->buffer
+ (src
->blockSize
- (srcDesc
->numRecords
* sizeof (UInt16
))));
216 if (fileID
== kHFSExtentsFileID
) {
217 HFSPlusExtentKey
*srcKey
;
218 HFSPlusExtentDescriptor
*srcRec
;
220 for (i
= 0; i
< srcDesc
->numRecords
; i
++) {
221 srcKey
= (HFSPlusExtentKey
*)((char *)src
->buffer
+ srcOffs
[i
]);
223 if (!unswap
) srcKey
->keyLength
= SWAP_BE16 (srcKey
->keyLength
);
224 srcRec
= (HFSPlusExtentDescriptor
*)((char *)srcKey
+ srcKey
->keyLength
+ 2);
225 if (unswap
) srcKey
->keyLength
= SWAP_BE16 (srcKey
->keyLength
);
227 /* Don't swap srcKey->forkType */
228 /* Don't swap srcKey->pad */
230 srcKey
->fileID
= SWAP_BE32 (srcKey
->fileID
);
231 srcKey
->startBlock
= SWAP_BE32 (srcKey
->startBlock
);
233 /* Stop if this is just an index node */
234 if (srcDesc
->kind
== kBTIndexNode
) {
235 *((UInt32
*)srcRec
) = SWAP_BE32 (*((UInt32
*)srcRec
));
239 /* Swap the extent data */
241 /* Swap each extent */
242 for (j
= 0; j
< kHFSPlusExtentDensity
; j
++) {
243 srcRec
[j
].startBlock
= SWAP_BE32 (srcRec
[j
].startBlock
);
244 srcRec
[j
].blockCount
= SWAP_BE32 (srcRec
[j
].blockCount
);
248 } else if (fileID
== kHFSCatalogFileID
) {
249 HFSPlusCatalogKey
*srcKey
;
252 for (i
= 0; i
< srcDesc
->numRecords
; i
++) {
253 srcKey
= (HFSPlusCatalogKey
*)((char *)src
->buffer
+ srcOffs
[i
]);
255 if (!unswap
) srcKey
->keyLength
= SWAP_BE16 (srcKey
->keyLength
);
256 srcPtr
= (SInt16
*)((char *)srcKey
+ srcKey
->keyLength
+ 2);
257 if (unswap
) srcKey
->keyLength
= SWAP_BE16 (srcKey
->keyLength
);
259 srcKey
->parentID
= SWAP_BE32 (srcKey
->parentID
);
261 if (!unswap
) srcKey
->nodeName
.length
= SWAP_BE16 (srcKey
->nodeName
.length
);
262 for (j
= 0; j
< srcKey
->nodeName
.length
; j
++) {
263 srcKey
->nodeName
.unicode
[j
] = SWAP_BE16 (srcKey
->nodeName
.unicode
[j
]);
265 if (unswap
) srcKey
->nodeName
.length
= SWAP_BE16 (srcKey
->nodeName
.length
);
267 /* Stop if this is just an index node */
268 if (srcDesc
->kind
== kBTIndexNode
) {
269 *((UInt32
*)srcPtr
) = SWAP_BE32 (*((UInt32
*)srcPtr
));
273 /* Swap the recordType field, if unswapping, leave to later */
274 if (!unswap
) srcPtr
[0] = SWAP_BE16 (srcPtr
[0]);
276 if (srcPtr
[0] == kHFSPlusFolderRecord
) {
277 HFSPlusCatalogFolder
*srcRec
= (HFSPlusCatalogFolder
*)srcPtr
;
279 srcRec
->flags
= SWAP_BE16 (srcRec
->flags
);
280 srcRec
->valence
= SWAP_BE32 (srcRec
->valence
);
281 srcRec
->folderID
= SWAP_BE32 (srcRec
->folderID
);
282 srcRec
->createDate
= SWAP_BE32 (srcRec
->createDate
);
283 srcRec
->contentModDate
= SWAP_BE32 (srcRec
->contentModDate
);
284 srcRec
->attributeModDate
= SWAP_BE32 (srcRec
->attributeModDate
);
285 srcRec
->accessDate
= SWAP_BE32 (srcRec
->accessDate
);
286 srcRec
->backupDate
= SWAP_BE32 (srcRec
->backupDate
);
288 srcRec
->bsdInfo
.ownerID
= SWAP_BE32 (srcRec
->bsdInfo
.ownerID
);
289 srcRec
->bsdInfo
.groupID
= SWAP_BE32 (srcRec
->bsdInfo
.groupID
);
291 /* Don't swap srcRec->bsdInfo.adminFlags */
292 /* Don't swap srcRec->bsdInfo.ownerFlags */
294 srcRec
->bsdInfo
.fileMode
= SWAP_BE16 (srcRec
->bsdInfo
.fileMode
);
295 srcRec
->bsdInfo
.special
.iNodeNum
= SWAP_BE32 (srcRec
->bsdInfo
.special
.iNodeNum
);
297 srcRec
->textEncoding
= SWAP_BE32 (srcRec
->textEncoding
);
299 /* Don't swap srcRec->userInfo */
300 /* Don't swap srcRec->finderInfo */
301 /* Don't swap srcRec->reserved */
303 } else if (srcPtr
[0] == kHFSPlusFileRecord
) {
304 HFSPlusCatalogFile
*srcRec
= (HFSPlusCatalogFile
*)srcPtr
;
306 srcRec
->flags
= SWAP_BE16 (srcRec
->flags
);
308 srcRec
->fileID
= SWAP_BE32 (srcRec
->fileID
);
310 srcRec
->createDate
= SWAP_BE32 (srcRec
->createDate
);
311 srcRec
->contentModDate
= SWAP_BE32 (srcRec
->contentModDate
);
312 srcRec
->attributeModDate
= SWAP_BE32 (srcRec
->attributeModDate
);
313 srcRec
->accessDate
= SWAP_BE32 (srcRec
->accessDate
);
314 srcRec
->backupDate
= SWAP_BE32 (srcRec
->backupDate
);
316 srcRec
->bsdInfo
.ownerID
= SWAP_BE32 (srcRec
->bsdInfo
.ownerID
);
317 srcRec
->bsdInfo
.groupID
= SWAP_BE32 (srcRec
->bsdInfo
.groupID
);
319 /* Don't swap srcRec->bsdInfo.adminFlags */
320 /* Don't swap srcRec->bsdInfo.ownerFlags */
322 srcRec
->bsdInfo
.fileMode
= SWAP_BE16 (srcRec
->bsdInfo
.fileMode
);
323 srcRec
->bsdInfo
.special
.iNodeNum
= SWAP_BE32 (srcRec
->bsdInfo
.special
.iNodeNum
);
325 srcRec
->textEncoding
= SWAP_BE32 (srcRec
->textEncoding
);
327 /* Don't swap srcRec->reserved1 */
328 /* Don't swap srcRec->userInfo */
329 /* Don't swap srcRec->finderInfo */
330 /* Don't swap srcRec->reserved2 */
332 hfs_swap_HFSPlusForkData (&srcRec
->dataFork
);
333 hfs_swap_HFSPlusForkData (&srcRec
->resourceFork
);
335 } else if ((srcPtr
[0] == kHFSPlusFolderThreadRecord
) ||
336 (srcPtr
[0] == kHFSPlusFileThreadRecord
)) {
338 HFSPlusCatalogThread
*srcRec
= (HFSPlusCatalogThread
*)srcPtr
;
340 /* Don't swap srcRec->reserved */
342 srcRec
->parentID
= SWAP_BE32 (srcRec
->parentID
);
344 if (!unswap
) srcRec
->nodeName
.length
= SWAP_BE16 (srcRec
->nodeName
.length
);
345 for (j
= 0; j
< srcRec
->nodeName
.length
; j
++) {
346 srcRec
->nodeName
.unicode
[j
] = SWAP_BE16 (srcRec
->nodeName
.unicode
[j
]);
348 if (unswap
) srcRec
->nodeName
.length
= SWAP_BE16 (srcRec
->nodeName
.length
);
351 panic ("%s unrecognized catalog record type", "hfs_swap_BTNode:");
354 /* If unswapping, we can safely unswap type field now */
355 if (unswap
) srcPtr
[0] = SWAP_BE16 (srcPtr
[0]);
359 panic ("%s unrecognized B-Tree type", "hfs_swap_BTNode:");
366 hfs_swap_HFSBTInternalNode (
367 BlockDescriptor
*src
,
368 HFSCatalogNodeID fileID
,
372 BTNodeDescriptor
*srcDesc
= src
->buffer
;
373 UInt16
*srcOffs
= (UInt16
*)((char *)src
->buffer
+ (src
->blockSize
- (srcDesc
->numRecords
* sizeof (UInt16
))));
378 if (fileID
== kHFSExtentsFileID
) {
379 HFSExtentKey
*srcKey
;
380 HFSExtentDescriptor
*srcRec
;
382 for (i
= 0; i
< srcDesc
->numRecords
; i
++) {
383 srcKey
= (HFSExtentKey
*)((char *)src
->buffer
+ srcOffs
[i
]);
385 /* Don't swap srcKey->keyLength */
386 /* Don't swap srcKey->forkType */
388 srcKey
->fileID
= SWAP_BE32 (srcKey
->fileID
);
389 srcKey
->startBlock
= SWAP_BE16 (srcKey
->startBlock
);
391 /* Point to record data (round up to even byte boundary) */
392 srcRec
= (HFSExtentDescriptor
*)((char *)srcKey
+ ((srcKey
->keyLength
+ 2) & ~1));
394 /* Stop if this is just an index node */
395 if (srcDesc
->kind
== kBTIndexNode
) {
396 *((UInt32
*)srcRec
) = SWAP_BE32 (*((UInt32
*)srcRec
));
400 /* Swap each extent */
401 for (j
= 0; j
< kHFSExtentDensity
; j
++) {
402 srcRec
[j
].startBlock
= SWAP_BE16 (srcRec
[j
].startBlock
);
403 srcRec
[j
].blockCount
= SWAP_BE16 (srcRec
[j
].blockCount
);
407 } else if (fileID
== kHFSCatalogFileID
) {
408 HFSCatalogKey
*srcKey
;
411 for (i
= 0; i
< srcDesc
->numRecords
; i
++) {
412 srcKey
= (HFSCatalogKey
*)((char *)src
->buffer
+ srcOffs
[i
]);
414 /* Don't swap srcKey->keyLength */
415 /* Don't swap srcKey->reserved */
417 srcKey
->parentID
= SWAP_BE32 (srcKey
->parentID
);
419 /* Don't swap srcKey->nodeName */
421 /* Point to record data (round up to even byte boundary) */
422 srcPtr
= (SInt16
*)((char *)srcKey
+ ((srcKey
->keyLength
+ 2) & ~1));
424 /* Stop if this is just an index node */
425 if (srcDesc
->kind
== kBTIndexNode
) {
426 *((UInt32
*)srcPtr
) = SWAP_BE32 (*((UInt32
*)srcPtr
));
430 /* Swap the recordType field, if unswapping, leave to later */
431 if (!unswap
) srcPtr
[0] = SWAP_BE16 (srcPtr
[0]);
433 if (srcPtr
[0] == kHFSFolderRecord
) {
434 HFSCatalogFolder
*srcRec
= (HFSCatalogFolder
*)srcPtr
;
436 srcRec
->flags
= SWAP_BE16 (srcRec
->flags
);
437 srcRec
->valence
= SWAP_BE16 (srcRec
->valence
);
439 srcRec
->folderID
= SWAP_BE32 (srcRec
->folderID
);
440 srcRec
->createDate
= SWAP_BE32 (srcRec
->createDate
);
441 srcRec
->modifyDate
= SWAP_BE32 (srcRec
->modifyDate
);
442 srcRec
->backupDate
= SWAP_BE32 (srcRec
->backupDate
);
444 /* Don't swap srcRec->userInfo */
445 /* Don't swap srcRec->finderInfo */
446 /* Don't swap resserved array */
448 } else if (srcPtr
[0] == kHFSFileRecord
) {
449 HFSCatalogFile
*srcRec
= (HFSCatalogFile
*)srcPtr
;
451 srcRec
->flags
= srcRec
->flags
;
452 srcRec
->fileType
= srcRec
->fileType
;
454 /* Don't swap srcRec->userInfo */
456 srcRec
->fileID
= SWAP_BE32 (srcRec
->fileID
);
458 srcRec
->dataStartBlock
= SWAP_BE16 (srcRec
->dataStartBlock
);
459 srcRec
->dataLogicalSize
= SWAP_BE32 (srcRec
->dataLogicalSize
);
460 srcRec
->dataPhysicalSize
= SWAP_BE32 (srcRec
->dataPhysicalSize
);
462 srcRec
->rsrcStartBlock
= SWAP_BE16 (srcRec
->rsrcStartBlock
);
463 srcRec
->rsrcLogicalSize
= SWAP_BE32 (srcRec
->rsrcLogicalSize
);
464 srcRec
->rsrcPhysicalSize
= SWAP_BE32 (srcRec
->rsrcPhysicalSize
);
466 srcRec
->createDate
= SWAP_BE32 (srcRec
->createDate
);
467 srcRec
->modifyDate
= SWAP_BE32 (srcRec
->modifyDate
);
468 srcRec
->backupDate
= SWAP_BE32 (srcRec
->backupDate
);
470 /* Don't swap srcRec->finderInfo */
472 srcRec
->clumpSize
= SWAP_BE16 (srcRec
->clumpSize
);
474 /* Swap the two sets of extents as an array of six (three each) UInt16 */
475 for (j
= 0; j
< kHFSExtentDensity
* 2; j
++) {
476 srcRec
->dataExtents
[j
].startBlock
= SWAP_BE16 (srcRec
->dataExtents
[j
].startBlock
);
477 srcRec
->dataExtents
[j
].blockCount
= SWAP_BE16 (srcRec
->dataExtents
[j
].blockCount
);
480 /* Don't swap srcRec->reserved */
482 } else if ((srcPtr
[0] == kHFSFolderThreadRecord
) ||
483 (srcPtr
[0] == kHFSFileThreadRecord
)) {
485 HFSCatalogThread
*srcRec
= (HFSCatalogThread
*)srcPtr
;
487 /* Don't swap srcRec->reserved array */
489 srcRec
->parentID
= SWAP_BE32 (srcRec
->parentID
);
491 /* Don't swap srcRec->nodeName */
494 panic ("%s unrecognized catalog record type", "hfs_swap_BTNode:");
497 /* If unswapping, we can safely swap type now */
498 if (unswap
) srcPtr
[0] = SWAP_BE16 (srcPtr
[0]);
502 panic ("%s unrecognized B-Tree type", "hfs_swap_BTNode:");