]> git.saurik.com Git - apple/xnu.git/blob - bsd/hfs/hfs_endian.c
d01635c4eb752fab4db916de103404e025d11730
[apple/xnu.git] / bsd / hfs / hfs_endian.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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.
11 *
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
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
23 /*
24 * hfs_endian.c
25 *
26 * This file implements endian swapping routines for the HFS/HFS Plus
27 * volume format.
28 */
29
30 #include <architecture/byte_order.h>
31
32 #include "hfs_endian.h"
33 #include "hfs_dbg.h"
34
35 #undef ENDIAN_DEBUG
36
37 /* Private swapping routines */
38 int hfs_swap_HFSPlusBTInternalNode (BlockDescriptor *src, HFSCatalogNodeID fileID, int unswap);
39 int hfs_swap_HFSBTInternalNode (BlockDescriptor *src, HFSCatalogNodeID fileID, int unswap);
40
41 /*
42 * hfs_swap_HFSPlusForkData
43 *
44 * There's still a few spots where we still need to swap the fork data.
45 */
46 void
47 hfs_swap_HFSPlusForkData (
48 HFSPlusForkData *src
49 )
50 {
51 int i;
52
53 DBG_FUNC_NAME("hfs_swap_HFSPlusForkData");
54 DBG_PRINT_FUNC_NAME();
55
56 src->logicalSize = SWAP_BE64 (src->logicalSize);
57
58 src->clumpSize = SWAP_BE32 (src->clumpSize);
59 src->totalBlocks = SWAP_BE32 (src->totalBlocks);
60
61 for (i = 0; i < kHFSPlusExtentDensity; i++) {
62 src->extents[i].startBlock = SWAP_BE32 (src->extents[i].startBlock);
63 src->extents[i].blockCount = SWAP_BE32 (src->extents[i].blockCount);
64 }
65 }
66
67 /*
68 * hfs_swap_BTNode
69 *
70 * NOTE: This operation is not naturally symmetric.
71 * We have to determine which way we're swapping things.
72 */
73 int
74 hfs_swap_BTNode (
75 BlockDescriptor *src,
76 int isHFSPlus,
77 HFSCatalogNodeID fileID,
78 int unswap
79 )
80 {
81 BTNodeDescriptor *srcDesc = src->buffer;
82 UInt16 *srcOffs = NULL;
83
84 UInt32 i;
85 int error = 0;
86
87 DBG_FUNC_NAME("hfs_swap_BTNode");
88 DBG_PRINT_FUNC_NAME();
89
90 #ifdef ENDIAN_DEBUG
91 if (unswap == 0) {
92 printf ("BE -> LE Swap\n");
93 } else if (unswap == 1) {
94 printf ("LE -> BE Swap\n");
95 } else if (unswap == 3) {
96 printf ("Not swapping descriptors\n");
97 } else {
98 panic ("%s This is impossible", "hfs_swap_BTNode:");
99 }
100 #endif
101
102 /* If we are doing a swap */
103 if (unswap == 0) {
104 /* Swap the node descriptor */
105 srcDesc->fLink = SWAP_BE32 (srcDesc->fLink);
106 srcDesc->bLink = SWAP_BE32 (srcDesc->bLink);
107
108 /* Don't swap srcDesc->kind */
109 /* Don't swap srcDesc->height */
110 /* Don't swap srcDesc->reserved */
111
112 srcDesc->numRecords = SWAP_BE16 (srcDesc->numRecords);
113
114 /* Swap the node offsets (including the free space one!) */
115 srcOffs = (UInt16 *)((char *)src->buffer + (src->blockSize - ((srcDesc->numRecords + 1) * sizeof (UInt16))));
116
117 /* Sanity check */
118 if ((char *)srcOffs > ((char *)src->buffer + src->blockSize)) {
119 panic ("%s Too many records in the B-Tree node", "hfs_swap_BTNode:");
120 }
121
122 for (i = 0; i < srcDesc->numRecords + 1; i++) {
123 srcOffs[i] = SWAP_BE16 (srcOffs[i]);
124
125 /* Sanity check */
126 if (srcOffs[i] >= src->blockSize) {
127 panic ("%s B-Tree node offset out of range", "hfs_swap_BTNode:");
128 }
129 }
130 }
131
132 /* Swap the records (ordered by frequency of access) */
133 /* Swap a B-Tree internal node */
134 if ((srcDesc->kind == kBTIndexNode) ||
135 (srcDesc-> kind == kBTLeafNode)) {
136
137 if (isHFSPlus) {
138 error = hfs_swap_HFSPlusBTInternalNode (src, fileID, unswap);
139 } else {
140 error = hfs_swap_HFSBTInternalNode (src, fileID, unswap);
141 }
142
143 /* Swap a B-Tree map node */
144 } else if (srcDesc-> kind == kBTMapNode) {
145 /* Don't swap the bitmaps, they'll be done in the bitmap routines */
146
147 /* Swap a B-Tree header node */
148 } else if (srcDesc-> kind == kBTHeaderNode) {
149 /* The header's offset is hard-wired because we cannot trust the offset pointers */
150 BTHeaderRec *srcHead = (BTHeaderRec *)((char *)src->buffer + 14);
151
152 srcHead->treeDepth = SWAP_BE16 (srcHead->treeDepth);
153
154 srcHead->rootNode = SWAP_BE32 (srcHead->rootNode);
155 srcHead->leafRecords = SWAP_BE32 (srcHead->leafRecords);
156 srcHead->firstLeafNode = SWAP_BE32 (srcHead->firstLeafNode);
157 srcHead->lastLeafNode = SWAP_BE32 (srcHead->lastLeafNode);
158
159 srcHead->nodeSize = SWAP_BE16 (srcHead->nodeSize);
160 srcHead->maxKeyLength = SWAP_BE16 (srcHead->maxKeyLength);
161
162 srcHead->totalNodes = SWAP_BE32 (srcHead->totalNodes);
163 srcHead->freeNodes = SWAP_BE32 (srcHead->freeNodes);
164
165 srcHead->clumpSize = SWAP_BE32 (srcHead->clumpSize);
166 srcHead->attributes = SWAP_BE32 (srcHead->attributes);
167
168 /* Don't swap srcHead->reserved1 */
169 /* Don't swap srcHead->btreeType */
170 /* Don't swap srcHead->reserved2 */
171 /* Don't swap srcHead->reserved3 */
172 /* Don't swap bitmap */
173 }
174
175 /* If we are doing an unswap */
176 if (unswap == 1) {
177 /* Swap the node descriptor */
178 srcDesc->fLink = SWAP_BE32 (srcDesc->fLink);
179 srcDesc->bLink = SWAP_BE32 (srcDesc->bLink);
180
181 /* Don't swap srcDesc->kind */
182 /* Don't swap srcDesc->height */
183 /* Don't swap srcDesc->reserved */
184
185 /* Swap the node offsets (including the free space one!) */
186 srcOffs = (UInt16 *)((char *)src->buffer + (src->blockSize - ((srcDesc->numRecords + 1) * sizeof (UInt16))));
187
188 /* Sanity check */
189 if ((char *)srcOffs > ((char *)src->buffer + src->blockSize)) {
190 panic ("%s Too many records in the B-Tree node", "hfs_swap_BTNode:");
191 }
192
193 for (i = 0; i < srcDesc->numRecords + 1; i++) {
194 /* Sanity check */
195 if (srcOffs[i] >= src->blockSize) {
196 panic ("%s B-Tree node offset out of range", "hfs_swap_BTNode:");
197 }
198
199 srcOffs[i] = SWAP_BE16 (srcOffs[i]);
200 }
201
202 srcDesc->numRecords = SWAP_BE16 (srcDesc->numRecords);
203 }
204
205 return (error);
206 }
207
208 int
209 hfs_swap_HFSPlusBTInternalNode (
210 BlockDescriptor *src,
211 HFSCatalogNodeID fileID,
212 int unswap
213 )
214 {
215 BTNodeDescriptor *srcDesc = src->buffer;
216 UInt16 *srcOffs = (UInt16 *)((char *)src->buffer + (src->blockSize - (srcDesc->numRecords * sizeof (UInt16))));
217
218 UInt32 i;
219 UInt32 j;
220
221 DBG_FUNC_NAME("hfs_swap_HFSPlusBTInternalNode");
222 DBG_PRINT_FUNC_NAME();
223
224 if (fileID == kHFSExtentsFileID) {
225 HFSPlusExtentKey *srcKey;
226 HFSPlusExtentDescriptor *srcRec;
227
228 for (i = 0; i < srcDesc->numRecords; i++) {
229 srcKey = (HFSPlusExtentKey *)((char *)src->buffer + srcOffs[i]);
230
231 if (!unswap) srcKey->keyLength = SWAP_BE16 (srcKey->keyLength);
232 srcRec = (HFSPlusExtentDescriptor *)((char *)srcKey + srcKey->keyLength + 2);
233 if (unswap) srcKey->keyLength = SWAP_BE16 (srcKey->keyLength);
234
235 /* Don't swap srcKey->forkType */
236 /* Don't swap srcKey->pad */
237
238 srcKey->fileID = SWAP_BE32 (srcKey->fileID);
239 srcKey->startBlock = SWAP_BE32 (srcKey->startBlock);
240
241 /* Stop if this is just an index node */
242 if (srcDesc->kind == kBTIndexNode) {
243 *((UInt32 *)srcRec) = SWAP_BE32 (*((UInt32 *)srcRec));
244 continue;
245 }
246
247 /* Swap the extent data */
248
249 /* Swap each extent */
250 for (j = 0; j < kHFSPlusExtentDensity; j++) {
251 srcRec[j].startBlock = SWAP_BE32 (srcRec[j].startBlock);
252 srcRec[j].blockCount = SWAP_BE32 (srcRec[j].blockCount);
253 }
254 }
255
256 } else if (fileID == kHFSCatalogFileID) {
257 HFSPlusCatalogKey *srcKey;
258 SInt16 *srcPtr;
259
260 for (i = 0; i < srcDesc->numRecords; i++) {
261 srcKey = (HFSPlusCatalogKey *)((char *)src->buffer + srcOffs[i]);
262
263 if (!unswap) srcKey->keyLength = SWAP_BE16 (srcKey->keyLength);
264 srcPtr = (SInt16 *)((char *)srcKey + srcKey->keyLength + 2);
265 if (unswap) srcKey->keyLength = SWAP_BE16 (srcKey->keyLength);
266
267 srcKey->parentID = SWAP_BE32 (srcKey->parentID);
268
269 if (!unswap) srcKey->nodeName.length = SWAP_BE16 (srcKey->nodeName.length);
270 for (j = 0; j < srcKey->nodeName.length; j++) {
271 srcKey->nodeName.unicode[j] = SWAP_BE16 (srcKey->nodeName.unicode[j]);
272 }
273 if (unswap) srcKey->nodeName.length = SWAP_BE16 (srcKey->nodeName.length);
274
275 /* Stop if this is just an index node */
276 if (srcDesc->kind == kBTIndexNode) {
277 *((UInt32 *)srcPtr) = SWAP_BE32 (*((UInt32 *)srcPtr));
278 continue;
279 }
280
281 /* Swap the recordType field, if unswapping, leave to later */
282 if (!unswap) srcPtr[0] = SWAP_BE16 (srcPtr[0]);
283
284 if (srcPtr[0] == kHFSPlusFolderRecord) {
285 HFSPlusCatalogFolder *srcRec = (HFSPlusCatalogFolder *)srcPtr;
286
287 srcRec->flags = SWAP_BE16 (srcRec->flags);
288 srcRec->valence = SWAP_BE32 (srcRec->valence);
289 srcRec->folderID = SWAP_BE32 (srcRec->folderID);
290 srcRec->createDate = SWAP_BE32 (srcRec->createDate);
291 srcRec->contentModDate = SWAP_BE32 (srcRec->contentModDate);
292 srcRec->attributeModDate = SWAP_BE32 (srcRec->attributeModDate);
293 srcRec->accessDate = SWAP_BE32 (srcRec->accessDate);
294 srcRec->backupDate = SWAP_BE32 (srcRec->backupDate);
295
296 srcRec->bsdInfo.ownerID = SWAP_BE32 (srcRec->bsdInfo.ownerID);
297 srcRec->bsdInfo.groupID = SWAP_BE32 (srcRec->bsdInfo.groupID);
298
299 /* Don't swap srcRec->bsdInfo.adminFlags */
300 /* Don't swap srcRec->bsdInfo.ownerFlags */
301
302 srcRec->bsdInfo.fileMode = SWAP_BE16 (srcRec->bsdInfo.fileMode);
303 srcRec->bsdInfo.special.iNodeNum = SWAP_BE32 (srcRec->bsdInfo.special.iNodeNum);
304
305 srcRec->textEncoding = SWAP_BE32 (srcRec->textEncoding);
306
307 /* Don't swap srcRec->userInfo */
308 /* Don't swap srcRec->finderInfo */
309 /* Don't swap srcRec->reserved */
310
311 } else if (srcPtr[0] == kHFSPlusFileRecord) {
312 HFSPlusCatalogFile *srcRec = (HFSPlusCatalogFile *)srcPtr;
313
314 srcRec->flags = SWAP_BE16 (srcRec->flags);
315
316 srcRec->fileID = SWAP_BE32 (srcRec->fileID);
317
318 srcRec->createDate = SWAP_BE32 (srcRec->createDate);
319 srcRec->contentModDate = SWAP_BE32 (srcRec->contentModDate);
320 srcRec->attributeModDate = SWAP_BE32 (srcRec->attributeModDate);
321 srcRec->accessDate = SWAP_BE32 (srcRec->accessDate);
322 srcRec->backupDate = SWAP_BE32 (srcRec->backupDate);
323
324 srcRec->bsdInfo.ownerID = SWAP_BE32 (srcRec->bsdInfo.ownerID);
325 srcRec->bsdInfo.groupID = SWAP_BE32 (srcRec->bsdInfo.groupID);
326
327 /* Don't swap srcRec->bsdInfo.adminFlags */
328 /* Don't swap srcRec->bsdInfo.ownerFlags */
329
330 srcRec->bsdInfo.fileMode = SWAP_BE16 (srcRec->bsdInfo.fileMode);
331 srcRec->bsdInfo.special.iNodeNum = SWAP_BE32 (srcRec->bsdInfo.special.iNodeNum);
332
333 srcRec->textEncoding = SWAP_BE32 (srcRec->textEncoding);
334
335 /* Don't swap srcRec->reserved1 */
336 /* Don't swap srcRec->userInfo */
337 /* Don't swap srcRec->finderInfo */
338 /* Don't swap srcRec->reserved2 */
339
340 hfs_swap_HFSPlusForkData (&srcRec->dataFork);
341 hfs_swap_HFSPlusForkData (&srcRec->resourceFork);
342
343 } else if ((srcPtr[0] == kHFSPlusFolderThreadRecord) ||
344 (srcPtr[0] == kHFSPlusFileThreadRecord)) {
345
346 HFSPlusCatalogThread *srcRec = (HFSPlusCatalogThread *)srcPtr;
347
348 /* Don't swap srcRec->reserved */
349
350 srcRec->parentID = SWAP_BE32 (srcRec->parentID);
351
352 if (!unswap) srcRec->nodeName.length = SWAP_BE16 (srcRec->nodeName.length);
353 for (j = 0; j < srcRec->nodeName.length; j++) {
354 srcRec->nodeName.unicode[j] = SWAP_BE16 (srcRec->nodeName.unicode[j]);
355 }
356 if (unswap) srcRec->nodeName.length = SWAP_BE16 (srcRec->nodeName.length);
357
358 } else {
359 panic ("%s unrecognized catalog record type", "hfs_swap_BTNode:");
360 }
361
362 /* If unswapping, we can safely unswap type field now */
363 if (unswap) srcPtr[0] = SWAP_BE16 (srcPtr[0]);
364 }
365
366 } else {
367 panic ("%s unrecognized B-Tree type", "hfs_swap_BTNode:");
368 }
369
370 return (0);
371 }
372
373 int
374 hfs_swap_HFSBTInternalNode (
375 BlockDescriptor *src,
376 HFSCatalogNodeID fileID,
377 int unswap
378 )
379 {
380 BTNodeDescriptor *srcDesc = src->buffer;
381 UInt16 *srcOffs = (UInt16 *)((char *)src->buffer + (src->blockSize - (srcDesc->numRecords * sizeof (UInt16))));
382
383 UInt32 i;
384 UInt32 j;
385
386 DBG_FUNC_NAME("hfs_swap_HFSBTInternalNode");
387 DBG_PRINT_FUNC_NAME();
388
389 if (fileID == kHFSExtentsFileID) {
390 HFSExtentKey *srcKey;
391 HFSExtentDescriptor *srcRec;
392
393 for (i = 0; i < srcDesc->numRecords; i++) {
394 srcKey = (HFSExtentKey *)((char *)src->buffer + srcOffs[i]);
395
396 /* Don't swap srcKey->keyLength */
397 /* Don't swap srcKey->forkType */
398
399 srcKey->fileID = SWAP_BE32 (srcKey->fileID);
400 srcKey->startBlock = SWAP_BE16 (srcKey->startBlock);
401
402 /* Point to record data (round up to even byte boundary) */
403 srcRec = (HFSExtentDescriptor *)((char *)srcKey + ((srcKey->keyLength + 2) & ~1));
404
405 /* Stop if this is just an index node */
406 if (srcDesc->kind == kBTIndexNode) {
407 *((UInt32 *)srcRec) = SWAP_BE32 (*((UInt32 *)srcRec));
408 continue;
409 }
410
411 /* Swap each extent */
412 for (j = 0; j < kHFSExtentDensity; j++) {
413 srcRec[j].startBlock = SWAP_BE16 (srcRec[j].startBlock);
414 srcRec[j].blockCount = SWAP_BE16 (srcRec[j].blockCount);
415 }
416 }
417
418 } else if (fileID == kHFSCatalogFileID) {
419 HFSCatalogKey *srcKey;
420 SInt16 *srcPtr;
421
422 for (i = 0; i < srcDesc->numRecords; i++) {
423 srcKey = (HFSCatalogKey *)((char *)src->buffer + srcOffs[i]);
424
425 /* Don't swap srcKey->keyLength */
426 /* Don't swap srcKey->reserved */
427
428 srcKey->parentID = SWAP_BE32 (srcKey->parentID);
429
430 /* Don't swap srcKey->nodeName */
431
432 /* Point to record data (round up to even byte boundary) */
433 srcPtr = (SInt16 *)((char *)srcKey + ((srcKey->keyLength + 2) & ~1));
434
435 /* Stop if this is just an index node */
436 if (srcDesc->kind == kBTIndexNode) {
437 *((UInt32 *)srcPtr) = SWAP_BE32 (*((UInt32 *)srcPtr));
438 continue;
439 }
440
441 /* Swap the recordType field, if unswapping, leave to later */
442 if (!unswap) srcPtr[0] = SWAP_BE16 (srcPtr[0]);
443
444 if (srcPtr[0] == kHFSFolderRecord) {
445 HFSCatalogFolder *srcRec = (HFSCatalogFolder *)srcPtr;
446
447 srcRec->flags = SWAP_BE16 (srcRec->flags);
448 srcRec->valence = SWAP_BE16 (srcRec->valence);
449
450 srcRec->folderID = SWAP_BE32 (srcRec->folderID);
451 srcRec->createDate = SWAP_BE32 (srcRec->createDate);
452 srcRec->modifyDate = SWAP_BE32 (srcRec->modifyDate);
453 srcRec->backupDate = SWAP_BE32 (srcRec->backupDate);
454
455 /* Don't swap srcRec->userInfo */
456 /* Don't swap srcRec->finderInfo */
457 /* Don't swap resserved array */
458
459 } else if (srcPtr[0] == kHFSFileRecord) {
460 HFSCatalogFile *srcRec = (HFSCatalogFile *)srcPtr;
461
462 srcRec->flags = srcRec->flags;
463 srcRec->fileType = srcRec->fileType;
464
465 /* Don't swap srcRec->userInfo */
466
467 srcRec->fileID = SWAP_BE32 (srcRec->fileID);
468
469 srcRec->dataStartBlock = SWAP_BE16 (srcRec->dataStartBlock);
470 srcRec->dataLogicalSize = SWAP_BE32 (srcRec->dataLogicalSize);
471 srcRec->dataPhysicalSize = SWAP_BE32 (srcRec->dataPhysicalSize);
472
473 srcRec->rsrcStartBlock = SWAP_BE16 (srcRec->rsrcStartBlock);
474 srcRec->rsrcLogicalSize = SWAP_BE32 (srcRec->rsrcLogicalSize);
475 srcRec->rsrcPhysicalSize = SWAP_BE32 (srcRec->rsrcPhysicalSize);
476
477 srcRec->createDate = SWAP_BE32 (srcRec->createDate);
478 srcRec->modifyDate = SWAP_BE32 (srcRec->modifyDate);
479 srcRec->backupDate = SWAP_BE32 (srcRec->backupDate);
480
481 /* Don't swap srcRec->finderInfo */
482
483 srcRec->clumpSize = SWAP_BE16 (srcRec->clumpSize);
484
485 /* Swap the two sets of extents as an array of six (three each) UInt16 */
486 for (j = 0; j < kHFSExtentDensity * 2; j++) {
487 srcRec->dataExtents[j].startBlock = SWAP_BE16 (srcRec->dataExtents[j].startBlock);
488 srcRec->dataExtents[j].blockCount = SWAP_BE16 (srcRec->dataExtents[j].blockCount);
489 }
490
491 /* Don't swap srcRec->reserved */
492
493 } else if ((srcPtr[0] == kHFSFolderThreadRecord) ||
494 (srcPtr[0] == kHFSFileThreadRecord)) {
495
496 HFSCatalogThread *srcRec = (HFSCatalogThread *)srcPtr;
497
498 /* Don't swap srcRec->reserved array */
499
500 srcRec->parentID = SWAP_BE32 (srcRec->parentID);
501
502 /* Don't swap srcRec->nodeName */
503
504 } else {
505 panic ("%s unrecognized catalog record type", "hfs_swap_BTNode:");
506 }
507
508 /* If unswapping, we can safely swap type now */
509 if (unswap) srcPtr[0] = SWAP_BE16 (srcPtr[0]);
510 }
511
512 } else {
513 panic ("%s unrecognized B-Tree type", "hfs_swap_BTNode:");
514 }
515
516 return (0);
517 }