2  * Copyright (c) 2000-2007 Apple Inc. All rights reserved. 
   4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. The rights granted to you under the License 
  10  * may not be used to create, or enable the creation or redistribution of, 
  11  * unlawful or unlicensed copies of an Apple operating system, or to 
  12  * circumvent, violate, or enable the circumvention or violation of, any 
  13  * terms of an Apple operating system software license agreement. 
  15  * Please obtain a copy of the License at 
  16  * http://www.opensource.apple.com/apsl/ and read it before using this file. 
  18  * The Original Code and all software distributed under the License are 
  19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  23  * Please see the License for the specific language governing rights and 
  24  * limitations under the License. 
  26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 
  32  * This file implements endian swapping routines for the HFS/HFS Plus 
  36 #include "hfs_endian.h" 
  38 #include "hfscommon/headers/BTreesPrivate.h" 
  43  * Internal swapping routines 
  45  * These routines handle swapping the records of leaf and index nodes.  The 
  46  * layout of the keys and records varies depending on the kind of B-tree 
  47  * (determined by fileID). 
  49  * The direction parameter must be kSwapBTNodeBigToHost or kSwapBTNodeHostToBig. 
  50  * The kSwapBTNodeHeaderRecordOnly "direction" is not valid for these routines. 
  52 static int hfs_swap_HFSPlusBTInternalNode (BlockDescriptor 
*src
, HFSCatalogNodeID fileID
, enum HFSBTSwapDirection direction
); 
  53 static int hfs_swap_HFSBTInternalNode (BlockDescriptor 
*src
, HFSCatalogNodeID fileID
, enum HFSBTSwapDirection direction
); 
  56  * hfs_swap_HFSPlusForkData 
  59 hfs_swap_HFSPlusForkData ( 
  65         src
->logicalSize                
= SWAP_BE64 (src
->logicalSize
); 
  67         src
->clumpSize                  
= SWAP_BE32 (src
->clumpSize
); 
  68         src
->totalBlocks                
= SWAP_BE32 (src
->totalBlocks
); 
  70     for (i 
= 0; i 
< kHFSPlusExtentDensity
; i
++) { 
  71         src
->extents
[i
].startBlock      
= SWAP_BE32 (src
->extents
[i
].startBlock
); 
  72         src
->extents
[i
].blockCount      
= SWAP_BE32 (src
->extents
[i
].blockCount
); 
  79  *  NOTE: This operation is not naturally symmetric. 
  80  *        We have to determine which way we're swapping things. 
  86     enum HFSBTSwapDirection direction
 
  89     BTNodeDescriptor 
*srcDesc 
= src
->buffer
; 
  90     u_int16_t 
*srcOffs 
= NULL
; 
  91         BTreeControlBlockPtr btcb 
= (BTreeControlBlockPtr
)VTOF(vp
)->fcbBTCBPtr
; 
  96     if (direction 
== kSwapBTNodeBigToHost
) { 
  97         printf ("BE -> Native Swap\n"); 
  98     } else if (direction 
== kSwapBTNodeHostToBig
) { 
  99         printf ("Native -> BE Swap\n"); 
 100     } else if (direction 
== kSwapBTNodeHeaderRecordOnly
) { 
 101         printf ("Not swapping descriptors\n"); 
 103         panic ("hfs_swap_BTNode: This is impossible"); 
 108      * If we are doing a swap from on-disk to in-memory, then swap the node 
 109      * descriptor and record offsets before we need to use them. 
 111     if (direction 
== kSwapBTNodeBigToHost
) { 
 112         srcDesc
->fLink          
= SWAP_BE32 (srcDesc
->fLink
); 
 113         srcDesc
->bLink          
= SWAP_BE32 (srcDesc
->bLink
); 
 116          * When first opening a BTree, we have to read the header node before the 
 117          * control block is initialized.  In this case, totalNodes will be zero, 
 118          * so skip the bounds checking. 
 120         if (btcb
->totalNodes 
!= 0) { 
 121                         if (srcDesc
->fLink 
>= btcb
->totalNodes
) { 
 122                                 printf("hfs_swap_BTNode: invalid forward link (0x%08x >= 0x%08x)\n", srcDesc
->fLink
, btcb
->totalNodes
); 
 123                                 error 
= fsBTInvalidHeaderErr
; 
 126                         if (srcDesc
->bLink 
>= btcb
->totalNodes
) { 
 127                                 printf("hfs_swap_BTNode: invalid backward link (0x%08x >= 0x%08x)\n", srcDesc
->bLink
, btcb
->totalNodes
); 
 128                                 error 
= fsBTInvalidHeaderErr
; 
 134                  * Check srcDesc->kind.  Don't swap it because it's only one byte. 
 136                 if (srcDesc
->kind 
< kBTLeafNode 
|| srcDesc
->kind 
> kBTMapNode
) { 
 137                         printf("hfs_swap_BTNode: invalid node kind (%d)\n", srcDesc
->kind
); 
 138                         error 
= fsBTInvalidHeaderErr
; 
 143                  * Check srcDesc->height.  Don't swap it because it's only one byte. 
 145                 if (srcDesc
->height 
> btcb
->treeDepth
) { 
 146                         printf("hfs_swap_BTNode: invalid node height (%d)\n", srcDesc
->height
); 
 147                         error 
= fsBTInvalidHeaderErr
; 
 151         /* Don't swap srcDesc->reserved */ 
 153         srcDesc
->numRecords     
= SWAP_BE16 (srcDesc
->numRecords
); 
 156          * Swap the node offsets (including the free space one!). 
 158         srcOffs 
= (u_int16_t 
*)((char *)src
->buffer 
+ (src
->blockSize 
- ((srcDesc
->numRecords 
+ 1) * sizeof (u_int16_t
)))); 
 161          * Sanity check that the record offsets are within the node itself. 
 163         if ((char *)srcOffs 
> ((char *)src
->buffer 
+ src
->blockSize
) || 
 164             (char *)srcOffs 
< ((char *)src
->buffer 
+ sizeof(BTNodeDescriptor
))) { 
 165             printf("hfs_swap_BTNode: invalid record count (0x%04X)\n", srcDesc
->numRecords
); 
 166             error 
= fsBTInvalidHeaderErr
; 
 171                  * Swap and sanity check each of the record offsets. 
 173         for (i 
= 0; i 
<= srcDesc
->numRecords
; i
++) { 
 174             srcOffs
[i
]  = SWAP_BE16 (srcOffs
[i
]); 
 177              * Sanity check: must be even, and within the node itself. 
 179              * We may be called to swap an unused node, which contains all zeroes. 
 180              * This is why we allow the record offset to be zero. 
 182             if ((srcOffs
[i
] & 1) || (srcOffs
[i
] < sizeof(BTNodeDescriptor
) && srcOffs
[i
] != 0) || (srcOffs
[i
] >= src
->blockSize
)) { 
 183                 printf("hfs_swap_BTNode: record #%d invalid offset (0x%04X)\n", srcDesc
->numRecords
-i
-1, srcOffs
[i
]); 
 184                 error 
= fsBTInvalidHeaderErr
; 
 189              * Make sure the offsets are strictly increasing.  Note that we're looping over 
 190              * them backwards, hence the order in the comparison. 
 192             if ((i 
!= 0) && (srcOffs
[i
] >= srcOffs
[i
-1])) { 
 193                 printf("hfs_swap_BTNode: offsets %d and %d out of order (0x%04X, 0x%04X)\n", 
 194                     srcDesc
->numRecords
-i
-1, srcDesc
->numRecords
-i
, srcOffs
[i
], srcOffs
[i
-1]); 
 195                 error 
= fsBTInvalidHeaderErr
; 
 202      * Swap the records (ordered by frequency of access) 
 204     if ((srcDesc
->kind 
== kBTIndexNode
) || 
 205         (srcDesc
-> kind 
== kBTLeafNode
)) { 
 207         if (VTOVCB(vp
)->vcbSigWord 
== kHFSPlusSigWord
) { 
 208             error 
= hfs_swap_HFSPlusBTInternalNode (src
, VTOC(vp
)->c_fileid
, direction
); 
 210             error 
= hfs_swap_HFSBTInternalNode (src
, VTOC(vp
)->c_fileid
, direction
); 
 213         if (error
) goto fail
; 
 215     } else if (srcDesc
-> kind 
== kBTMapNode
) { 
 216         /* Don't swap the bitmaps, they'll be done in the bitmap routines */ 
 218     } else if (srcDesc
-> kind 
== kBTHeaderNode
) { 
 219         /* The header's offset is hard-wired because we cannot trust the offset pointers. */ 
 220         BTHeaderRec 
*srcHead 
= (BTHeaderRec 
*)((char *)src
->buffer 
+ sizeof(BTNodeDescriptor
)); 
 222         srcHead
->treeDepth              
=       SWAP_BE16 (srcHead
->treeDepth
); 
 224         srcHead
->rootNode               
=       SWAP_BE32 (srcHead
->rootNode
); 
 225         srcHead
->leafRecords    
=       SWAP_BE32 (srcHead
->leafRecords
); 
 226         srcHead
->firstLeafNode  
=       SWAP_BE32 (srcHead
->firstLeafNode
); 
 227         srcHead
->lastLeafNode   
=       SWAP_BE32 (srcHead
->lastLeafNode
); 
 229         srcHead
->nodeSize               
=       SWAP_BE16 (srcHead
->nodeSize
); 
 230         srcHead
->maxKeyLength   
=       SWAP_BE16 (srcHead
->maxKeyLength
); 
 232         srcHead
->totalNodes             
=       SWAP_BE32 (srcHead
->totalNodes
); 
 233         srcHead
->freeNodes              
=       SWAP_BE32 (srcHead
->freeNodes
); 
 235         srcHead
->clumpSize              
=       SWAP_BE32 (srcHead
->clumpSize
); 
 236         srcHead
->attributes             
=       SWAP_BE32 (srcHead
->attributes
); 
 238         /* Don't swap srcHead->reserved1 */ 
 239         /* Don't swap srcHead->btreeType; it's only one byte */ 
 240         /* Don't swap srcHead->reserved2 */ 
 241         /* Don't swap srcHead->reserved3 */ 
 242         /* Don't swap bitmap */ 
 246      * If we are doing a swap from in-memory to on-disk, then swap the node 
 247      * descriptor and record offsets after we're done using them. 
 249     if (direction 
== kSwapBTNodeHostToBig
) { 
 251                  * Sanity check and swap the forward and backward links. 
 253                 if (srcDesc
->fLink 
>= btcb
->totalNodes
) { 
 254                         panic("hfs_UNswap_BTNode: invalid forward link (0x%08X)\n", srcDesc
->fLink
); 
 255                         error 
= fsBTInvalidHeaderErr
; 
 258                 if (srcDesc
->bLink 
>= btcb
->totalNodes
) { 
 259                         panic("hfs_UNswap_BTNode: invalid backward link (0x%08X)\n", srcDesc
->bLink
); 
 260                         error 
= fsBTInvalidHeaderErr
; 
 263         srcDesc
->fLink          
= SWAP_BE32 (srcDesc
->fLink
); 
 264         srcDesc
->bLink          
= SWAP_BE32 (srcDesc
->bLink
); 
 267                  * Check srcDesc->kind.  Don't swap it because it's only one byte. 
 269                 if (srcDesc
->kind 
< kBTLeafNode 
|| srcDesc
->kind 
> kBTMapNode
) { 
 270                         panic("hfs_UNswap_BTNode: invalid node kind (%d)\n", srcDesc
->kind
); 
 271                         error 
= fsBTInvalidHeaderErr
; 
 276                  * Check srcDesc->height.  Don't swap it because it's only one byte. 
 278                 if (srcDesc
->height 
> btcb
->treeDepth
) { 
 279                         panic("hfs_UNswap_BTNode: invalid node height (%d)\n", srcDesc
->height
); 
 280                         error 
= fsBTInvalidHeaderErr
; 
 284         /* Don't swap srcDesc->reserved */ 
 287          * Swap the node offsets (including the free space one!). 
 289         srcOffs 
= (u_int16_t 
*)((char *)src
->buffer 
+ (src
->blockSize 
- ((srcDesc
->numRecords 
+ 1) * sizeof (u_int16_t
)))); 
 292          * Sanity check that the record offsets are within the node itself. 
 294         if ((char *)srcOffs 
> ((char *)src
->buffer 
+ src
->blockSize
) || 
 295                 (char *)srcOffs 
< ((char *)src
->buffer 
+ sizeof(BTNodeDescriptor
))) { 
 296             panic("hfs_UNswap_BTNode: invalid record count (0x%04X)\n", srcDesc
->numRecords
); 
 297             error 
= fsBTInvalidHeaderErr
; 
 302                  * Swap and sanity check each of the record offsets. 
 304         for (i 
= 0; i 
<= srcDesc
->numRecords
; i
++) { 
 306              * Sanity check: must be even, and within the node itself. 
 308              * We may be called to swap an unused node, which contains all zeroes. 
 309              * This is why we allow the record offset to be zero. 
 311             if ((srcOffs
[i
] & 1) || (srcOffs
[i
] < sizeof(BTNodeDescriptor
) && srcOffs
[i
] != 0) || (srcOffs
[i
] >= src
->blockSize
)) { 
 312                 panic("hfs_UNswap_BTNode: record #%d invalid offset (0x%04X)\n", srcDesc
->numRecords
-i
-1, srcOffs
[i
]); 
 313                 error 
= fsBTInvalidHeaderErr
; 
 318              * Make sure the offsets are strictly increasing.  Note that we're looping over 
 319              * them backwards, hence the order in the comparison. 
 321             if ((i 
< srcDesc
->numRecords
) && (srcOffs
[i
+1] >= srcOffs
[i
])) { 
 322                 panic("hfs_UNswap_BTNode: offsets %d and %d out of order (0x%04X, 0x%04X)\n", 
 323                     srcDesc
->numRecords
-i
-2, srcDesc
->numRecords
-i
-1, srcOffs
[i
+1], srcOffs
[i
]); 
 324                 error 
= fsBTInvalidHeaderErr
; 
 328             srcOffs
[i
]  = SWAP_BE16 (srcOffs
[i
]); 
 331         srcDesc
->numRecords     
= SWAP_BE16 (srcDesc
->numRecords
); 
 337                  * Log some useful information about where the corrupt node is. 
 339                 printf("node=%lld fileID=%u volume=%s device=%s\n", src
->blockNum
, VTOC(vp
)->c_fileid
, 
 340                         VTOVCB(vp
)->vcbVN
, vfs_statfs(vnode_mount(vp
))->f_mntfromname
); 
 341                 hfs_mark_volume_inconsistent(VTOVCB(vp
)); 
 348 hfs_swap_HFSPlusBTInternalNode ( 
 349     BlockDescriptor 
*src
, 
 350     HFSCatalogNodeID fileID
, 
 351     enum HFSBTSwapDirection direction
 
 354     BTNodeDescriptor 
*srcDesc 
= src
->buffer
; 
 355     u_int16_t 
*srcOffs 
= (u_int16_t 
*)((char *)src
->buffer 
+ (src
->blockSize 
- (srcDesc
->numRecords 
* sizeof (u_int16_t
)))); 
 356     char *nextRecord
;   /*  Points to start of record following current one */ 
 359      * i is an int32 because it needs to be negative to index the offset to free space. 
 360      * srcDesc->numRecords is a u_int16_t and is unlikely to become 32-bit so this should be ok. 
 366     if (fileID 
== kHFSExtentsFileID
) { 
 367         HFSPlusExtentKey 
*srcKey
; 
 368         HFSPlusExtentDescriptor 
*srcRec
; 
 369                 size_t recordSize
;      /* Size of the data part of the record, or node number for index nodes */ 
 371         if (srcDesc
->kind 
== kBTIndexNode
) 
 372                 recordSize 
= sizeof(u_int32_t
); 
 374                 recordSize 
= sizeof(HFSPlusExtentDescriptor
); 
 376         for (i 
= 0; i 
< srcDesc
->numRecords
; i
++) { 
 377                 /* Point to the start of the record we're currently checking. */ 
 378             srcKey 
= (HFSPlusExtentKey 
*)((char *)src
->buffer 
+ srcOffs
[i
]); 
 381              * Point to start of next (larger offset) record.  We'll use this 
 382              * to be sure the current record doesn't overflow into the next 
 385                         nextRecord 
= (char *)src
->buffer 
+ srcOffs
[i
-1]; 
 388                          * Make sure the key and data are within the buffer.  Since both key 
 389                          * and data are fixed size, this is relatively easy.  Note that this 
 390                          * relies on the keyLength being a constant; we verify the keyLength 
 393                         if ((char *)srcKey 
+ sizeof(HFSPlusExtentKey
) + recordSize 
> nextRecord
) { 
 394                                 if (direction 
== kSwapBTNodeHostToBig
) { 
 395                                         panic("hfs_swap_HFSPlusBTInternalNode: extents key #%d offset too big (0x%04X)\n", srcDesc
->numRecords
-i
-1, srcOffs
[i
]); 
 397                                         printf("hfs_swap_HFSPlusBTInternalNode: extents key #%d offset too big (0x%04X)\n", srcDesc
->numRecords
-i
-1, srcOffs
[i
]); 
 399                                 return fsBTInvalidNodeErr
; 
 402             if (direction 
== kSwapBTNodeBigToHost
)  
 403                 srcKey
->keyLength 
= SWAP_BE16 (srcKey
->keyLength
); 
 404             if (srcKey
->keyLength 
!= sizeof(*srcKey
) - sizeof(srcKey
->keyLength
)) { 
 405                                 if (direction 
== kSwapBTNodeHostToBig
) { 
 406                                         panic("hfs_swap_HFSPlusBTInternalNode: extents key #%d invalid length (%d)\n", srcDesc
->numRecords
-i
-1, srcKey
->keyLength
); 
 408                                         printf("hfs_swap_HFSPlusBTInternalNode: extents key #%d invalid length (%d)\n", srcDesc
->numRecords
-i
-1, srcKey
->keyLength
); 
 410                                 return fsBTInvalidNodeErr
; 
 412             srcRec 
= (HFSPlusExtentDescriptor 
*)((char *)srcKey 
+ srcKey
->keyLength 
+ sizeof(srcKey
->keyLength
)); 
 413             if (direction 
== kSwapBTNodeHostToBig
) 
 414                 srcKey
->keyLength 
= SWAP_BE16 (srcKey
->keyLength
); 
 416             /* Don't swap srcKey->forkType; it's only one byte */ 
 417             /* Don't swap srcKey->pad */ 
 419             srcKey
->fileID                      
= SWAP_BE32 (srcKey
->fileID
); 
 420             srcKey
->startBlock          
= SWAP_BE32 (srcKey
->startBlock
); 
 422             if (srcDesc
->kind 
== kBTIndexNode
) { 
 423                 /* For index nodes, the record data is just a child node number. */ 
 424                 *((u_int32_t 
*)srcRec
) = SWAP_BE32 (*((u_int32_t 
*)srcRec
)); 
 426                                 /* Swap the extent data */ 
 427                                 for (j 
= 0; j 
< kHFSPlusExtentDensity
; j
++) { 
 428                                         srcRec
[j
].startBlock    
= SWAP_BE32 (srcRec
[j
].startBlock
); 
 429                                         srcRec
[j
].blockCount    
= SWAP_BE32 (srcRec
[j
].blockCount
); 
 434     } else if (fileID 
== kHFSCatalogFileID
) { 
 435         HFSPlusCatalogKey 
*srcKey
; 
 439         for (i 
= 0; i 
< srcDesc
->numRecords
; i
++) { 
 440                 /* Point to the start of the record we're currently checking. */ 
 441             srcKey 
= (HFSPlusCatalogKey 
*)((char *)src
->buffer 
+ srcOffs
[i
]); 
 444              * Point to start of next (larger offset) record.  We'll use this 
 445              * to be sure the current record doesn't overflow into the next 
 448                         nextRecord 
= (char *)src
->buffer 
+ srcOffs
[i
-1]; 
 451                          * Make sure we can safely dereference the keyLength and parentID fields.  
 453                         if ((char *)srcKey 
+ offsetof(HFSPlusCatalogKey
, nodeName
.unicode
[0]) > nextRecord
) { 
 454                                 if (direction 
== kSwapBTNodeHostToBig
) { 
 455                                         panic("hfs_swap_HFSPlusBTInternalNode: catalog key #%d offset too big (0x%04X)\n", srcDesc
->numRecords
-i
-1, srcOffs
[i
]); 
 457                                         printf("hfs_swap_HFSPlusBTInternalNode: catalog key #%d offset too big (0x%04X)\n", srcDesc
->numRecords
-i
-1, srcOffs
[i
]); 
 459                                 return fsBTInvalidNodeErr
; 
 463                          * Swap and sanity check the key length 
 465             if (direction 
== kSwapBTNodeBigToHost
) 
 466                 srcKey
->keyLength 
= SWAP_BE16 (srcKey
->keyLength
); 
 467             keyLength 
= srcKey
->keyLength
;      /* Put it in a local (native order) because we use it several times */ 
 468             if (direction 
== kSwapBTNodeHostToBig
) 
 469                 srcKey
->keyLength 
= SWAP_BE16 (keyLength
); 
 471             /* Sanity check the key length */ 
 472             if (keyLength 
< kHFSPlusCatalogKeyMinimumLength 
|| keyLength 
> kHFSPlusCatalogKeyMaximumLength
) { 
 473                                 if (direction 
== kSwapBTNodeHostToBig
) { 
 474                                         panic("hfs_swap_HFSPlusBTInternalNode: catalog key #%d invalid length (%d)\n", srcDesc
->numRecords
-i
-1, keyLength
); 
 476                                         printf("hfs_swap_HFSPlusBTInternalNode: catalog key #%d invalid length (%d)\n", srcDesc
->numRecords
-i
-1, keyLength
); 
 478                                 return fsBTInvalidNodeErr
; 
 482              * Make sure that we can safely dereference the record's type field or 
 483              * an index node's child node number. 
 485             srcPtr 
= (int16_t *)((char *)srcKey 
+ keyLength 
+ sizeof(srcKey
->keyLength
)); 
 486             if ((char *)srcPtr 
+ sizeof(u_int32_t
) > nextRecord
) { 
 487                                 if (direction 
== kSwapBTNodeHostToBig
) { 
 488                                         panic("hfs_swap_HFSPlusBTInternalNode: catalog key #%d too big\n", srcDesc
->numRecords
-i
-1); 
 490                                         printf("hfs_swap_HFSPlusBTInternalNode: catalog key #%d too big\n", srcDesc
->numRecords
-i
-1); 
 492                                 return fsBTInvalidNodeErr
; 
 495             srcKey
->parentID                                            
= SWAP_BE32 (srcKey
->parentID
); 
 498                          * Swap and sanity check the key's node name 
 500             if (direction 
== kSwapBTNodeBigToHost
) 
 501                 srcKey
->nodeName
.length 
= SWAP_BE16 (srcKey
->nodeName
.length
); 
 502             /* Make sure name length is consistent with key length */ 
 503             if (keyLength 
< sizeof(srcKey
->parentID
) + sizeof(srcKey
->nodeName
.length
) + 
 504                 srcKey
->nodeName
.length
*sizeof(srcKey
->nodeName
.unicode
[0])) { 
 505                                 if (direction 
== kSwapBTNodeHostToBig
) { 
 506                                         panic("hfs_swap_HFSPlusBTInternalNode: catalog record #%d keyLength=%d expected=%lu\n", 
 507                                                 srcDesc
->numRecords
-i
, keyLength
, sizeof(srcKey
->parentID
) + sizeof(srcKey
->nodeName
.length
) + 
 508                         srcKey
->nodeName
.length
*sizeof(srcKey
->nodeName
.unicode
[0])); 
 510                                         printf("hfs_swap_HFSPlusBTInternalNode: catalog record #%d keyLength=%d expected=%lu\n", 
 511                                                 srcDesc
->numRecords
-i
, keyLength
, sizeof(srcKey
->parentID
) + sizeof(srcKey
->nodeName
.length
) + 
 512                         srcKey
->nodeName
.length
*sizeof(srcKey
->nodeName
.unicode
[0])); 
 514                                 return fsBTInvalidNodeErr
; 
 516             for (j 
= 0; j 
< srcKey
->nodeName
.length
; j
++) { 
 517                 srcKey
->nodeName
.unicode
[j
]     = SWAP_BE16 (srcKey
->nodeName
.unicode
[j
]); 
 519             if (direction 
== kSwapBTNodeHostToBig
) 
 520                 srcKey
->nodeName
.length 
= SWAP_BE16 (srcKey
->nodeName
.length
); 
 523              * For index nodes, the record data is just the child's node number. 
 524              * Skip over swapping the various types of catalog record. 
 526             if (srcDesc
->kind 
== kBTIndexNode
) { 
 527                 *((u_int32_t 
*)srcPtr
) = SWAP_BE32 (*((u_int32_t 
*)srcPtr
)); 
 531             /* Make sure the recordType is in native order before using it. */ 
 532             if (direction 
== kSwapBTNodeBigToHost
) 
 533                 srcPtr
[0] = SWAP_BE16 (srcPtr
[0]); 
 535             if (srcPtr
[0] == kHFSPlusFolderRecord
) { 
 536                 HFSPlusCatalogFolder 
*srcRec 
= (HFSPlusCatalogFolder 
*)srcPtr
; 
 537                 if ((char *)srcRec 
+ sizeof(*srcRec
) > nextRecord
) { 
 538                                         if (direction 
== kSwapBTNodeHostToBig
) { 
 539                                                 panic("hfs_swap_HFSPlusBTInternalNode: catalog folder record #%d too big\n", srcDesc
->numRecords
-i
-1); 
 541                                                 printf("hfs_swap_HFSPlusBTInternalNode: catalog folder record #%d too big\n", srcDesc
->numRecords
-i
-1); 
 543                                         return fsBTInvalidNodeErr
; 
 546                 srcRec
->flags                           
= SWAP_BE16 (srcRec
->flags
); 
 547                 srcRec
->valence                         
= SWAP_BE32 (srcRec
->valence
); 
 548                 srcRec
->folderID                        
= SWAP_BE32 (srcRec
->folderID
); 
 549                 srcRec
->createDate                      
= SWAP_BE32 (srcRec
->createDate
); 
 550                 srcRec
->contentModDate          
= SWAP_BE32 (srcRec
->contentModDate
); 
 551                 srcRec
->attributeModDate        
= SWAP_BE32 (srcRec
->attributeModDate
); 
 552                 srcRec
->accessDate                      
= SWAP_BE32 (srcRec
->accessDate
); 
 553                 srcRec
->backupDate                      
= SWAP_BE32 (srcRec
->backupDate
); 
 555                 srcRec
->bsdInfo
.ownerID         
= SWAP_BE32 (srcRec
->bsdInfo
.ownerID
); 
 556                 srcRec
->bsdInfo
.groupID         
= SWAP_BE32 (srcRec
->bsdInfo
.groupID
); 
 558                 /* Don't swap srcRec->bsdInfo.adminFlags; it's only one byte */ 
 559                 /* Don't swap srcRec->bsdInfo.ownerFlags; it's only one byte */ 
 561                 srcRec
->bsdInfo
.fileMode                        
= SWAP_BE16 (srcRec
->bsdInfo
.fileMode
); 
 562                 srcRec
->bsdInfo
.special
.iNodeNum        
= SWAP_BE32 (srcRec
->bsdInfo
.special
.iNodeNum
); 
 564                 srcRec
->textEncoding            
= SWAP_BE32 (srcRec
->textEncoding
); 
 566                 /* Don't swap srcRec->userInfo */ 
 567                 /* Don't swap srcRec->finderInfo */ 
 568                 srcRec
->folderCount 
= SWAP_BE32 (srcRec
->folderCount
); 
 570             } else if (srcPtr
[0] == kHFSPlusFileRecord
) { 
 571                 HFSPlusCatalogFile 
*srcRec 
= (HFSPlusCatalogFile 
*)srcPtr
; 
 572                 if ((char *)srcRec 
+ sizeof(*srcRec
) > nextRecord
) { 
 573                                         if (direction 
== kSwapBTNodeHostToBig
) { 
 574                                                 panic("hfs_swap_HFSPlusBTInternalNode: catalog file record #%d too big\n", srcDesc
->numRecords
-i
-1); 
 576                                                 printf("hfs_swap_HFSPlusBTInternalNode: catalog file record #%d too big\n", srcDesc
->numRecords
-i
-1); 
 578                                         return fsBTInvalidNodeErr
; 
 581                 srcRec
->flags                           
= SWAP_BE16 (srcRec
->flags
); 
 583                 srcRec
->fileID                          
= SWAP_BE32 (srcRec
->fileID
); 
 585                 srcRec
->createDate                      
= SWAP_BE32 (srcRec
->createDate
); 
 586                 srcRec
->contentModDate          
= SWAP_BE32 (srcRec
->contentModDate
); 
 587                 srcRec
->attributeModDate        
= SWAP_BE32 (srcRec
->attributeModDate
); 
 588                 srcRec
->accessDate                      
= SWAP_BE32 (srcRec
->accessDate
); 
 589                 srcRec
->backupDate                      
= SWAP_BE32 (srcRec
->backupDate
); 
 591                 srcRec
->bsdInfo
.ownerID         
= SWAP_BE32 (srcRec
->bsdInfo
.ownerID
); 
 592                 srcRec
->bsdInfo
.groupID         
= SWAP_BE32 (srcRec
->bsdInfo
.groupID
); 
 594                 /* Don't swap srcRec->bsdInfo.adminFlags; it's only one byte */ 
 595                 /* Don't swap srcRec->bsdInfo.ownerFlags; it's only one byte */ 
 597                 srcRec
->bsdInfo
.fileMode                        
= SWAP_BE16 (srcRec
->bsdInfo
.fileMode
); 
 598                 srcRec
->bsdInfo
.special
.iNodeNum        
= SWAP_BE32 (srcRec
->bsdInfo
.special
.iNodeNum
); 
 600                 srcRec
->textEncoding            
= SWAP_BE32 (srcRec
->textEncoding
); 
 602                 /* If kHFSHasLinkChainBit is set, reserved1 is hl_FirstLinkID.   
 603                                  * In all other context, it is expected to be zero. 
 605                 srcRec
->reserved1 
= SWAP_BE32 (srcRec
->reserved1
); 
 607                 /* Don't swap srcRec->userInfo */ 
 608                 /* Don't swap srcRec->finderInfo */ 
 609                 /* Don't swap srcRec->reserved2 */ 
 611                 hfs_swap_HFSPlusForkData (&srcRec
->dataFork
); 
 612                 hfs_swap_HFSPlusForkData (&srcRec
->resourceFork
); 
 614             } else if ((srcPtr
[0] == kHFSPlusFolderThreadRecord
) || 
 615                        (srcPtr
[0] == kHFSPlusFileThreadRecord
)) { 
 618                                  * Make sure there is room for parentID and name length. 
 620                 HFSPlusCatalogThread 
*srcRec 
= (HFSPlusCatalogThread 
*)srcPtr
; 
 621                                 if ((char *) &srcRec
->nodeName
.unicode
[0] > nextRecord
) { 
 622                                         if (direction 
== kSwapBTNodeHostToBig
) { 
 623                                                 panic("hfs_swap_HFSPlusBTInternalNode: catalog thread record #%d too big\n", srcDesc
->numRecords
-i
-1); 
 625                                                 printf("hfs_swap_HFSPlusBTInternalNode: catalog thread record #%d too big\n", srcDesc
->numRecords
-i
-1); 
 627                                         return fsBTInvalidNodeErr
; 
 630                 /* Don't swap srcRec->reserved */ 
 632                 srcRec
->parentID                                                
= SWAP_BE32 (srcRec
->parentID
); 
 634                 if (direction 
== kSwapBTNodeBigToHost
) 
 635                         srcRec
->nodeName
.length 
= SWAP_BE16 (srcRec
->nodeName
.length
); 
 638                  * Make sure there is room for the name in the buffer. 
 639                  * Then swap the characters of the name itself. 
 641                                 if ((char *) &srcRec
->nodeName
.unicode
[srcRec
->nodeName
.length
] > nextRecord
) { 
 642                                         if (direction 
== kSwapBTNodeHostToBig
) { 
 643                                                 panic("hfs_swap_HFSPlusBTInternalNode: catalog thread record #%d name too big\n", srcDesc
->numRecords
-i
-1); 
 645                                                 printf("hfs_swap_HFSPlusBTInternalNode: catalog thread record #%d name too big\n", srcDesc
->numRecords
-i
-1); 
 647                                         return fsBTInvalidNodeErr
; 
 649                 for (j 
= 0; j 
< srcRec
->nodeName
.length
; j
++) { 
 650                     srcRec
->nodeName
.unicode
[j
] = SWAP_BE16 (srcRec
->nodeName
.unicode
[j
]); 
 653                 if (direction 
== kSwapBTNodeHostToBig
) 
 654                         srcRec
->nodeName
.length 
= SWAP_BE16 (srcRec
->nodeName
.length
); 
 657                                 if (direction 
== kSwapBTNodeHostToBig
) { 
 658                         panic("hfs_swap_HFSPlusBTInternalNode: unrecognized catalog record type (0x%04X; record #%d)\n", srcPtr
[0], srcDesc
->numRecords
-i
-1); 
 660                         printf("hfs_swap_HFSPlusBTInternalNode: unrecognized catalog record type (0x%04X; record #%d)\n", srcPtr
[0], srcDesc
->numRecords
-i
-1); 
 662                                 return fsBTInvalidNodeErr
; 
 665             /* We can swap the record type now that we're done using it. */ 
 666             if (direction 
== kSwapBTNodeHostToBig
) 
 667                 srcPtr
[0] = SWAP_BE16 (srcPtr
[0]); 
 670     } else if (fileID 
== kHFSAttributesFileID
) { 
 671         HFSPlusAttrKey 
*srcKey
; 
 672         HFSPlusAttrRecord 
*srcRec
; 
 674                 u_int32_t attrSize 
= 0; 
 676         for (i 
= 0; i 
< srcDesc
->numRecords
; i
++) { 
 677                 /* Point to the start of the record we're currently checking. */ 
 678                 srcKey 
= (HFSPlusAttrKey 
*)((char *)src
->buffer 
+ srcOffs
[i
]); 
 681              * Point to start of next (larger offset) record.  We'll use this 
 682              * to be sure the current record doesn't overflow into the next 
 685                         nextRecord 
= (char *)src
->buffer 
+ srcOffs
[i
-1]; 
 687                 /* Make sure there is room in the buffer for a minimal key */ 
 688                 if ((char *) &srcKey
->attrName
[1] > nextRecord
) { 
 689                                 if (direction 
== kSwapBTNodeHostToBig
) { 
 690                                         panic("hfs_swap_HFSPlusBTInternalNode: attr key #%d offset too big (0x%04X)\n", srcDesc
->numRecords
-i
-1, srcOffs
[i
]); 
 692                                         printf("hfs_swap_HFSPlusBTInternalNode: attr key #%d offset too big (0x%04X)\n", srcDesc
->numRecords
-i
-1, srcOffs
[i
]); 
 694                                 return fsBTInvalidNodeErr
; 
 697                 /* Swap the key length field */ 
 698                 if (direction 
== kSwapBTNodeBigToHost
) 
 699                         srcKey
->keyLength 
= SWAP_BE16(srcKey
->keyLength
); 
 700                 keyLength 
= srcKey
->keyLength
;  /* Keep a copy in native order */ 
 701                 if (direction 
== kSwapBTNodeHostToBig
) 
 702                         srcKey
->keyLength 
= SWAP_BE16(srcKey
->keyLength
); 
 705              * Make sure that we can safely dereference the record's type field or 
 706              * an index node's child node number. 
 708                 srcRec 
= (HFSPlusAttrRecord 
*)((char *)srcKey 
+ keyLength 
+ sizeof(srcKey
->keyLength
)); 
 709                 if ((char *)srcRec 
+ sizeof(u_int32_t
) > nextRecord
) { 
 710                                 if (direction 
== kSwapBTNodeHostToBig
) { 
 711                                         panic("hfs_swap_HFSPlusBTInternalNode: attr key #%d too big (%d)\n", srcDesc
->numRecords
-i
-1, keyLength
); 
 713                                         printf("hfs_swap_HFSPlusBTInternalNode: attr key #%d too big (%d)\n", srcDesc
->numRecords
-i
-1, keyLength
); 
 715                                 return fsBTInvalidNodeErr
; 
 718                 srcKey
->fileID 
= SWAP_BE32(srcKey
->fileID
); 
 719                 srcKey
->startBlock 
= SWAP_BE32(srcKey
->startBlock
); 
 722                          * Swap and check the attribute name 
 724                 if (direction 
== kSwapBTNodeBigToHost
) 
 725                         srcKey
->attrNameLen 
= SWAP_BE16(srcKey
->attrNameLen
); 
 726                 /* Sanity check the attribute name length */ 
 727                 if (srcKey
->attrNameLen 
> kHFSMaxAttrNameLen 
|| keyLength 
< (kHFSPlusAttrKeyMinimumLength 
+ sizeof(u_int16_t
)*srcKey
->attrNameLen
)) { 
 728                                 if (direction 
== kSwapBTNodeHostToBig
) { 
 729                                         panic("hfs_swap_HFSPlusBTInternalNode: attr key #%d keyLength=%d attrNameLen=%d\n", srcDesc
->numRecords
-i
-1, keyLength
, srcKey
->attrNameLen
); 
 731                                         printf("hfs_swap_HFSPlusBTInternalNode: attr key #%d keyLength=%d attrNameLen=%d\n", srcDesc
->numRecords
-i
-1, keyLength
, srcKey
->attrNameLen
); 
 733                                 return fsBTInvalidNodeErr
; 
 735                 for (j 
= 0; j 
< srcKey
->attrNameLen
; j
++) 
 736                         srcKey
->attrName
[j
] = SWAP_BE16(srcKey
->attrName
[j
]); 
 737                 if (direction 
== kSwapBTNodeHostToBig
) 
 738                         srcKey
->attrNameLen 
= SWAP_BE16(srcKey
->attrNameLen
); 
 741              * For index nodes, the record data is just the child's node number. 
 742              * Skip over swapping the various types of attribute record. 
 744             if (srcDesc
->kind 
== kBTIndexNode
) { 
 745                 *((u_int32_t 
*)srcRec
) = SWAP_BE32 (*((u_int32_t 
*)srcRec
)); 
 749             /* Swap the record data */ 
 750             if (direction 
== kSwapBTNodeBigToHost
) 
 751                 srcRec
->recordType 
= SWAP_BE32(srcRec
->recordType
); 
 752             switch (srcRec
->recordType
) { 
 753                 case kHFSPlusAttrInlineData
: 
 754                         /* Is there room for the inline data header? */ 
 755                         if ((char *) &srcRec
->attrData
.attrData
[0]  > nextRecord
) { 
 756                                                 if (direction 
== kSwapBTNodeHostToBig
) { 
 757                                                         panic("hfs_swap_HFSPlusBTInternalNode: attr inline #%d too big\n", srcDesc
->numRecords
-i
-1); 
 759                                                         printf("hfs_swap_HFSPlusBTInternalNode: attr inline #%d too big\n", srcDesc
->numRecords
-i
-1); 
 761                                                 return fsBTInvalidNodeErr
; 
 764                         /* We're not swapping the reserved fields */ 
 766                         /* Swap the attribute size */ 
 767                         if (direction 
== kSwapBTNodeHostToBig
) 
 768                                 attrSize 
= srcRec
->attrData
.attrSize
; 
 769                         srcRec
->attrData
.attrSize 
= SWAP_BE32(srcRec
->attrData
.attrSize
); 
 770                         if (direction 
== kSwapBTNodeBigToHost
) 
 771                                 attrSize 
= srcRec
->attrData
.attrSize
; 
 773                         /* Is there room for the inline attribute data? */ 
 774                         if ((char *) &srcRec
->attrData
.attrData
[attrSize
] > nextRecord
) { 
 775                                                 if (direction 
== kSwapBTNodeHostToBig
) { 
 776                                                         panic("hfs_swap_HFSPlusBTInternalNode: attr inline #%d too big (attrSize=%u)\n", srcDesc
->numRecords
-i
-1, attrSize
); 
 778                                                         printf("hfs_swap_HFSPlusBTInternalNode: attr inline #%d too big (attrSize=%u)\n", srcDesc
->numRecords
-i
-1, attrSize
); 
 780                                                 return fsBTInvalidNodeErr
; 
 783                         /* Not swapping the attribute data itself */ 
 786                 case kHFSPlusAttrForkData
: 
 787                         /* Is there room for the fork data record? */ 
 788                         if ((char *)srcRec 
+ sizeof(HFSPlusAttrForkData
) > nextRecord
) { 
 789                                                 if (direction 
== kSwapBTNodeHostToBig
) { 
 790                                                         panic("hfs_swap_HFSPlusBTInternalNode: attr fork data #%d too big\n", srcDesc
->numRecords
-i
-1); 
 792                                                         printf("hfs_swap_HFSPlusBTInternalNode: attr fork data #%d too big\n", srcDesc
->numRecords
-i
-1); 
 794                                                 return fsBTInvalidNodeErr
; 
 797                         /* We're not swapping the reserved field */ 
 799                         hfs_swap_HFSPlusForkData(&srcRec
->forkData
.theFork
); 
 802                 case kHFSPlusAttrExtents
: 
 803                         /* Is there room for an extent record? */ 
 804                         if ((char *)srcRec 
+ sizeof(HFSPlusAttrExtents
) > nextRecord
) { 
 805                                                 if (direction 
== kSwapBTNodeHostToBig
) { 
 806                                                         panic("hfs_swap_HFSPlusBTInternalNode: attr extents #%d too big\n", srcDesc
->numRecords
-i
-1); 
 808                                                         printf("hfs_swap_HFSPlusBTInternalNode: attr extents #%d too big\n", srcDesc
->numRecords
-i
-1); 
 810                                                 return fsBTInvalidNodeErr
; 
 813                         /* We're not swapping the reserved field */ 
 815                         for (j 
= 0; j 
< kHFSPlusExtentDensity
; j
++) { 
 816                                 srcRec
->overflowExtents
.extents
[j
].startBlock 
= 
 817                                         SWAP_BE32(srcRec
->overflowExtents
.extents
[j
].startBlock
); 
 818                                 srcRec
->overflowExtents
.extents
[j
].blockCount 
= 
 819                                         SWAP_BE32(srcRec
->overflowExtents
.extents
[j
].blockCount
); 
 823             if (direction 
== kSwapBTNodeHostToBig
) 
 824                 srcRec
->recordType 
= SWAP_BE32(srcRec
->recordType
); 
 826     } else if (fileID 
> kHFSFirstUserCatalogNodeID
) { 
 827         /* The only B-tree with a non-system CNID that we use is the hotfile B-tree */ 
 831                 for (i 
= 0; i 
< srcDesc
->numRecords
; i
++) { 
 832                 /* Point to the start of the record we're currently checking. */ 
 833                         srcKey 
= (HotFileKey 
*)((char *)src
->buffer 
+ srcOffs
[i
]); 
 836              * Point to start of next (larger offset) record.  We'll use this 
 837              * to be sure the current record doesn't overflow into the next 
 840                         nextRecord 
= (char *)src
->buffer 
+ srcOffs
[i
-1]; 
 842                         /* Make sure there is room for the key (HotFileKey) and data (u_int32_t) */ 
 843                         if ((char *)srcKey 
+ sizeof(HotFileKey
) + sizeof(u_int32_t
) > nextRecord
) { 
 844                                 if (direction 
== kSwapBTNodeHostToBig
) { 
 845                                         panic("hfs_swap_HFSPlusBTInternalNode: hotfile #%d offset too big (0x%04X)\n", srcDesc
->numRecords
-i
-1, srcOffs
[i
]); 
 847                                         printf("hfs_swap_HFSPlusBTInternalNode: hotfile #%d offset too big (0x%04X)\n", srcDesc
->numRecords
-i
-1, srcOffs
[i
]); 
 849                                 return fsBTInvalidNodeErr
; 
 852                         /* Swap and sanity check the key length field */ 
 853                         if (direction 
== kSwapBTNodeBigToHost
) 
 854                                 srcKey
->keyLength 
= SWAP_BE16 (srcKey
->keyLength
); 
 855                         if (srcKey
->keyLength 
!= sizeof(*srcKey
) - sizeof(srcKey
->keyLength
)) { 
 856                                 if (direction 
== kSwapBTNodeHostToBig
) { 
 857                                         panic("hfs_swap_HFSPlusBTInternalNode: hotfile #%d incorrect keyLength %d\n", srcDesc
->numRecords
-i
-1, srcKey
->keyLength
); 
 859                                         printf("hfs_swap_HFSPlusBTInternalNode: hotfile #%d incorrect keyLength %d\n", srcDesc
->numRecords
-i
-1, srcKey
->keyLength
); 
 861                                 return fsBTInvalidNodeErr
; 
 863                         srcRec 
= (u_int32_t 
*)((char *)srcKey 
+ srcKey
->keyLength 
+ sizeof(srcKey
->keyLength
)); 
 864                         if (direction 
== kSwapBTNodeHostToBig
) 
 865                                 srcKey
->keyLength 
= SWAP_BE16 (srcKey
->keyLength
); 
 867                         /* Don't swap srcKey->forkType */ 
 868                         /* Don't swap srcKey->pad */ 
 870                         srcKey
->temperature 
= SWAP_BE32 (srcKey
->temperature
); 
 871                         srcKey
->fileID 
= SWAP_BE32 (srcKey
->fileID
); 
 873                         *((u_int32_t 
*)srcRec
) = SWAP_BE32 (*((u_int32_t 
*)srcRec
)); 
 876         panic ("hfs_swap_HFSPlusBTInternalNode: fileID %u is not a system B-tree\n", fileID
); 
 884 hfs_swap_HFSBTInternalNode ( 
 885     BlockDescriptor 
*src
, 
 886     HFSCatalogNodeID fileID
, 
 887     enum HFSBTSwapDirection direction
 
 890     BTNodeDescriptor 
*srcDesc 
= src
->buffer
; 
 891     u_int16_t 
*srcOffs 
= (u_int16_t 
*)((char *)src
->buffer 
+ (src
->blockSize 
- (srcDesc
->numRecords 
* sizeof (u_int16_t
)))); 
 892         char *nextRecord
;       /*  Points to start of record following current one */ 
 895      * i is an int32 because it needs to be negative to index the offset to free space. 
 896      * srcDesc->numRecords is a u_int16_t and is unlikely to become 32-bit so this should be ok. 
 901     if (fileID 
== kHFSExtentsFileID
) { 
 902         HFSExtentKey 
*srcKey
; 
 903         HFSExtentDescriptor 
*srcRec
; 
 904                 size_t recordSize
;      /* Size of the data part of the record, or node number for index nodes */ 
 906         if (srcDesc
->kind 
== kBTIndexNode
) 
 907                 recordSize 
= sizeof(u_int32_t
); 
 909                 recordSize 
= sizeof(HFSExtentDescriptor
); 
 911         for (i 
= 0; i 
< srcDesc
->numRecords
; i
++) { 
 912                 /* Point to the start of the record we're currently checking. */ 
 913             srcKey 
= (HFSExtentKey 
*)((char *)src
->buffer 
+ srcOffs
[i
]); 
 916              * Point to start of next (larger offset) record.  We'll use this 
 917              * to be sure the current record doesn't overflow into the next 
 920                         nextRecord 
= (char *)src
->buffer 
+ srcOffs
[i
-1]; 
 923                          * Make sure the key and data are within the buffer.  Since both key 
 924                          * and data are fixed size, this is relatively easy.  Note that this 
 925                          * relies on the keyLength being a constant; we verify the keyLength 
 928                         if ((char *)srcKey 
+ sizeof(HFSExtentKey
) + recordSize 
> nextRecord
) { 
 929                                 if (direction 
== kSwapBTNodeHostToBig
) { 
 930                                         panic("hfs_swap_HFSBTInternalNode: extents key #%d offset too big (0x%04X)\n", srcDesc
->numRecords
-i
-1, srcOffs
[i
]); 
 932                                         printf("hfs_swap_HFSBTInternalNode: extents key #%d offset too big (0x%04X)\n", srcDesc
->numRecords
-i
-1, srcOffs
[i
]); 
 934                                 return fsBTInvalidNodeErr
; 
 937             /* Don't swap srcKey->keyLength (it's only one byte), but do sanity check it */ 
 938             if (srcKey
->keyLength 
!= sizeof(*srcKey
) - sizeof(srcKey
->keyLength
)) { 
 939                                 if (direction 
== kSwapBTNodeHostToBig
) { 
 940                                         panic("hfs_swap_HFSBTInternalNode: extents key #%d invalid length (%d)\n", srcDesc
->numRecords
-i
-1, srcKey
->keyLength
); 
 942                                         printf("hfs_swap_HFSBTInternalNode: extents key #%d invalid length (%d)\n", srcDesc
->numRecords
-i
-1, srcKey
->keyLength
); 
 944                                 return fsBTInvalidNodeErr
; 
 947             /* Don't swap srcKey->forkType; it's only one byte */ 
 949             srcKey
->fileID                      
= SWAP_BE32 (srcKey
->fileID
); 
 950             srcKey
->startBlock          
= SWAP_BE16 (srcKey
->startBlock
); 
 952             /* Point to record data (round up to even byte boundary) */ 
 953             srcRec 
= (HFSExtentDescriptor 
*)((char *)srcKey 
+ ((srcKey
->keyLength 
+ 2) & ~1)); 
 955             if (srcDesc
->kind 
== kBTIndexNode
) { 
 956                 /* For index nodes, the record data is just a child node number. */ 
 957                 *((u_int32_t 
*)srcRec
) = SWAP_BE32 (*((u_int32_t 
*)srcRec
)); 
 959                                 /* Swap the extent data */ 
 960                                 for (j 
= 0; j 
< kHFSExtentDensity
; j
++) { 
 961                                         srcRec
[j
].startBlock    
= SWAP_BE16 (srcRec
[j
].startBlock
); 
 962                                         srcRec
[j
].blockCount    
= SWAP_BE16 (srcRec
[j
].blockCount
); 
 967     } else if (fileID 
== kHFSCatalogFileID
) { 
 968         HFSCatalogKey 
*srcKey
; 
 970         unsigned expectedKeyLength
; 
 972         for (i 
= 0; i 
< srcDesc
->numRecords
; i
++) { 
 973                 /* Point to the start of the record we're currently checking. */ 
 974             srcKey 
= (HFSCatalogKey 
*)((char *)src
->buffer 
+ srcOffs
[i
]); 
 977              * Point to start of next (larger offset) record.  We'll use this 
 978              * to be sure the current record doesn't overflow into the next 
 981                         nextRecord 
= (char *)src
->buffer 
+ srcOffs
[i
-1]; 
 984                          * Make sure we can safely dereference the keyLength and parentID fields. 
 985                          * The value 8 below is 1 bytes for keyLength + 1 byte reserved + 4 bytes 
 986                          * for parentID + 1 byte for nodeName's length + 1 byte to round up the 
 987                          * record start to an even offset, which forms a minimal key. 
 989                         if ((char *)srcKey 
+ 8 > nextRecord
) { 
 990                                 if (direction 
== kSwapBTNodeHostToBig
) { 
 991                                         panic("hfs_swap_HFSBTInternalNode: catalog key #%d offset too big (0x%04X)\n", srcDesc
->numRecords
-i
-1, srcOffs
[i
]); 
 993                                         printf("hfs_swap_HFSBTInternalNode: catalog key #%d offset too big (0x%04X)\n", srcDesc
->numRecords
-i
-1, srcOffs
[i
]); 
 995                                 return fsBTInvalidNodeErr
; 
 998             /* Don't swap srcKey->keyLength (it's only one byte), but do sanity check it */ 
 999             if (srcKey
->keyLength 
< kHFSCatalogKeyMinimumLength 
|| srcKey
->keyLength 
> kHFSCatalogKeyMaximumLength
) { 
1000                                 if (direction 
== kSwapBTNodeHostToBig
) { 
1001                                         panic("hfs_swap_HFSBTInternalNode: catalog key #%d invalid length (%d)\n", srcDesc
->numRecords
-i
-1, srcKey
->keyLength
); 
1003                                         printf("hfs_swap_HFSBTInternalNode: catalog key #%d invalid length (%d)\n", srcDesc
->numRecords
-i
-1, srcKey
->keyLength
); 
1005                                 return fsBTInvalidNodeErr
; 
1008             /* Don't swap srcKey->reserved */ 
1010             srcKey
->parentID                    
= SWAP_BE32 (srcKey
->parentID
); 
1012             /* Don't swap srcKey->nodeName */ 
1014                         /* Make sure the keyLength is big enough for the key's content */ 
1015                         if (srcDesc
->kind 
== kBTIndexNode
) 
1016                                 expectedKeyLength 
= sizeof(*srcKey
) - sizeof(srcKey
->keyLength
); 
1018                                 expectedKeyLength 
= srcKey
->nodeName
[0] + kHFSCatalogKeyMinimumLength
; 
1019             if (srcKey
->keyLength 
< expectedKeyLength
) { 
1020                                 if (direction 
== kSwapBTNodeHostToBig
) { 
1021                                         panic("hfs_swap_HFSBTInternalNode: catalog record #%d keyLength=%u expected=%u\n", 
1022                                                 srcDesc
->numRecords
-i
, srcKey
->keyLength
, expectedKeyLength
); 
1024                                         printf("hfs_swap_HFSBTInternalNode: catalog record #%d keyLength=%u expected=%u\n", 
1025                                                 srcDesc
->numRecords
-i
, srcKey
->keyLength
, expectedKeyLength
); 
1027                                 return fsBTInvalidNodeErr
; 
1030             /* Point to record data (round up to even byte boundary) */ 
1031             srcPtr 
= (int16_t *)((char *)srcKey 
+ ((srcKey
->keyLength 
+ 2) & ~1)); 
1034              * Make sure that we can safely dereference the record's type field or 
1035              * and index node's child node number. 
1037             if ((char *)srcPtr 
+ sizeof(u_int32_t
) > nextRecord
) { 
1038                                 if (direction 
== kSwapBTNodeHostToBig
) { 
1039                                         panic("hfs_swap_HFSBTInternalNode: catalog key #%d too big\n", srcDesc
->numRecords
-i
-1); 
1041                                         printf("hfs_swap_HFSBTInternalNode: catalog key #%d too big\n", srcDesc
->numRecords
-i
-1); 
1043                                 return fsBTInvalidNodeErr
; 
1047              * For index nodes, the record data is just the child's node number. 
1048              * Skip over swapping the various types of catalog record. 
1050             if (srcDesc
->kind 
== kBTIndexNode
) { 
1051                 *((u_int32_t 
*)srcPtr
) = SWAP_BE32 (*((u_int32_t 
*)srcPtr
)); 
1055             /* Make sure the recordType is in native order before using it. */ 
1056             if (direction 
== kSwapBTNodeBigToHost
) 
1057                 srcPtr
[0] = SWAP_BE16 (srcPtr
[0]); 
1059             if (srcPtr
[0] == kHFSFolderRecord
) { 
1060                 HFSCatalogFolder 
*srcRec 
= (HFSCatalogFolder 
*)srcPtr
; 
1061                 if ((char *)srcRec 
+ sizeof(*srcRec
) > nextRecord
) { 
1062                                         if (direction 
== kSwapBTNodeHostToBig
) { 
1063                                                 panic("hfs_swap_HFSBTInternalNode: catalog folder record #%d too big\n", srcDesc
->numRecords
-i
-1); 
1065                                                 printf("hfs_swap_HFSBTInternalNode: catalog folder record #%d too big\n", srcDesc
->numRecords
-i
-1); 
1067                                         return fsBTInvalidNodeErr
; 
1070                 srcRec
->flags                           
= SWAP_BE16 (srcRec
->flags
); 
1071                 srcRec
->valence                         
= SWAP_BE16 (srcRec
->valence
); 
1073                 srcRec
->folderID                        
= SWAP_BE32 (srcRec
->folderID
); 
1074                 srcRec
->createDate                      
= SWAP_BE32 (srcRec
->createDate
); 
1075                 srcRec
->modifyDate                      
= SWAP_BE32 (srcRec
->modifyDate
); 
1076                 srcRec
->backupDate                      
= SWAP_BE32 (srcRec
->backupDate
); 
1078                 /* Don't swap srcRec->userInfo */ 
1079                 /* Don't swap srcRec->finderInfo */ 
1080                 /* Don't swap resserved array */ 
1082             } else if (srcPtr
[0] == kHFSFileRecord
) { 
1083                 HFSCatalogFile 
*srcRec 
= (HFSCatalogFile 
*)srcPtr
; 
1084                 if ((char *)srcRec 
+ sizeof(*srcRec
) > nextRecord
) { 
1085                                         if (direction 
== kSwapBTNodeHostToBig
) { 
1086                                                 panic("hfs_swap_HFSBTInternalNode: catalog file record #%d too big\n", srcDesc
->numRecords
-i
-1); 
1088                                                 printf("hfs_swap_HFSBTInternalNode: catalog file record #%d too big\n", srcDesc
->numRecords
-i
-1); 
1090                                         return fsBTInvalidNodeErr
; 
1093                 srcRec
->flags                           
= srcRec
->flags
; 
1094                 srcRec
->fileType                        
= srcRec
->fileType
; 
1096                 /* Don't swap srcRec->userInfo */ 
1098                 srcRec
->fileID                          
= SWAP_BE32 (srcRec
->fileID
); 
1100                 srcRec
->dataStartBlock          
= SWAP_BE16 (srcRec
->dataStartBlock
); 
1101                 srcRec
->dataLogicalSize         
= SWAP_BE32 (srcRec
->dataLogicalSize
); 
1102                 srcRec
->dataPhysicalSize        
= SWAP_BE32 (srcRec
->dataPhysicalSize
); 
1104                 srcRec
->rsrcStartBlock          
= SWAP_BE16 (srcRec
->rsrcStartBlock
); 
1105                 srcRec
->rsrcLogicalSize         
= SWAP_BE32 (srcRec
->rsrcLogicalSize
); 
1106                 srcRec
->rsrcPhysicalSize        
= SWAP_BE32 (srcRec
->rsrcPhysicalSize
); 
1108                 srcRec
->createDate                      
= SWAP_BE32 (srcRec
->createDate
); 
1109                 srcRec
->modifyDate                      
= SWAP_BE32 (srcRec
->modifyDate
); 
1110                 srcRec
->backupDate                      
= SWAP_BE32 (srcRec
->backupDate
); 
1112                 /* Don't swap srcRec->finderInfo */ 
1114                 srcRec
->clumpSize                       
= SWAP_BE16 (srcRec
->clumpSize
); 
1116                 /* Swap the two sets of extents as an array of six (three each) u_int16_t */ 
1117                 for (j 
= 0; j 
< kHFSExtentDensity 
* 2; j
++) { 
1118                     srcRec
->dataExtents
[j
].startBlock   
= SWAP_BE16 (srcRec
->dataExtents
[j
].startBlock
); 
1119                     srcRec
->dataExtents
[j
].blockCount   
= SWAP_BE16 (srcRec
->dataExtents
[j
].blockCount
); 
1122                 /* Don't swap srcRec->reserved */ 
1124             } else if ((srcPtr
[0] == kHFSFolderThreadRecord
) || 
1125                     (srcPtr
[0] == kHFSFileThreadRecord
)) { 
1126                 HFSCatalogThread 
*srcRec 
= (HFSCatalogThread 
*)srcPtr
; 
1128                 /* Make sure there is room for parentID and name length */ 
1129                 if ((char *) &srcRec
->nodeName
[1] > nextRecord
) { 
1130                                         if (direction 
== kSwapBTNodeHostToBig
) { 
1131                                                 panic("hfs_swap_HFSBTInternalNode: catalog thread record #%d too big\n", srcDesc
->numRecords
-i
-1); 
1133                                                 printf("hfs_swap_HFSBTInternalNode: catalog thread record #%d too big\n", srcDesc
->numRecords
-i
-1); 
1135                                         return fsBTInvalidNodeErr
; 
1138                 /* Don't swap srcRec->reserved array */ 
1140                 srcRec
->parentID                        
= SWAP_BE32 (srcRec
->parentID
); 
1142                 /* Don't swap srcRec->nodeName */ 
1144                         /* Make sure there is room for the name in the buffer */ 
1145                 if ((char *) &srcRec
->nodeName
[srcRec
->nodeName
[0]] > nextRecord
) { 
1146                                         if (direction 
== kSwapBTNodeHostToBig
) { 
1147                                                 panic("hfs_swap_HFSBTInternalNode: catalog thread record #%d name too big\n", srcDesc
->numRecords
-i
-1); 
1149                                                 printf("hfs_swap_HFSBTInternalNode: catalog thread record #%d name too big\n", srcDesc
->numRecords
-i
-1); 
1151                                         return fsBTInvalidNodeErr
; 
1154                                 if (direction 
== kSwapBTNodeHostToBig
) { 
1155                         panic("hfs_swap_HFSBTInternalNode: unrecognized catalog record type (0x%04X; record #%d)\n", srcPtr
[0], srcDesc
->numRecords
-i
-1); 
1157                         printf("hfs_swap_HFSBTInternalNode: unrecognized catalog record type (0x%04X; record #%d)\n", srcPtr
[0], srcDesc
->numRecords
-i
-1); 
1159                                 return fsBTInvalidNodeErr
; 
1162             /* We can swap the record type now that we're done using it */ 
1163             if (direction 
== kSwapBTNodeHostToBig
) 
1164                 srcPtr
[0] = SWAP_BE16 (srcPtr
[0]); 
1168         panic ("hfs_swap_HFSBTInternalNode: fileID %u is not a system B-tree\n", fileID
);