2
* Copyright (c) 2000,2005 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
31
#include <sys/types.h>
34
#include <architecture/byte_order.h>
35
#include <hfs/hfs_format.h>
37
#include "Scavenger.h"
38
#include "BTreePrivate.h"
39
#include "hfs_endian.h"
40
#include "../fsck_hfs.h"
45
* Internal swapping routines
47
* These routines handle swapping the records of leaf and index nodes. The
48
* layout of the keys and records varies depending on the kind of B-tree
49
* (determined by fileID).
51
* The direction parameter must be kSwapBTNodeBigToHost or kSwapBTNodeHostToBig.
52
* The kSwapBTNodeHeaderRecordOnly "direction" is not valid for these routines.
54
static int hfs_swap_HFSPlusBTInternalNode (BlockDescriptor *src, SFCB *fcb, enum HFSBTSwapDirection direction);
55
static int hfs_swap_HFSBTInternalNode (BlockDescriptor *src, SFCB *fcb, enum HFSBTSwapDirection direction);
58
* hfs_swap_HFSPlusForkData
61
hfs_swap_HFSPlusForkData (
67
src->logicalSize = SWAP_BE64 (src->logicalSize);
69
src->clumpSize = SWAP_BE32 (src->clumpSize);
70
src->totalBlocks = SWAP_BE32 (src->totalBlocks);
72
for (i = 0; i < kHFSPlusExtentDensity; i++) {
73
src->extents[i].startBlock = SWAP_BE32 (src->extents[i].startBlock);
74
src->extents[i].blockCount = SWAP_BE32 (src->extents[i].blockCount);
79
* hfs_swap_HFSMasterDirectoryBlock
81
* Specially modified to swap parts of the finder info
84
hfs_swap_HFSMasterDirectoryBlock (
88
HFSMasterDirectoryBlock *src = (HFSMasterDirectoryBlock *)buf;
90
src->drSigWord = SWAP_BE16 (src->drSigWord);
91
src->drCrDate = SWAP_BE32 (src->drCrDate);
92
src->drLsMod = SWAP_BE32 (src->drLsMod);
93
src->drAtrb = SWAP_BE16 (src->drAtrb);
94
src->drNmFls = SWAP_BE16 (src->drNmFls);
95
src->drVBMSt = SWAP_BE16 (src->drVBMSt);
96
src->drAllocPtr = SWAP_BE16 (src->drAllocPtr);
97
src->drNmAlBlks = SWAP_BE16 (src->drNmAlBlks);
98
src->drAlBlkSiz = SWAP_BE32 (src->drAlBlkSiz);
99
src->drClpSiz = SWAP_BE32 (src->drClpSiz);
100
src->drAlBlSt = SWAP_BE16 (src->drAlBlSt);
101
src->drNxtCNID = SWAP_BE32 (src->drNxtCNID);
102
src->drFreeBks = SWAP_BE16 (src->drFreeBks);
104
/* Don't swap drVN */
106
src->drVolBkUp = SWAP_BE32 (src->drVolBkUp);
107
src->drVSeqNum = SWAP_BE16 (src->drVSeqNum);
108
src->drWrCnt = SWAP_BE32 (src->drWrCnt);
109
src->drXTClpSiz = SWAP_BE32 (src->drXTClpSiz);
110
src->drCTClpSiz = SWAP_BE32 (src->drCTClpSiz);
111
src->drNmRtDirs = SWAP_BE16 (src->drNmRtDirs);
112
src->drFilCnt = SWAP_BE32 (src->drFilCnt);
113
src->drDirCnt = SWAP_BE32 (src->drDirCnt);
115
/* Swap just the 'blessed folder' in drFndrInfo */
116
src->drFndrInfo[0] = SWAP_BE32 (src->drFndrInfo[0]);
118
src->drEmbedSigWord = SWAP_BE16 (src->drEmbedSigWord);
119
src->drEmbedExtent.startBlock = SWAP_BE16 (src->drEmbedExtent.startBlock);
120
src->drEmbedExtent.blockCount = SWAP_BE16 (src->drEmbedExtent.blockCount);
122
src->drXTFlSize = SWAP_BE32 (src->drXTFlSize);
123
src->drXTExtRec[0].startBlock = SWAP_BE16 (src->drXTExtRec[0].startBlock);
124
src->drXTExtRec[0].blockCount = SWAP_BE16 (src->drXTExtRec[0].blockCount);
125
src->drXTExtRec[1].startBlock = SWAP_BE16 (src->drXTExtRec[1].startBlock);
126
src->drXTExtRec[1].blockCount = SWAP_BE16 (src->drXTExtRec[1].blockCount);
127
src->drXTExtRec[2].startBlock = SWAP_BE16 (src->drXTExtRec[2].startBlock);
128
src->drXTExtRec[2].blockCount = SWAP_BE16 (src->drXTExtRec[2].blockCount);
130
src->drCTFlSize = SWAP_BE32 (src->drCTFlSize);
131
src->drCTExtRec[0].startBlock = SWAP_BE16 (src->drCTExtRec[0].startBlock);
132
src->drCTExtRec[0].blockCount = SWAP_BE16 (src->drCTExtRec[0].blockCount);
133
src->drCTExtRec[1].startBlock = SWAP_BE16 (src->drCTExtRec[1].startBlock);
134
src->drCTExtRec[1].blockCount = SWAP_BE16 (src->drCTExtRec[1].blockCount);
135
src->drCTExtRec[2].startBlock = SWAP_BE16 (src->drCTExtRec[2].startBlock);
136
src->drCTExtRec[2].blockCount = SWAP_BE16 (src->drCTExtRec[2].blockCount);
140
* hfs_swap_HFSPlusVolumeHeader
143
hfs_swap_HFSPlusVolumeHeader (
147
HFSPlusVolumeHeader *src = (HFSPlusVolumeHeader *)buf;
149
src->signature = SWAP_BE16 (src->signature);
150
src->version = SWAP_BE16 (src->version);
151
src->attributes = SWAP_BE32 (src->attributes);
152
src->lastMountedVersion = SWAP_BE32 (src->lastMountedVersion);
154
/* Don't swap reserved */
156
src->createDate = SWAP_BE32 (src->createDate);
157
src->modifyDate = SWAP_BE32 (src->modifyDate);
158
src->backupDate = SWAP_BE32 (src->backupDate);
159
src->checkedDate = SWAP_BE32 (src->checkedDate);
160
src->fileCount = SWAP_BE32 (src->fileCount);
161
src->folderCount = SWAP_BE32 (src->folderCount);
162
src->blockSize = SWAP_BE32 (src->blockSize);
163
src->totalBlocks = SWAP_BE32 (src->totalBlocks);
164
src->freeBlocks = SWAP_BE32 (src->freeBlocks);
165
src->nextAllocation = SWAP_BE32 (src->nextAllocation);
166
src->rsrcClumpSize = SWAP_BE32 (src->rsrcClumpSize);
167
src->dataClumpSize = SWAP_BE32 (src->dataClumpSize);
168
src->nextCatalogID = SWAP_BE32 (src->nextCatalogID);
169
src->writeCount = SWAP_BE32 (src->writeCount);
170
src->encodingsBitmap = SWAP_BE64 (src->encodingsBitmap);
172
/* Don't swap finderInfo */
174
hfs_swap_HFSPlusForkData (&src->allocationFile);
175
hfs_swap_HFSPlusForkData (&src->extentsFile);
176
hfs_swap_HFSPlusForkData (&src->catalogFile);
177
hfs_swap_HFSPlusForkData (&src->attributesFile);
178
hfs_swap_HFSPlusForkData (&src->startupFile);
184
* NOTE: This operation is not naturally symmetric.
185
* We have to determine which way we're swapping things.
189
BlockDescriptor *src,
191
enum HFSBTSwapDirection direction
194
BTNodeDescriptor *srcDesc = src->buffer;
195
BTreeControlBlockPtr btcb = fcb->fcbBtree;
196
UInt16 *srcOffs = NULL;
200
// WriteError(fcb->fcbVolume->vcbGPtr, E_BadNode, fcb->fcbFileID, src->blockNum);
203
if (direction == kSwapBTNodeBigToHost) {
204
printf ("BE -> Native Swap\n");
205
} else if (direction == kSwapBTNodeHostToBig) {
206
printf ("Native -> BE Swap\n");
207
} else if (direction == kSwapBTNodeHeaderRecordOnly) {
208
printf ("Not swapping descriptors\n");
210
printf ("hfs_swap_BTNode: This is impossible");
216
* If we are doing a swap from on-disk to in-memory, then swap the node
217
* descriptor and record offsets before we need to use them.
219
if (direction == kSwapBTNodeBigToHost) {
220
srcDesc->fLink = SWAP_BE32 (srcDesc->fLink);
221
srcDesc->bLink = SWAP_BE32 (srcDesc->bLink);
222
if (srcDesc->fLink >= btcb->totalNodes) {
223
if (debug) printf("hfs_swap_BTNode: invalid forward link (0x%08X)\n", srcDesc->fLink);
225
if (srcDesc->bLink >= btcb->totalNodes) {
226
if (debug) printf("hfs_swap_BTNode: invalid backward link (0x%08X)\n", srcDesc->bLink);
230
* Don't swap srcDesc->kind or srcDesc->height because they are only one byte.
231
* We don't check them here because the upper layers will check (and possibly
232
* repair) them more effectively.
234
if (srcDesc->kind < kBTLeafNode || srcDesc->kind > kBTMapNode) {
235
if (debug) printf("hfs_swap_BTNode: invalid node kind (%d)\n", srcDesc->kind);
237
if (srcDesc->height > btcb->treeDepth) {
238
if (debug) printf("hfs_swap_BTNode: invalid node height (%d)\n", srcDesc->height);
241
/* Don't swap srcDesc->reserved */
243
srcDesc->numRecords = SWAP_BE16 (srcDesc->numRecords);
246
* Swap the node offsets (including the free space one!).
248
srcOffs = (UInt16 *)((char *)src->buffer + (src->blockSize - ((srcDesc->numRecords + 1) * sizeof (UInt16))));
251
* Sanity check that the record offsets are within the node itself.
253
if ((char *)srcOffs > ((char *)src->buffer + src->blockSize) ||
254
(char *)srcOffs < ((char *)src->buffer + sizeof(BTNodeDescriptor))) {
255
if (debug) printf("hfs_swap_BTNode: invalid record count (0x%04X)\n", srcDesc->numRecords);
256
WriteError(fcb->fcbVolume->vcbGPtr, E_NRecs, fcb->fcbFileID, src->blockNum);
262
* Swap and sanity check each of the record offsets.
264
for (i = 0; i <= srcDesc->numRecords; i++) {
265
srcOffs[i] = SWAP_BE16 (srcOffs[i]);
268
* Sanity check: must be even, and within the node itself.
270
* We may be called to swap an unused node, which contains all zeroes.
271
* This is why we allow the record offset to be zero.
273
if ((srcOffs[i] & 1) || (srcOffs[i] < sizeof(BTNodeDescriptor) && srcOffs[i] != 0) || (srcOffs[i] >= src->blockSize)) {
274
if (debug) printf("hfs_swap_BTNode: record #%d invalid offset (0x%04X)\n", srcDesc->numRecords-i-1, srcOffs[i]);
275
WriteError(fcb->fcbVolume->vcbGPtr, E_BadNode, fcb->fcbFileID, src->blockNum);
281
* Make sure the offsets are strictly increasing. Note that we're looping over
282
* them backwards, hence the order in the comparison.
284
if ((i != 0) && (srcOffs[i] >= srcOffs[i-1])) {
285
if (debug) printf("hfs_swap_BTNode: offsets %d and %d out of order (0x%04X, 0x%04X)\n",
286
srcDesc->numRecords-i-1, srcDesc->numRecords-i, srcOffs[i], srcOffs[i-1]);
287
WriteError(fcb->fcbVolume->vcbGPtr, E_BadNode, fcb->fcbFileID, src->blockNum);
295
* Swap the records (ordered by frequency of access)
297
if ((srcDesc->kind == kBTIndexNode) ||
298
(srcDesc-> kind == kBTLeafNode)) {
300
if (fcb->fcbVolume->vcbSignature == kHFSPlusSigWord) {
301
error = hfs_swap_HFSPlusBTInternalNode (src, fcb, direction);
303
error = hfs_swap_HFSBTInternalNode (src, fcb, direction);
306
if (error) goto fail;
308
} else if (srcDesc-> kind == kBTMapNode) {
309
/* Don't swap the bitmaps, they'll be done in the bitmap routines */
311
} else if (srcDesc-> kind == kBTHeaderNode) {
312
/* The header's offset is hard-wired because we cannot trust the offset pointers. */
313
BTHeaderRec *srcHead = (BTHeaderRec *)((char *)src->buffer + sizeof(BTNodeDescriptor));
315
srcHead->treeDepth = SWAP_BE16 (srcHead->treeDepth);
317
srcHead->rootNode = SWAP_BE32 (srcHead->rootNode);
318
srcHead->leafRecords = SWAP_BE32 (srcHead->leafRecords);
319
srcHead->firstLeafNode = SWAP_BE32 (srcHead->firstLeafNode);
320
srcHead->lastLeafNode = SWAP_BE32 (srcHead->lastLeafNode);
322
srcHead->nodeSize = SWAP_BE16 (srcHead->nodeSize);
323
srcHead->maxKeyLength = SWAP_BE16 (srcHead->maxKeyLength);
325
srcHead->totalNodes = SWAP_BE32 (srcHead->totalNodes);
326
srcHead->freeNodes = SWAP_BE32 (srcHead->freeNodes);
328
srcHead->clumpSize = SWAP_BE32 (srcHead->clumpSize);
329
srcHead->attributes = SWAP_BE32 (srcHead->attributes);
331
/* Don't swap srcHead->reserved1 */
332
/* Don't swap srcHead->btreeType; it's only one byte */
333
/* Don't swap srcHead->reserved2 */
334
/* Don't swap srcHead->reserved3 */
335
/* Don't swap bitmap */
337
/* Else: other node kinds will be caught by upper layers */
340
* If we are doing a swap from in-memory to on-disk, then swap the node
341
* descriptor and record offsets after we're done using them.
343
if (direction == kSwapBTNodeHostToBig) {
345
* Swap the forkward and backward links.
347
if (srcDesc->fLink >= btcb->totalNodes) {
348
if (debug) printf("hfs_UNswap_BTNode: invalid forward link (0x%08X)\n", srcDesc->fLink);
350
if (srcDesc->bLink >= btcb->totalNodes) {
351
if (debug) printf("hfs_UNswap_BTNode: invalid backward link (0x%08X)\n", srcDesc->bLink);
353
srcDesc->fLink = SWAP_BE32 (srcDesc->fLink);
354
srcDesc->bLink = SWAP_BE32 (srcDesc->bLink);
357
* Don't swap srcDesc->kind or srcDesc->height because they are only one byte.
358
* We don't check them here because the upper layers will check (and possibly
359
* repair) them more effectively.
361
if (srcDesc->kind < kBTLeafNode || srcDesc->kind > kBTMapNode) {
362
if (debug) printf("hfs_UNswap_BTNode: invalid node kind (%d)\n", srcDesc->kind);
364
if (srcDesc->height > btcb->treeDepth) {
365
if (debug) printf("hfs_UNswap_BTNode: invalid node height (%d)\n", srcDesc->height);
368
/* Don't swap srcDesc->reserved */
371
* Swap the node offsets (including the free space one!).
373
srcOffs = (UInt16 *)((char *)src->buffer + (src->blockSize - ((srcDesc->numRecords + 1) * sizeof (UInt16))));
376
* Sanity check that the record offsets are within the node itself.
378
if ((char *)srcOffs > ((char *)src->buffer + src->blockSize) ||
379
(char *)srcOffs < ((char *)src->buffer + sizeof(BTNodeDescriptor))) {
380
if (debug) printf("hfs_UNswap_BTNode: invalid record count (0x%04X)\n", srcDesc->numRecords);
381
WriteError(fcb->fcbVolume->vcbGPtr, E_NRecs, fcb->fcbFileID, src->blockNum);
387
* Swap and sanity check each of the record offsets.
389
for (i = 0; i <= srcDesc->numRecords; i++) {
391
* Sanity check: must be even, and within the node itself.
393
* We may be called to swap an unused node, which contains all zeroes.
394
* This is why we allow the record offset to be zero.
396
if ((srcOffs[i] & 1) || (srcOffs[i] < sizeof(BTNodeDescriptor) && srcOffs[i] != 0) || (srcOffs[i] >= src->blockSize)) {
397
if (debug) printf("hfs_UNswap_BTNode: record #%d invalid offset (0x%04X)\n", srcDesc->numRecords-i-1, srcOffs[i]);
398
WriteError(fcb->fcbVolume->vcbGPtr, E_BadNode, fcb->fcbFileID, src->blockNum);
404
* Make sure the offsets are strictly increasing. Note that we're looping over
405
* them backwards, hence the order in the comparison.
407
if ((i < srcDesc->numRecords) && (srcOffs[i+1] >= srcOffs[i])) {
408
if (debug) printf("hfs_UNswap_BTNode: offsets %d and %d out of order (0x%04X, 0x%04X)\n",
409
srcDesc->numRecords-i-2, srcDesc->numRecords-i-1, srcOffs[i+1], srcOffs[i]);
410
WriteError(fcb->fcbVolume->vcbGPtr, E_BadNode, fcb->fcbFileID, src->blockNum);
415
srcOffs[i] = SWAP_BE16 (srcOffs[i]);
418
srcDesc->numRecords = SWAP_BE16 (srcDesc->numRecords);
426
hfs_swap_HFSPlusBTInternalNode (
427
BlockDescriptor *src,
429
enum HFSBTSwapDirection direction
432
HFSCatalogNodeID fileID =fcb->fcbFileID;
433
BTNodeDescriptor *srcDesc = src->buffer;
434
UInt16 *srcOffs = (UInt16 *)((char *)src->buffer + (src->blockSize - (srcDesc->numRecords * sizeof (UInt16))));
435
char *nextRecord; /* Points to start of record following current one */
439
if (fileID == kHFSExtentsFileID) {
440
HFSPlusExtentKey *srcKey;
441
HFSPlusExtentDescriptor *srcRec;
442
size_t recordSize; /* Size of the data part of the record, or node number for index nodes */
444
if (srcDesc->kind == kBTIndexNode)
445
recordSize = sizeof(UInt32);
447
recordSize = sizeof(HFSPlusExtentDescriptor);
449
for (i = 0; i < srcDesc->numRecords; i++) {
450
/* Point to the start of the record we're currently checking. */
451
srcKey = (HFSPlusExtentKey *)((char *)src->buffer + srcOffs[i]);
454
* Point to start of next (larger offset) record. We'll use this
455
* to be sure the current record doesn't overflow into the next
458
nextRecord = (char *)src->buffer + srcOffs[i-1];
461
* Make sure the key and data are within the buffer. Since both key
462
* and data are fixed size, this is relatively easy. Note that this
463
* relies on the keyLength being a constant; we verify the keyLength
466
if ((char *)srcKey + sizeof(HFSPlusExtentKey) + recordSize > nextRecord) {
467
if (debug) printf("hfs_swap_HFSPlusBTInternalNode: extents key #%d offset too big (0x%04X)\n", srcDesc->numRecords-i-1, srcOffs[i]);
468
WriteError(fcb->fcbVolume->vcbGPtr, E_BadNode, fcb->fcbFileID, src->blockNum);
472
if (direction == kSwapBTNodeBigToHost)
473
srcKey->keyLength = SWAP_BE16 (srcKey->keyLength);
474
if (srcKey->keyLength != sizeof(*srcKey) - sizeof(srcKey->keyLength)) {
475
if (debug) printf("hfs_swap_HFSPlusBTInternalNode: extents key #%d invalid length (%d)\n", srcDesc->numRecords-i-1, srcKey->keyLength);
476
WriteError(fcb->fcbVolume->vcbGPtr, E_KeyLen, fcb->fcbFileID, src->blockNum);
479
srcRec = (HFSPlusExtentDescriptor *)((char *)srcKey + srcKey->keyLength + sizeof(srcKey->keyLength));
480
if (direction == kSwapBTNodeHostToBig)
481
srcKey->keyLength = SWAP_BE16 (srcKey->keyLength);
483
/* Don't swap srcKey->forkType; it's only one byte */
484
/* Don't swap srcKey->pad */
486
srcKey->fileID = SWAP_BE32 (srcKey->fileID);
487
srcKey->startBlock = SWAP_BE32 (srcKey->startBlock);
489
if (srcDesc->kind == kBTIndexNode) {
490
/* For index nodes, the record data is just a child node number. */
491
*((UInt32 *)srcRec) = SWAP_BE32 (*((UInt32 *)srcRec));
493
/* Swap the extent data */
494
for (j = 0; j < kHFSPlusExtentDensity; j++) {
495
srcRec[j].startBlock = SWAP_BE32 (srcRec[j].startBlock);
496
srcRec[j].blockCount = SWAP_BE32 (srcRec[j].blockCount);
501
} else if (fileID == kHFSCatalogFileID || fileID == kHFSRepairCatalogFileID) {
502
HFSPlusCatalogKey *srcKey;
506
for (i = 0; i < srcDesc->numRecords; i++) {
507
/* Point to the start of the record we're currently checking. */
508
srcKey = (HFSPlusCatalogKey *)((char *)src->buffer + srcOffs[i]);
511
* Point to start of next (larger offset) record. We'll use this
512
* to be sure the current record doesn't overflow into the next
515
nextRecord = (char *)src->buffer + srcOffs[i-1];
518
* Make sure we can safely dereference the keyLength and parentID fields. */
519
if ((char *)srcKey + offsetof(HFSPlusCatalogKey, nodeName.unicode[0]) > nextRecord) {
520
if (debug) printf("hfs_swap_HFSPlusBTInternalNode: catalog key #%d offset too big (0x%04X)\n", srcDesc->numRecords-i-1, srcOffs[i]);
521
WriteError(fcb->fcbVolume->vcbGPtr, E_BadNode, fcb->fcbFileID, src->blockNum);
526
* Swap and sanity check the key length
528
if (direction == kSwapBTNodeBigToHost)
529
srcKey->keyLength = SWAP_BE16 (srcKey->keyLength);
530
keyLength = srcKey->keyLength; /* Put it in a local (native order) because we use it several times */
531
if (direction == kSwapBTNodeHostToBig)
532
srcKey->keyLength = SWAP_BE16 (keyLength);
534
/* Sanity check the key length */
535
if (keyLength < kHFSPlusCatalogKeyMinimumLength || keyLength > kHFSPlusCatalogKeyMaximumLength) {
536
if (debug) printf("hfs_swap_HFSPlusBTInternalNode: catalog key #%d invalid length (%d)\n", srcDesc->numRecords-i-1, keyLength);
537
WriteError(fcb->fcbVolume->vcbGPtr, E_KeyLen, fcb->fcbFileID, src->blockNum);
542
* Make sure that we can safely dereference the record's type field or
543
* an index node's child node number.
545
srcPtr = (SInt16 *)((char *)srcKey + keyLength + sizeof(srcKey->keyLength));
546
if ((char *)srcPtr + sizeof(UInt32) > nextRecord) {
547
if (debug) printf("hfs_swap_HFSPlusBTInternalNode: catalog key #%d too big\n", srcDesc->numRecords-i-1);
548
WriteError(fcb->fcbVolume->vcbGPtr, E_KeyLen, fcb->fcbFileID, src->blockNum);
552
srcKey->parentID = SWAP_BE32 (srcKey->parentID);
555
* Swap and sanity check the key's node name
557
if (direction == kSwapBTNodeBigToHost)
558
srcKey->nodeName.length = SWAP_BE16 (srcKey->nodeName.length);
559
/* Make sure name length is consistent with key length */
560
if (keyLength < sizeof(srcKey->parentID) + sizeof(srcKey->nodeName.length) +
561
srcKey->nodeName.length*sizeof(srcKey->nodeName.unicode[0])) {
562
if (debug) printf("hfs_swap_HFSPlusBTInternalNode: catalog record #%d keyLength=%d expected=%lu\n",
563
srcDesc->numRecords-i, keyLength, sizeof(srcKey->parentID) + sizeof(srcKey->nodeName.length) +
564
srcKey->nodeName.length*sizeof(srcKey->nodeName.unicode[0]));
565
WriteError(fcb->fcbVolume->vcbGPtr, E_KeyLen, fcb->fcbFileID, src->blockNum);
568
for (j = 0; j < srcKey->nodeName.length; j++) {
569
srcKey->nodeName.unicode[j] = SWAP_BE16 (srcKey->nodeName.unicode[j]);
571
if (direction == kSwapBTNodeHostToBig)
572
srcKey->nodeName.length = SWAP_BE16 (srcKey->nodeName.length);
575
* For index nodes, the record data is just the child's node number.
576
* Skip over swapping the various types of catalog record.
578
if (srcDesc->kind == kBTIndexNode) {
579
*((UInt32 *)srcPtr) = SWAP_BE32 (*((UInt32 *)srcPtr));
583
/* Make sure the recordType is in native order before using it. */
584
if (direction == kSwapBTNodeBigToHost)
585
srcPtr[0] = SWAP_BE16 (srcPtr[0]);
587
if (srcPtr[0] == kHFSPlusFolderRecord) {
588
HFSPlusCatalogFolder *srcRec = (HFSPlusCatalogFolder *)srcPtr;
589
if ((char *)srcRec + sizeof(*srcRec) > nextRecord) {
590
if (debug) printf("hfs_swap_HFSPlusBTInternalNode: catalog folder record #%d too big\n", srcDesc->numRecords-i-1);
591
WriteError(fcb->fcbVolume->vcbGPtr, E_BadNode, fcb->fcbFileID, src->blockNum);
595
srcRec->flags = SWAP_BE16 (srcRec->flags);
596
srcRec->valence = SWAP_BE32 (srcRec->valence);
597
srcRec->folderID = SWAP_BE32 (srcRec->folderID);
598
srcRec->createDate = SWAP_BE32 (srcRec->createDate);
599
srcRec->contentModDate = SWAP_BE32 (srcRec->contentModDate);
600
srcRec->attributeModDate = SWAP_BE32 (srcRec->attributeModDate);
601
srcRec->accessDate = SWAP_BE32 (srcRec->accessDate);
602
srcRec->backupDate = SWAP_BE32 (srcRec->backupDate);
604
srcRec->bsdInfo.ownerID = SWAP_BE32 (srcRec->bsdInfo.ownerID);
605
srcRec->bsdInfo.groupID = SWAP_BE32 (srcRec->bsdInfo.groupID);
607
/* Don't swap srcRec->bsdInfo.adminFlags; it's only one byte */
608
/* Don't swap srcRec->bsdInfo.ownerFlags; it's only one byte */
610
srcRec->bsdInfo.fileMode = SWAP_BE16 (srcRec->bsdInfo.fileMode);
611
srcRec->bsdInfo.special.iNodeNum = SWAP_BE32 (srcRec->bsdInfo.special.iNodeNum);
613
srcRec->textEncoding = SWAP_BE32 (srcRec->textEncoding);
615
/* Don't swap srcRec->userInfo */
616
/* Don't swap srcRec->finderInfo */
617
/* Don't swap srcRec->reserved */
619
} else if (srcPtr[0] == kHFSPlusFileRecord) {
620
HFSPlusCatalogFile *srcRec = (HFSPlusCatalogFile *)srcPtr;
621
if ((char *)srcRec + sizeof(*srcRec) > nextRecord) {
622
if (debug) printf("hfs_swap_HFSPlusBTInternalNode: catalog file record #%d too big\n", srcDesc->numRecords-i-1);
623
return fsBTInvalidNodeErr;
626
srcRec->flags = SWAP_BE16 (srcRec->flags);
628
srcRec->fileID = SWAP_BE32 (srcRec->fileID);
630
srcRec->createDate = SWAP_BE32 (srcRec->createDate);
631
srcRec->contentModDate = SWAP_BE32 (srcRec->contentModDate);
632
srcRec->attributeModDate = SWAP_BE32 (srcRec->attributeModDate);
633
srcRec->accessDate = SWAP_BE32 (srcRec->accessDate);
634
srcRec->backupDate = SWAP_BE32 (srcRec->backupDate);
636
srcRec->bsdInfo.ownerID = SWAP_BE32 (srcRec->bsdInfo.ownerID);
637
srcRec->bsdInfo.groupID = SWAP_BE32 (srcRec->bsdInfo.groupID);
639
/* Don't swap srcRec->bsdInfo.adminFlags; it's only one byte */
640
/* Don't swap srcRec->bsdInfo.ownerFlags; it's only one byte */
642
srcRec->bsdInfo.fileMode = SWAP_BE16 (srcRec->bsdInfo.fileMode);
643
srcRec->bsdInfo.special.iNodeNum = SWAP_BE32 (srcRec->bsdInfo.special.iNodeNum);
645
srcRec->textEncoding = SWAP_BE32 (srcRec->textEncoding);
647
/* Don't swap srcRec->reserved1 */
648
/* Don't swap srcRec->userInfo */
649
/* Don't swap srcRec->finderInfo */
650
/* Don't swap srcRec->reserved2 */
652
hfs_swap_HFSPlusForkData (&srcRec->dataFork);
653
hfs_swap_HFSPlusForkData (&srcRec->resourceFork);
655
} else if ((srcPtr[0] == kHFSPlusFolderThreadRecord) ||
656
(srcPtr[0] == kHFSPlusFileThreadRecord)) {
659
* Make sure there is room for parentID and name length.
661
HFSPlusCatalogThread *srcRec = (HFSPlusCatalogThread *)srcPtr;
662
if ((char *) &srcRec->nodeName.unicode[0] > nextRecord) {
663
if (debug) printf("hfs_swap_HFSPlusBTInternalNode: catalog thread record #%d too big\n", srcDesc->numRecords-i-1);
664
WriteError(fcb->fcbVolume->vcbGPtr, E_BadNode, fcb->fcbFileID, src->blockNum);
668
/* Don't swap srcRec->reserved */
670
srcRec->parentID = SWAP_BE32 (srcRec->parentID);
672
if (direction == kSwapBTNodeBigToHost)
673
srcRec->nodeName.length = SWAP_BE16 (srcRec->nodeName.length);
676
* Make sure there is room for the name in the buffer.
677
* Then swap the characters of the name itself.
679
if ((char *) &srcRec->nodeName.unicode[srcRec->nodeName.length] > nextRecord) {
680
if (debug) printf("hfs_swap_HFSPlusBTInternalNode: catalog thread record #%d name too big\n", srcDesc->numRecords-i-1);
681
WriteError(fcb->fcbVolume->vcbGPtr, E_BadNode, fcb->fcbFileID, src->blockNum);
684
for (j = 0; j < srcRec->nodeName.length; j++) {
685
srcRec->nodeName.unicode[j] = SWAP_BE16 (srcRec->nodeName.unicode[j]);
688
if (direction == kSwapBTNodeHostToBig)
689
srcRec->nodeName.length = SWAP_BE16 (srcRec->nodeName.length);
692
if (debug) printf("hfs_swap_HFSPlusBTInternalNode: unrecognized catalog record type (0x%04X; record #%d)\n", srcPtr[0], srcDesc->numRecords-i-1);
695
/* We can swap the record type now that we're done using it. */
696
if (direction == kSwapBTNodeHostToBig)
697
srcPtr[0] = SWAP_BE16 (srcPtr[0]);
700
} else if (fileID == kHFSAttributesFileID) {
701
HFSPlusAttrKey *srcKey;
702
HFSPlusAttrRecord *srcRec;
704
u_int32_t attrSize = 0;
706
for (i = 0; i < srcDesc->numRecords; i++) {
707
/* Point to the start of the record we're currently checking. */
708
srcKey = (HFSPlusAttrKey *)((char *)src->buffer + srcOffs[i]);
711
* Point to start of next (larger offset) record. We'll use this
712
* to be sure the current record doesn't overflow into the next
715
nextRecord = (char *)src->buffer + srcOffs[i-1];
717
/* Make sure there is room in the buffer for a minimal key */
718
if ((char *) &srcKey->attrName[1] > nextRecord) {
719
if (debug) printf("hfs_swap_HFSPlusBTInternalNode: attr key #%d offset too big (0x%04X)\n", srcDesc->numRecords-i-1, srcOffs[i]);
720
WriteError(fcb->fcbVolume->vcbGPtr, E_BadNode, fcb->fcbFileID, src->blockNum);
724
/* Swap the key length field */
725
if (direction == kSwapBTNodeBigToHost)
726
srcKey->keyLength = SWAP_BE16(srcKey->keyLength);
727
keyLength = srcKey->keyLength; /* Keep a copy in native order */
728
if (direction == kSwapBTNodeHostToBig)
729
srcKey->keyLength = SWAP_BE16(srcKey->keyLength);
732
* Make sure that we can safely dereference the record's type field or
733
* an index node's child node number.
735
srcRec = (HFSPlusAttrRecord *)((char *)srcKey + keyLength + sizeof(srcKey->keyLength));
736
if ((char *)srcRec + sizeof(u_int32_t) > nextRecord) {
737
if (debug) printf("hfs_swap_HFSPlusBTInternalNode: attr key #%d too big (%d)\n", srcDesc->numRecords-i-1, keyLength);
738
WriteError(fcb->fcbVolume->vcbGPtr, E_KeyLen, fcb->fcbFileID, src->blockNum);
742
srcKey->fileID = SWAP_BE32(srcKey->fileID);
743
srcKey->startBlock = SWAP_BE32(srcKey->startBlock);
746
* Swap and check the attribute name
748
if (direction == kSwapBTNodeBigToHost)
749
srcKey->attrNameLen = SWAP_BE16(srcKey->attrNameLen);
750
/* Sanity check the attribute name length */
751
if (srcKey->attrNameLen > kHFSMaxAttrNameLen || keyLength < (kHFSPlusAttrKeyMinimumLength + sizeof(u_int16_t)*srcKey->attrNameLen)) {
752
if (debug) printf("hfs_swap_HFSPlusBTInternalNode: attr key #%d keyLength=%d attrNameLen=%d\n", srcDesc->numRecords-i-1, keyLength, srcKey->attrNameLen);
753
WriteError(fcb->fcbVolume->vcbGPtr, E_BadNode, fcb->fcbFileID, src->blockNum);
756
for (j = 0; j < srcKey->attrNameLen; j++)
757
srcKey->attrName[j] = SWAP_BE16(srcKey->attrName[j]);
758
if (direction == kSwapBTNodeHostToBig)
759
srcKey->attrNameLen = SWAP_BE16(srcKey->attrNameLen);
762
* For index nodes, the record data is just the child's node number.
763
* Skip over swapping the various types of attribute record.
765
if (srcDesc->kind == kBTIndexNode) {
766
*((UInt32 *)srcRec) = SWAP_BE32 (*((UInt32 *)srcRec));
770
/* Swap the record data */
771
if (direction == kSwapBTNodeBigToHost)
772
srcRec->recordType = SWAP_BE32(srcRec->recordType);
773
switch (srcRec->recordType) {
774
case kHFSPlusAttrInlineData:
775
/* Is there room for the inline data header? */
776
if ((char *) &srcRec->attrData.attrData[0] > nextRecord) {
777
if (debug) printf("hfs_swap_HFSPlusBTInternalNode: attr inline #%d too big\n", srcDesc->numRecords-i-1);
778
WriteError(fcb->fcbVolume->vcbGPtr, E_BadNode, fcb->fcbFileID, src->blockNum);
782
/* We're not swapping the reserved fields */
784
/* Swap the attribute size */
785
if (direction == kSwapBTNodeHostToBig)
786
attrSize = srcRec->attrData.attrSize;
787
srcRec->attrData.attrSize = SWAP_BE32(srcRec->attrData.attrSize);
788
if (direction == kSwapBTNodeBigToHost)
789
attrSize = srcRec->attrData.attrSize;
791
/* Is there room for the inline attribute data? */
792
if ((char *) &srcRec->attrData.attrData[attrSize] > nextRecord) {
793
if (debug) printf("hfs_swap_HFSPlusBTInternalNode: attr inline #%d too big (attrSize=%u)\n", srcDesc->numRecords-i-1, attrSize);
794
WriteError(fcb->fcbVolume->vcbGPtr, E_BadNode, fcb->fcbFileID, src->blockNum);
798
/* Not swapping the attribute data itself */
801
case kHFSPlusAttrForkData:
802
/* Is there room for the fork data record? */
803
if ((char *)srcRec + sizeof(HFSPlusAttrForkData) > nextRecord) {
804
if (debug) printf("hfs_swap_HFSPlusBTInternalNode: attr fork data #%d too big\n", srcDesc->numRecords-i-1);
805
WriteError(fcb->fcbVolume->vcbGPtr, E_BadNode, fcb->fcbFileID, src->blockNum);
809
/* We're not swapping the reserved field */
811
hfs_swap_HFSPlusForkData(&srcRec->forkData.theFork);
814
case kHFSPlusAttrExtents:
815
/* Is there room for an extent record? */
816
if ((char *)srcRec + sizeof(HFSPlusAttrExtents) > nextRecord) {
817
if (debug) printf("hfs_swap_HFSPlusBTInternalNode: attr extents #%d too big\n", srcDesc->numRecords-i-1);
818
WriteError(fcb->fcbVolume->vcbGPtr, E_BadNode, fcb->fcbFileID, src->blockNum);
822
/* We're not swapping the reserved field */
824
for (j = 0; j < kHFSPlusExtentDensity; j++) {
825
srcRec->overflowExtents.extents[j].startBlock =
826
SWAP_BE32(srcRec->overflowExtents.extents[j].startBlock);
827
srcRec->overflowExtents.extents[j].blockCount =
828
SWAP_BE32(srcRec->overflowExtents.extents[j].blockCount);
832
if (debug) printf ("hfs_swap_BTNode: unrecognized attribute record type (%d)\n", srcRec->recordType);
834
if (direction == kSwapBTNodeHostToBig)
835
srcRec->recordType = SWAP_BE32(srcRec->recordType);
838
printf("hfs_swap_HFSPlusBTInternalNode: fileID %u is not a system B-tree\n", fileID);
846
hfs_swap_HFSBTInternalNode (
847
BlockDescriptor *src,
849
enum HFSBTSwapDirection direction
852
HFSCatalogNodeID fileID =fcb->fcbFileID;
853
BTNodeDescriptor *srcDesc = src->buffer;
854
UInt16 *srcOffs = (UInt16 *)((char *)src->buffer + (src->blockSize - (srcDesc->numRecords * sizeof (UInt16))));
855
char *nextRecord; /* Points to start of record following current one */
860
if (fileID == kHFSExtentsFileID) {
861
HFSExtentKey *srcKey;
862
HFSExtentDescriptor *srcRec;
863
size_t recordSize; /* Size of the data part of the record, or node number for index nodes */
865
if (srcDesc->kind == kBTIndexNode)
866
recordSize = sizeof(UInt32);
868
recordSize = sizeof(HFSExtentDescriptor);
870
for (i = 0; i < srcDesc->numRecords; i++) {
871
/* Point to the start of the record we're currently checking. */
872
srcKey = (HFSExtentKey *)((char *)src->buffer + srcOffs[i]);
875
* Point to start of next (larger offset) record. We'll use this
876
* to be sure the current record doesn't overflow into the next
879
nextRecord = (char *)src->buffer + srcOffs[i-1];
882
* Make sure the key and data are within the buffer. Since both key
883
* and data are fixed size, this is relatively easy. Note that this
884
* relies on the keyLength being a constant; we verify the keyLength
887
if ((char *)srcKey + sizeof(HFSExtentKey) + recordSize > nextRecord) {
888
if (debug) printf("hfs_swap_HFSBTInternalNode: extents key #%d offset too big (0x%04X)\n", srcDesc->numRecords-i-1, srcOffs[i]);
889
WriteError(fcb->fcbVolume->vcbGPtr, E_BadNode, fcb->fcbFileID, src->blockNum);
893
/* Don't swap srcKey->keyLength (it's only one byte), but do sanity check it */
894
if (srcKey->keyLength != sizeof(*srcKey) - sizeof(srcKey->keyLength)) {
895
if (debug) printf("hfs_swap_HFSBTInternalNode: extents key #%d invalid length (%d)\n", srcDesc->numRecords-i-1, srcKey->keyLength);
898
/* Don't swap srcKey->forkType; it's only one byte */
900
srcKey->fileID = SWAP_BE32 (srcKey->fileID);
901
srcKey->startBlock = SWAP_BE16 (srcKey->startBlock);
903
/* Point to record data (round up to even byte boundary) */
904
srcRec = (HFSExtentDescriptor *)((char *)srcKey + ((srcKey->keyLength + 2) & ~1));
906
if (srcDesc->kind == kBTIndexNode) {
907
/* For index nodes, the record data is just a child node number. */
908
*((UInt32 *)srcRec) = SWAP_BE32 (*((UInt32 *)srcRec));
910
/* Swap the extent data */
911
for (j = 0; j < kHFSExtentDensity; j++) {
912
srcRec[j].startBlock = SWAP_BE16 (srcRec[j].startBlock);
913
srcRec[j].blockCount = SWAP_BE16 (srcRec[j].blockCount);
918
} else if (fileID == kHFSCatalogFileID || fileID == kHFSRepairCatalogFileID) {
919
HFSCatalogKey *srcKey;
921
unsigned expectedKeyLength;
923
for (i = 0; i < srcDesc->numRecords; i++) {
924
/* Point to the start of the record we're currently checking. */
925
srcKey = (HFSCatalogKey *)((char *)src->buffer + srcOffs[i]);
928
* Point to start of next (larger offset) record. We'll use this
929
* to be sure the current record doesn't overflow into the next
932
nextRecord = (char *)src->buffer + srcOffs[i-1];
935
* Make sure we can safely dereference the keyLength and parentID fields.
936
* The value 8 below is 1 bytes for keyLength + 1 byte reserved + 4 bytes
937
* for parentID + 1 byte for nodeName's length + 1 byte to round up the
938
* record start to an even offset, which forms a minimal key.
940
if ((char *)srcKey + 8 > nextRecord) {
941
if (debug) printf("hfs_swap_HFSBTInternalNode: catalog key #%d offset too big (0x%04X)\n", srcDesc->numRecords-i-1, srcOffs[i]);
942
WriteError(fcb->fcbVolume->vcbGPtr, E_BadNode, fcb->fcbFileID, src->blockNum);
946
/* Don't swap srcKey->keyLength (it's only one byte), but do sanity check it */
947
if (srcKey->keyLength < kHFSCatalogKeyMinimumLength || srcKey->keyLength > kHFSCatalogKeyMaximumLength) {
948
if (debug) printf("hfs_swap_HFSBTInternalNode: catalog key #%d invalid length (%d)\n", srcDesc->numRecords-i-1, srcKey->keyLength);
951
/* Don't swap srcKey->reserved */
953
srcKey->parentID = SWAP_BE32 (srcKey->parentID);
955
/* Don't swap srcKey->nodeName */
957
/* Make sure the keyLength is big enough for the key's content */
958
if (srcDesc->kind == kBTIndexNode)
959
expectedKeyLength = sizeof(*srcKey) - sizeof(srcKey->keyLength);
961
expectedKeyLength = srcKey->nodeName[0] + kHFSCatalogKeyMinimumLength;
962
if (srcKey->keyLength < expectedKeyLength) {
963
if (debug) printf("hfs_swap_HFSBTInternalNode: catalog record #%d keyLength=%u expected=%u\n",
964
srcDesc->numRecords-i, srcKey->keyLength, expectedKeyLength);
965
WriteError(fcb->fcbVolume->vcbGPtr, E_BadNode, fcb->fcbFileID, src->blockNum);
969
/* Point to record data (round up to even byte boundary) */
970
srcPtr = (SInt16 *)((char *)srcKey + ((srcKey->keyLength + 2) & ~1));
973
* Make sure that we can safely dereference the record's type field or
974
* and index node's child node number.
976
if ((char *)srcPtr + sizeof(UInt32) > nextRecord) {
977
if (debug) printf("hfs_swap_HFSBTInternalNode: catalog key #%d too big\n", srcDesc->numRecords-i-1);
978
WriteError(fcb->fcbVolume->vcbGPtr, E_BadNode, fcb->fcbFileID, src->blockNum);
983
* For index nodes, the record data is just the child's node number.
984
* Skip over swapping the various types of catalog record.
986
if (srcDesc->kind == kBTIndexNode) {
987
*((UInt32 *)srcPtr) = SWAP_BE32 (*((UInt32 *)srcPtr));
991
/* Make sure the recordType is in native order before using it. */
992
if (direction == kSwapBTNodeBigToHost)
993
srcPtr[0] = SWAP_BE16 (srcPtr[0]);
995
if (srcPtr[0] == kHFSFolderRecord) {
996
HFSCatalogFolder *srcRec = (HFSCatalogFolder *)srcPtr;
997
if ((char *)srcRec + sizeof(*srcRec) > nextRecord) {
998
if (debug) printf("hfs_swap_HFSBTInternalNode: catalog folder record #%d too big\n", srcDesc->numRecords-i-1);
999
WriteError(fcb->fcbVolume->vcbGPtr, E_BadNode, fcb->fcbFileID, src->blockNum);
1003
srcRec->flags = SWAP_BE16 (srcRec->flags);
1004
srcRec->valence = SWAP_BE16 (srcRec->valence);
1006
srcRec->folderID = SWAP_BE32 (srcRec->folderID);
1007
srcRec->createDate = SWAP_BE32 (srcRec->createDate);
1008
srcRec->modifyDate = SWAP_BE32 (srcRec->modifyDate);
1009
srcRec->backupDate = SWAP_BE32 (srcRec->backupDate);
1011
/* Don't swap srcRec->userInfo */
1012
/* Don't swap srcRec->finderInfo */
1013
/* Don't swap resserved array */
1015
} else if (srcPtr[0] == kHFSFileRecord) {
1016
HFSCatalogFile *srcRec = (HFSCatalogFile *)srcPtr;
1017
if ((char *)srcRec + sizeof(*srcRec) > nextRecord) {
1018
if (debug) printf("hfs_swap_HFSBTInternalNode: catalog file record #%d too big\n", srcDesc->numRecords-i-1);
1019
WriteError(fcb->fcbVolume->vcbGPtr, E_BadNode, fcb->fcbFileID, src->blockNum);
1023
srcRec->flags = srcRec->flags;
1024
srcRec->fileType = srcRec->fileType;
1026
/* Don't swap srcRec->userInfo */
1028
srcRec->fileID = SWAP_BE32 (srcRec->fileID);
1030
srcRec->dataStartBlock = SWAP_BE16 (srcRec->dataStartBlock);
1031
srcRec->dataLogicalSize = SWAP_BE32 (srcRec->dataLogicalSize);
1032
srcRec->dataPhysicalSize = SWAP_BE32 (srcRec->dataPhysicalSize);
1034
srcRec->rsrcStartBlock = SWAP_BE16 (srcRec->rsrcStartBlock);
1035
srcRec->rsrcLogicalSize = SWAP_BE32 (srcRec->rsrcLogicalSize);
1036
srcRec->rsrcPhysicalSize = SWAP_BE32 (srcRec->rsrcPhysicalSize);
1038
srcRec->createDate = SWAP_BE32 (srcRec->createDate);
1039
srcRec->modifyDate = SWAP_BE32 (srcRec->modifyDate);
1040
srcRec->backupDate = SWAP_BE32 (srcRec->backupDate);
1042
/* Don't swap srcRec->finderInfo */
1044
srcRec->clumpSize = SWAP_BE16 (srcRec->clumpSize);
1046
/* Swap the two sets of extents as an array of six (three each) UInt16 */
1047
for (j = 0; j < kHFSExtentDensity * 2; j++) {
1048
srcRec->dataExtents[j].startBlock = SWAP_BE16 (srcRec->dataExtents[j].startBlock);
1049
srcRec->dataExtents[j].blockCount = SWAP_BE16 (srcRec->dataExtents[j].blockCount);
1052
/* Don't swap srcRec->reserved */
1054
} else if ((srcPtr[0] == kHFSFolderThreadRecord) ||
1055
(srcPtr[0] == kHFSFileThreadRecord)) {
1056
HFSCatalogThread *srcRec = (HFSCatalogThread *)srcPtr;
1058
/* Make sure there is room for parentID and name length */
1059
if ((char *) &srcRec->nodeName[1] > nextRecord) {
1060
if (debug) printf("hfs_swap_HFSBTInternalNode: catalog thread record #%d too big\n", srcDesc->numRecords-i-1);
1061
WriteError(fcb->fcbVolume->vcbGPtr, E_BadNode, fcb->fcbFileID, src->blockNum);
1065
/* Don't swap srcRec->reserved array */
1067
srcRec->parentID = SWAP_BE32 (srcRec->parentID);
1069
/* Don't swap srcRec->nodeName */
1071
/* Make sure there is room for the name in the buffer */
1072
if ((char *) &srcRec->nodeName[srcRec->nodeName[0]] > nextRecord) {
1073
if (debug) printf("hfs_swap_HFSBTInternalNode: catalog thread record #%d name too big\n", srcDesc->numRecords-i-1);
1074
WriteError(fcb->fcbVolume->vcbGPtr, E_BadNode, fcb->fcbFileID, src->blockNum);
1078
if (debug) printf("hfs_swap_HFSBTInternalNode: unrecognized catalog record type (0x%04X; record #%d)\n", srcPtr[0], srcDesc->numRecords-i-1);
1081
/* We can swap the record type now that we're done using it */
1082
if (direction == kSwapBTNodeHostToBig)
1083
srcPtr[0] = SWAP_BE16 (srcPtr[0]);
1087
printf("hfs_swap_HFSBTInternalNode: fileID %u is not a system B-tree\n", fileID);