static long GetCatalogEntry(long long * dirIndex, char ** name, long * flags, long * time, FinderInfo * finderInfo, long * infoValid) { long extentSize, nodeSize, curNode, index; void *extent; char *nodeBuf, *testKey, *entry; BTNodeDescriptor *node; if (gIsHFSPlus) { extent = &gHFSPlus->catalogFile.extents; extentSize = SWAP_BE64(gHFSPlus->catalogFile.logicalSize); } else { extent = (HFSExtentDescriptor *)&gHFSMDB->drCTExtRec; extentSize = SWAP_BE32(gHFSMDB->drCTFlSize); } nodeSize = SWAP_BE16(gBTHeaders[kBTreeCatalog]->nodeSize); nodeBuf = (char *)malloc(nodeSize); node = (BTNodeDescriptor *)nodeBuf; index = (long) (*dirIndex % nodeSize); curNode = (long) (*dirIndex / nodeSize); // Read the BTree node and get the record for index. ReadExtent(extent, extentSize, kHFSCatalogFileID, (long long) curNode * nodeSize, nodeSize, nodeBuf, 1); GetBTreeRecord(index, nodeBuf, nodeSize, &testKey, &entry); GetCatalogEntryInfo(entry, flags, time, finderInfo, infoValid); // Get the file name. if (gIsHFSPlus) { utf_encodestr(((HFSPlusCatalogKey *)testKey)->nodeName.unicode, SWAP_BE16(((HFSPlusCatalogKey *)testKey)->nodeName.length), (u_int8_t *)gTempStr, 256, OSBigEndian); } else { strncpy(gTempStr, (const char *)&((HFSCatalogKey *)testKey)->nodeName[1], ((HFSCatalogKey *)testKey)->nodeName[0]); gTempStr[((HFSCatalogKey *)testKey)->nodeName[0]] = '\0'; } *name = gTempStr; // Update dirIndex. index++; if (index == SWAP_BE16(node->numRecords)) { index = 0; curNode = SWAP_BE32(node->fLink); } *dirIndex = (long long) curNode * nodeSize + index; free(nodeBuf); return 0; }
static long GetCatalogEntry(unsigned long *dirIndex, char **name, long *flags, long *time) { long nodeSize, index; u_int32_t curNode; u_int64_t extentSize; void *extent; char *nodeBuf, *testKey, *entry; BTNodeDescriptor *node; if (gIsHFSPlus) { extent = &gHFSPlus->catalogFile.extents; extentSize = gHFSPlus->catalogFile.logicalSize; } else { extent = (HFSExtentDescriptor *)&gHFSMDB->drCTExtRec; extentSize = gHFSMDB->drCTFlSize; } nodeSize = gBTHeaders[kBTreeCatalog]->nodeSize; nodeBuf = (char *)malloc(nodeSize); node = (BTNodeDescriptor *)nodeBuf; index = *dirIndex % nodeSize; curNode = *dirIndex / nodeSize; // Read the BTree node and get the record for index. ReadExtent(extent, extentSize, kHFSCatalogFileID, curNode * (u_int32_t)nodeSize, nodeSize, nodeBuf, 1); GetBTreeRecord(index, nodeBuf, nodeSize, &testKey, &entry); GetCatalogEntryInfo(entry, flags, time); // Get the file name. if (gIsHFSPlus) { utf_encodestr(((HFSPlusCatalogKey *)testKey)->nodeName.unicode, ((HFSPlusCatalogKey *)testKey)->nodeName.length, gTempStr, 256); } else { strncpy(gTempStr, &((HFSCatalogKey *)testKey)->nodeName[1], ((HFSCatalogKey *)testKey)->nodeName[0]); } *name = gTempStr; // Update dirIndex. index++; if (index == node->numRecords) { index = 0; curNode = node->fLink; } *dirIndex = curNode * nodeSize + index; free(nodeBuf); return 0; }
/** * Reads volume label into str. * Reads boot sector, performs dome checking, loads root dir * and parses volume label. */ void EXFATGetDescription(CICell ih, char *str, long strMaxLen) { struct exfatbootfile *boot; u_int32_t bytesPerSector = 0; u_int32_t sectorsPerCluster = 0; long long rdirOffset = 0; char *buf = NULL; struct direntry_label *dire = NULL; int loopControl = 0; DBG("EXFAT: start %x:%x\n", ih->biosdev, ih->part_no); buf = (char *)malloc(MAX_BLOCK_SIZE); if (buf == 0) { goto error; } bzero(buf,MAX_BLOCK_SIZE ); /* * Read the boot sector, check signatures, and do some minimal * sanity checking. NOTE: the size of the read below is intended * to be a multiple of all supported block sizes, so we don't * have to determine or change the device's block size. */ Seek(ih, 0); Read(ih, (long)buf, MAX_BLOCK_SIZE); // take our boot structure boot = (struct exfatbootfile *) buf; /* * The first three bytes are an Intel x86 jump instruction. I assume it * can be the same forms as DOS FAT: * 0xE9 0x?? 0x?? * 0xEC 0x?? 0x90 * where 0x?? means any byte value is OK. */ if (boot->reserved1[0] != 0xE9 && (boot->reserved1[0] != 0xEB || boot->reserved1[2] != 0x90)) { goto error; } // Check the "EXFAT " signature. if (memcmp((const char *)boot->bf_sysid, EXFAT_BBID, EXFAT_BBIDLEN) != 0) { goto error; } /* * Make sure the bytes per sector and sectors per cluster are * powers of two, and within reasonable ranges. */ bytesPerSector = 1 << boot->bf_bpss; /* Just one byte; no swapping needed */ DBG("EXFAT: bpss=%d, bytesPerSector=%d\n", boot->bf_bpss, bytesPerSector); if (boot->bf_bpss < 9 || boot->bf_bpss > 12) { DBG("EXFAT: invalid bytes per sector shift(%d)\n", boot->bf_bpss); goto error; } sectorsPerCluster = 1 << boot->bf_spcs; /* Just one byte; no swapping needed */ DBG("EXFAT: spcs=%d, sectorsPerCluster=%d\n", boot->bf_spcs, sectorsPerCluster); if (boot->bf_spcs > (25 - boot->bf_bpss)) { DBG("EXFAT: invalid sectors per cluster shift (%d)\n", boot->bf_spcs); goto error; } // calculate root dir cluster offset rdirOffset = boot->bf_cloff + (boot->bf_rdircl - 2) * sectorsPerCluster; DBG("EXFAT: rdirOffset=%d\n", rdirOffset); // load MAX_BLOCK_SIZE bytes of root dir Seek(ih, rdirOffset * bytesPerSector); Read(ih, (long)buf, MAX_BLOCK_SIZE); DBG("buf 0 1 2 = %x %x %x\n", 0x00ff & buf[0], 0x00ff & buf[1], 0x00ff & buf[2]); str[0] = '\0'; /* * Search for volume label dir entry (type 0x83), convert from unicode and put to str. * Set loopControl var to avoid searching outside of buf. */ loopControl = MAX_BLOCK_SIZE / sizeof(struct direntry_label); dire = (struct direntry_label *)buf; while (loopControl && dire->type && dire->type != 0x83) { dire++; loopControl--; } if (dire->type == 0x83 && dire->llen > 0 && dire->llen <= 11) { utf_encodestr( dire->label, (int)dire->llen, (u_int8_t *)str, strMaxLen, OSLittleEndian ); } DBG("EXFAT: label=%s\n", str); free(buf); PAUSE(); return; error: if (buf) free(buf); DBG("EXFAT: error\n"); PAUSE(); return; }