mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
Workaround when HFS and Apple Partition Map where created on a
512 byte/sector device (like a HDD) but are present on a 2048 byte/sector device (like a CD). Solves #1. HFS+ should not be affected (even if wrapped).
This commit is contained in:
@@ -96,34 +96,38 @@ namespace DiscImageChef.PartPlugins
|
|||||||
first_sector = 1;
|
first_sector = 1;
|
||||||
|
|
||||||
// Read first entry
|
// Read first entry
|
||||||
byte[] APMEntry_sector = imagePlugin.ReadSector(first_sector);
|
byte[] APMEntry_sector;
|
||||||
APMEntry.signature = BigEndianBitConverter.ToUInt16(APMEntry_sector, 0x00);
|
bool APMFromHDDOnCD = false;
|
||||||
APMEntry.reserved1 = BigEndianBitConverter.ToUInt16(APMEntry_sector, 0x02);
|
|
||||||
APMEntry.entries = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x04);
|
|
||||||
APMEntry.start = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x08);
|
|
||||||
APMEntry.sectors = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x0C);
|
|
||||||
cString = new byte[32];
|
|
||||||
Array.Copy(APMEntry_sector, 0x10, cString, 0, 32);
|
|
||||||
APMEntry.name = StringHandlers.CToString(cString);
|
|
||||||
cString = new byte[32];
|
|
||||||
Array.Copy(APMEntry_sector, 0x30, cString, 0, 32);
|
|
||||||
APMEntry.type = StringHandlers.CToString(cString);
|
|
||||||
APMEntry.first_data_block = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x50);
|
|
||||||
APMEntry.data_sectors = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x54);
|
|
||||||
APMEntry.status = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x58);
|
|
||||||
APMEntry.first_boot_block = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x5C);
|
|
||||||
APMEntry.boot_size = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x60);
|
|
||||||
APMEntry.load_address = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x64);
|
|
||||||
APMEntry.reserved2 = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x68);
|
|
||||||
APMEntry.entry_point = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x6C);
|
|
||||||
APMEntry.reserved3 = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x70);
|
|
||||||
APMEntry.checksum = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x74);
|
|
||||||
cString = new byte[16];
|
|
||||||
Array.Copy(APMEntry_sector, 0x78, cString, 0, 16);
|
|
||||||
APMEntry.processor = StringHandlers.CToString(cString);
|
|
||||||
|
|
||||||
if (APMEntry.signature != APM_ENTRY && APMEntry.signature != APM_OLDENT)
|
if (sector_size == 2048)
|
||||||
return false;
|
{
|
||||||
|
APMEntry_sector = Read2048SectorAs512(imagePlugin, first_sector);
|
||||||
|
APMEntry = DecodeAPMEntry(APMEntry_sector);
|
||||||
|
|
||||||
|
if (APMEntry.signature == APM_ENTRY || APMEntry.signature == APM_OLDENT)
|
||||||
|
{
|
||||||
|
sector_size = 512;
|
||||||
|
APMFromHDDOnCD = true;
|
||||||
|
if (MainClass.isDebug)
|
||||||
|
Console.WriteLine("DEBUG (Apple Partition Map Plugin): PM sector size is 512 bytes, but device's 2048");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
APMEntry_sector = imagePlugin.ReadSector(first_sector);
|
||||||
|
APMEntry = DecodeAPMEntry(APMEntry_sector);
|
||||||
|
|
||||||
|
if (APMEntry.signature != APM_ENTRY && APMEntry.signature != APM_OLDENT)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
APMEntry_sector = imagePlugin.ReadSector(first_sector);
|
||||||
|
APMEntry = DecodeAPMEntry(APMEntry_sector);
|
||||||
|
|
||||||
|
if (APMEntry.signature != APM_ENTRY && APMEntry.signature != APM_OLDENT)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (APMEntry.entries <= 1)
|
if (APMEntry.entries <= 1)
|
||||||
return false;
|
return false;
|
||||||
@@ -133,31 +137,12 @@ namespace DiscImageChef.PartPlugins
|
|||||||
for (ulong i = 0; i < apm_entries; i++) // For each partition
|
for (ulong i = 0; i < apm_entries; i++) // For each partition
|
||||||
{
|
{
|
||||||
APMEntry = new AppleMapPartitionEntry();
|
APMEntry = new AppleMapPartitionEntry();
|
||||||
APMEntry_sector = imagePlugin.ReadSector(first_sector + i);
|
if(APMFromHDDOnCD)
|
||||||
APMEntry.signature = BigEndianBitConverter.ToUInt16(APMEntry_sector, 0x00);
|
APMEntry_sector = Read2048SectorAs512(imagePlugin, first_sector + i);
|
||||||
APMEntry.reserved1 = BigEndianBitConverter.ToUInt16(APMEntry_sector, 0x02);
|
else
|
||||||
APMEntry.entries = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x04);
|
APMEntry_sector = imagePlugin.ReadSector(first_sector + i);
|
||||||
APMEntry.start = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x08);
|
|
||||||
APMEntry.sectors = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x0C);
|
APMEntry = DecodeAPMEntry(APMEntry_sector);
|
||||||
cString = new byte[32];
|
|
||||||
Array.Copy(APMEntry_sector, 0x10, cString, 0, 32);
|
|
||||||
APMEntry.name = StringHandlers.CToString(cString);
|
|
||||||
cString = new byte[32];
|
|
||||||
Array.Copy(APMEntry_sector, 0x30, cString, 0, 32);
|
|
||||||
APMEntry.type = StringHandlers.CToString(cString);
|
|
||||||
APMEntry.first_data_block = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x50);
|
|
||||||
APMEntry.data_sectors = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x54);
|
|
||||||
APMEntry.status = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x58);
|
|
||||||
APMEntry.first_boot_block = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x5C);
|
|
||||||
APMEntry.boot_size = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x60);
|
|
||||||
APMEntry.load_address = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x64);
|
|
||||||
APMEntry.reserved2 = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x68);
|
|
||||||
APMEntry.entry_point = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x6C);
|
|
||||||
APMEntry.reserved3 = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x70);
|
|
||||||
APMEntry.checksum = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x74);
|
|
||||||
cString = new byte[16];
|
|
||||||
Array.Copy(APMEntry_sector, 0x78, cString, 0, 16);
|
|
||||||
APMEntry.processor = StringHandlers.CToString(cString);
|
|
||||||
|
|
||||||
if (APMEntry.signature == APM_ENTRY || APMEntry.signature == APM_OLDENT) // It should have partition entry signature
|
if (APMEntry.signature == APM_ENTRY || APMEntry.signature == APM_OLDENT) // It should have partition entry signature
|
||||||
{
|
{
|
||||||
@@ -209,6 +194,52 @@ namespace DiscImageChef.PartPlugins
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte[] Read2048SectorAs512(ImagePlugins.ImagePlugin imagePlugin, UInt64 LBA)
|
||||||
|
{
|
||||||
|
UInt64 LBA2k = LBA / 4;
|
||||||
|
int Remainder = (int)(LBA % 4);
|
||||||
|
|
||||||
|
byte[] buffer = imagePlugin.ReadSector(LBA2k);
|
||||||
|
byte[] sector = new byte[512];
|
||||||
|
|
||||||
|
Array.Copy(buffer, Remainder * 512, sector, 0, 512);
|
||||||
|
|
||||||
|
return sector;
|
||||||
|
}
|
||||||
|
|
||||||
|
AppleMapPartitionEntry DecodeAPMEntry(byte[] APMEntry_sector)
|
||||||
|
{
|
||||||
|
AppleMapPartitionEntry APMEntry = new AppleMapPartitionEntry();
|
||||||
|
byte[] cString;
|
||||||
|
|
||||||
|
APMEntry.signature = BigEndianBitConverter.ToUInt16(APMEntry_sector, 0x00);
|
||||||
|
APMEntry.reserved1 = BigEndianBitConverter.ToUInt16(APMEntry_sector, 0x02);
|
||||||
|
APMEntry.entries = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x04);
|
||||||
|
APMEntry.start = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x08);
|
||||||
|
APMEntry.sectors = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x0C);
|
||||||
|
cString = new byte[32];
|
||||||
|
Array.Copy(APMEntry_sector, 0x10, cString, 0, 32);
|
||||||
|
APMEntry.name = StringHandlers.CToString(cString);
|
||||||
|
cString = new byte[32];
|
||||||
|
Array.Copy(APMEntry_sector, 0x30, cString, 0, 32);
|
||||||
|
APMEntry.type = StringHandlers.CToString(cString);
|
||||||
|
APMEntry.first_data_block = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x50);
|
||||||
|
APMEntry.data_sectors = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x54);
|
||||||
|
APMEntry.status = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x58);
|
||||||
|
APMEntry.first_boot_block = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x5C);
|
||||||
|
APMEntry.boot_size = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x60);
|
||||||
|
APMEntry.load_address = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x64);
|
||||||
|
APMEntry.reserved2 = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x68);
|
||||||
|
APMEntry.entry_point = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x6C);
|
||||||
|
APMEntry.reserved3 = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x70);
|
||||||
|
APMEntry.checksum = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x74);
|
||||||
|
cString = new byte[16];
|
||||||
|
Array.Copy(APMEntry_sector, 0x78, cString, 0, 16);
|
||||||
|
APMEntry.processor = StringHandlers.CToString(cString);
|
||||||
|
|
||||||
|
return APMEntry;
|
||||||
|
}
|
||||||
|
|
||||||
public struct AppleMapBootEntry
|
public struct AppleMapBootEntry
|
||||||
{
|
{
|
||||||
// Signature ("ER")
|
// Signature ("ER")
|
||||||
|
|||||||
@@ -63,14 +63,47 @@ namespace DiscImageChef.Plugins
|
|||||||
if ((2 + partitionOffset) >= imagePlugin.GetSectors())
|
if ((2 + partitionOffset) >= imagePlugin.GetSectors())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
byte[] mdb_sector = imagePlugin.ReadSector(2 + partitionOffset);
|
byte[] mdb_sector;
|
||||||
UInt16 drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0);
|
UInt16 drSigWord;
|
||||||
|
|
||||||
if (drSigWord == HFS_MAGIC)
|
if (imagePlugin.GetSectorSize() == 2352 || imagePlugin.GetSectorSize() == 2448 || imagePlugin.GetSectorSize() == 2048)
|
||||||
{
|
{
|
||||||
drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0x7C); // Seek to embedded HFS+ signature
|
mdb_sector = imagePlugin.ReadSector(2 + partitionOffset);
|
||||||
|
drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0);
|
||||||
|
|
||||||
return drSigWord != HFSP_MAGIC;
|
if (drSigWord == HFS_MAGIC)
|
||||||
|
{
|
||||||
|
drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0x7C); // Seek to embedded HFS+ signature
|
||||||
|
|
||||||
|
return drSigWord != HFSP_MAGIC;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mdb_sector = Read2048SectorAs512(imagePlugin, 2 + partitionOffset);
|
||||||
|
drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0);
|
||||||
|
|
||||||
|
if (drSigWord == HFS_MAGIC)
|
||||||
|
{
|
||||||
|
if(MainClass.isDebug)
|
||||||
|
Console.WriteLine("DEBUG (HFS Plugin): HFS sector size is 512 bytes, but device's 2048");
|
||||||
|
|
||||||
|
drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0x7C); // Seek to embedded HFS+ signature
|
||||||
|
|
||||||
|
return drSigWord != HFSP_MAGIC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mdb_sector = imagePlugin.ReadSector(2 + partitionOffset);
|
||||||
|
drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0);
|
||||||
|
|
||||||
|
if (drSigWord == HFS_MAGIC)
|
||||||
|
{
|
||||||
|
drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0x7C); // Seek to embedded HFS+ signature
|
||||||
|
|
||||||
|
return drSigWord != HFSP_MAGIC;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -86,8 +119,46 @@ namespace DiscImageChef.Plugins
|
|||||||
|
|
||||||
byte[] pString;
|
byte[] pString;
|
||||||
|
|
||||||
byte[] bb_sector = imagePlugin.ReadSector(partitionOffset); // BB's first sector
|
byte[] bb_sector;
|
||||||
byte[] mdb_sector = imagePlugin.ReadSector(2 + partitionOffset); // MDB sector
|
byte[] mdb_sector;
|
||||||
|
UInt16 drSigWord;
|
||||||
|
|
||||||
|
bool APMFromHDDOnCD = false;
|
||||||
|
|
||||||
|
if (imagePlugin.GetSectorSize() == 2352 || imagePlugin.GetSectorSize() == 2448 || imagePlugin.GetSectorSize() == 2048)
|
||||||
|
{
|
||||||
|
mdb_sector = imagePlugin.ReadSector(2 + partitionOffset);
|
||||||
|
drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0);
|
||||||
|
|
||||||
|
if (drSigWord == HFS_MAGIC)
|
||||||
|
{
|
||||||
|
bb_sector = imagePlugin.ReadSector(partitionOffset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mdb_sector = Read2048SectorAs512(imagePlugin, 2 + partitionOffset);
|
||||||
|
drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0);
|
||||||
|
|
||||||
|
if (drSigWord == HFS_MAGIC)
|
||||||
|
{
|
||||||
|
bb_sector = Read2048SectorAs512(imagePlugin, partitionOffset);
|
||||||
|
APMFromHDDOnCD = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mdb_sector = imagePlugin.ReadSector(2 + partitionOffset);
|
||||||
|
drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0);
|
||||||
|
|
||||||
|
if (drSigWord == HFS_MAGIC)
|
||||||
|
bb_sector = imagePlugin.ReadSector(partitionOffset);
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
MDB.drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0x000);
|
MDB.drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0x000);
|
||||||
if (MDB.drSigWord != HFS_MAGIC)
|
if (MDB.drSigWord != HFS_MAGIC)
|
||||||
return;
|
return;
|
||||||
@@ -181,6 +252,8 @@ namespace DiscImageChef.Plugins
|
|||||||
|
|
||||||
sb.AppendLine("Apple Hierarchical File System");
|
sb.AppendLine("Apple Hierarchical File System");
|
||||||
sb.AppendLine();
|
sb.AppendLine();
|
||||||
|
if (APMFromHDDOnCD)
|
||||||
|
sb.AppendLine("HFS uses 512 bytes/sector while devices uses 2048 bytes/sector.").AppendLine();
|
||||||
sb.AppendLine("Master Directory Block:");
|
sb.AppendLine("Master Directory Block:");
|
||||||
sb.AppendFormat("Creation date: {0}", DateHandlers.MacToDateTime(MDB.drCrDate)).AppendLine();
|
sb.AppendFormat("Creation date: {0}", DateHandlers.MacToDateTime(MDB.drCrDate)).AppendLine();
|
||||||
sb.AppendFormat("Last modification date: {0}", DateHandlers.MacToDateTime(MDB.drLsMod)).AppendLine();
|
sb.AppendFormat("Last modification date: {0}", DateHandlers.MacToDateTime(MDB.drLsMod)).AppendLine();
|
||||||
@@ -291,6 +364,19 @@ namespace DiscImageChef.Plugins
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte[] Read2048SectorAs512(ImagePlugins.ImagePlugin imagePlugin, UInt64 LBA)
|
||||||
|
{
|
||||||
|
UInt64 LBA2k = LBA / 4;
|
||||||
|
int Remainder = (int)(LBA % 4);
|
||||||
|
|
||||||
|
byte[] buffer = imagePlugin.ReadSector(LBA2k);
|
||||||
|
byte[] sector = new byte[512];
|
||||||
|
|
||||||
|
Array.Copy(buffer, Remainder * 512, sector, 0, 512);
|
||||||
|
|
||||||
|
return sector;
|
||||||
|
}
|
||||||
|
|
||||||
struct HFS_MasterDirectoryBlock // Should be sector 2 in volume
|
struct HFS_MasterDirectoryBlock // Should be sector 2 in volume
|
||||||
{
|
{
|
||||||
public UInt16 drSigWord;
|
public UInt16 drSigWord;
|
||||||
|
|||||||
Reference in New Issue
Block a user