From 25f69a99e51e0bc2c1925591957db69d93d9e803 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Wed, 31 Jul 2019 17:02:50 +0100 Subject: [PATCH] Add support for different mode sectors in ISO9660. --- .../.idea/contentModel.xml | 1 + .../DiscImageChef.Filesystems.csproj | 1 + .../ISO9660/Consts/Internal.cs | 3 +- DiscImageChef.Filesystems/ISO9660/Dir.cs | 14 ++-- DiscImageChef.Filesystems/ISO9660/File.cs | 4 +- DiscImageChef.Filesystems/ISO9660/Mode2.cs | 81 +++++++++++++++++++ DiscImageChef.Filesystems/ISO9660/Super.cs | 19 +++-- DiscImageChef.Filesystems/ISO9660/Xattr.cs | 6 +- 8 files changed, 106 insertions(+), 23 deletions(-) create mode 100644 DiscImageChef.Filesystems/ISO9660/Mode2.cs diff --git a/.idea/.idea.DiscImageChef/.idea/contentModel.xml b/.idea/.idea.DiscImageChef/.idea/contentModel.xml index 3b6db496f..65dba0460 100644 --- a/.idea/.idea.DiscImageChef/.idea/contentModel.xml +++ b/.idea/.idea.DiscImageChef/.idea/contentModel.xml @@ -1311,6 +1311,7 @@ + diff --git a/DiscImageChef.Filesystems/DiscImageChef.Filesystems.csproj b/DiscImageChef.Filesystems/DiscImageChef.Filesystems.csproj index f1bc91d6a..6cc354ec2 100644 --- a/DiscImageChef.Filesystems/DiscImageChef.Filesystems.csproj +++ b/DiscImageChef.Filesystems/DiscImageChef.Filesystems.csproj @@ -75,6 +75,7 @@ + diff --git a/DiscImageChef.Filesystems/ISO9660/Consts/Internal.cs b/DiscImageChef.Filesystems/ISO9660/Consts/Internal.cs index 41b41f5b4..359b2314d 100644 --- a/DiscImageChef.Filesystems/ISO9660/Consts/Internal.cs +++ b/DiscImageChef.Filesystems/ISO9660/Consts/Internal.cs @@ -36,7 +36,8 @@ namespace DiscImageChef.Filesystems.ISO9660 { public partial class ISO9660 { - static readonly int DirectoryRecordSize = Marshal.SizeOf(); + const byte MODE2_FORM2 = 0x20; + static readonly int DirectoryRecordSize = Marshal.SizeOf(); enum Namespace { diff --git a/DiscImageChef.Filesystems/ISO9660/Dir.cs b/DiscImageChef.Filesystems/ISO9660/Dir.cs index d6e9e1336..7711bce2c 100644 --- a/DiscImageChef.Filesystems/ISO9660/Dir.cs +++ b/DiscImageChef.Filesystems/ISO9660/Dir.cs @@ -67,7 +67,7 @@ namespace DiscImageChef.Filesystems.ISO9660 uint dirSizeInSectors = entry.Value.Size / 2048; if(entry.Value.Size % 2048 > 0) dirSizeInSectors++; - byte[] directoryBuffer = image.ReadSectors(currentExtent, dirSizeInSectors); + byte[] directoryBuffer = ReadSectors(currentExtent, dirSizeInSectors); // TODO: Decode Joliet currentDirectory = cdi @@ -349,7 +349,7 @@ namespace DiscImageChef.Filesystems.ISO9660 uint transTblSectors = transTblEntry.Value.Size / 2048; if(transTblEntry.Value.Size % 2048 > 0) transTblSectors++; - byte[] transTbl = image.ReadSectors(transTblEntry.Value.Extent, transTblSectors); + byte[] transTbl = ReadSectors(transTblEntry.Value.Extent, transTblSectors); MemoryStream mr = new MemoryStream(transTbl, 0, (int)transTblEntry.Value.Size, false); StreamReader sr = new StreamReader(mr, Encoding); @@ -719,7 +719,7 @@ namespace DiscImageChef.Filesystems.ISO9660 Marshal.ByteArrayToStructureLittleEndian(data, systemAreaOff, Marshal.SizeOf()); - byte[] childSector = image.ReadSector(cl.child_dir_lba); + byte[] childSector = ReadSectors(cl.child_dir_lba, 1); DirectoryRecord childRecord = Marshal.ByteArrayToStructureLittleEndian(childSector); @@ -829,7 +829,7 @@ namespace DiscImageChef.Filesystems.ISO9660 uint caLenInSectors = ca.ca_length / 2048; if((ca.ca_length + caOff) % 2048 > 0) caLenInSectors++; - byte[] caData = image.ReadSectors(ca.block + caOffSector, caLenInSectors); + byte[] caData = ReadSectors(ca.block + caOffSector, caLenInSectors); DecodeSystemArea(caData, (int)caOff, (int)(caOff + ca.ca_length), ref entry, out hasResourceFork); @@ -922,7 +922,7 @@ namespace DiscImageChef.Filesystems.ISO9660 List entries = new List(); foreach(PathTableEntryInternal tEntry in tableEntries) { - byte[] sector = image.ReadSector(tEntry.Extent); + byte[] sector = ReadSectors(tEntry.Extent, 1); CdiDirectoryRecord record = Marshal.ByteArrayToStructureBigEndian(sector, tEntry.XattrLength, Marshal.SizeOf()); @@ -962,7 +962,7 @@ namespace DiscImageChef.Filesystems.ISO9660 List entries = new List(); foreach(PathTableEntryInternal tEntry in tableEntries) { - byte[] sector = image.ReadSector(tEntry.Extent); + byte[] sector = ReadSectors(tEntry.Extent, 1); DirectoryRecord record = Marshal.ByteArrayToStructureLittleEndian(sector, tEntry.XattrLength, Marshal.SizeOf()); @@ -1006,7 +1006,7 @@ namespace DiscImageChef.Filesystems.ISO9660 List entries = new List(); foreach(PathTableEntryInternal tEntry in tableEntries) { - byte[] sector = image.ReadSector(tEntry.Extent); + byte[] sector = ReadSectors(tEntry.Extent, 1); HighSierraDirectoryRecord record = Marshal.ByteArrayToStructureLittleEndian(sector, tEntry.XattrLength, Marshal diff --git a/DiscImageChef.Filesystems/ISO9660/File.cs b/DiscImageChef.Filesystems/ISO9660/File.cs index 21b2e9db3..9b154ec9e 100644 --- a/DiscImageChef.Filesystems/ISO9660/File.cs +++ b/DiscImageChef.Filesystems/ISO9660/File.cs @@ -71,7 +71,7 @@ namespace DiscImageChef.Filesystems.ISO9660 MemoryStream ms = new MemoryStream(); - byte[] buffer = image.ReadSectors((ulong)(entry.Extent + firstSector), (uint)sizeInSectors); + byte[] buffer = ReadSectors((ulong)(entry.Extent + firstSector), (uint)sizeInSectors); buf = new byte[size]; Array.Copy(buffer, offsetInSector, buf, 0, size); @@ -206,7 +206,7 @@ namespace DiscImageChef.Filesystems.ISO9660 uint eaSizeInSectors = (uint)(entry.XattrLength / 2048); if(entry.XattrLength % 2048 > 0) eaSizeInSectors++; - byte[] ea = image.ReadSectors(entry.Extent, eaSizeInSectors); + byte[] ea = ReadSectors(entry.Extent, eaSizeInSectors); ExtendedAttributeRecord ear = Marshal.ByteArrayToStructureLittleEndian(ea); diff --git a/DiscImageChef.Filesystems/ISO9660/Mode2.cs b/DiscImageChef.Filesystems/ISO9660/Mode2.cs new file mode 100644 index 000000000..a68999715 --- /dev/null +++ b/DiscImageChef.Filesystems/ISO9660/Mode2.cs @@ -0,0 +1,81 @@ +using System.IO; + +namespace DiscImageChef.Filesystems.ISO9660 +{ + public partial class ISO9660 + { + byte[] ReadSectors(ulong start, uint count) + { + MemoryStream ms = new MemoryStream(); + + for(ulong sector = start; sector < start + count; sector++) + { + byte[] data = image.ReadSector(sector); + + switch(data.Length) + { + case 2048: + // Mode 1 sector + ms.Write(data, 0, 2048); + break; + case 2352: + // Not a data sector + if(data[0] != 0 || data[1] != 0xFF || data[2] != 0xFF || data[3] != 0xFF || + data[4] != 0xFF || + data[5] != 0xFF || data[6] != 0xFF || data[7] != 0xFF || data[8] != 0xFF || + data[9] != 0xFF || data[10] != 0xFF || data[11] != 0x00) + { + ms.Write(data, 0, 2352); + break; + } + + switch(data[15]) + { + // Mode 0 sector + case 0: + ms.Write(new byte[2048], 0, 2048); + break; + // Mode 1 sector + case 1: + ms.Write(data, 16, 2048); + break; + case 2: + // Mode 2 form 1 sector + if((data[16] & MODE2_FORM2) != 0) + { + ms.Write(data, 24, 2048); + break; + } + + // Mode 2 form 2 sector + ms.Write(data, 24, 2324); + break; + // Unknown, audio? + default: + ms.Write(data, 0, 2352); + break; + } + + break; + case 2336: + // Mode 2 form 1 sector + if((data[16] & MODE2_FORM2) == 0) + { + ms.Write(data, 8, 2048); + break; + } + + // Mode 2 form 2 sector + ms.Write(data, 8, 2324); + break; + // Should not happen, but, just in case + default: + ms.Write(data, 0, data.Length); + break; + } + } + + return ms.ToArray(); + } + } +} \ No newline at end of file diff --git a/DiscImageChef.Filesystems/ISO9660/Super.cs b/DiscImageChef.Filesystems/ISO9660/Super.cs index 7ac914fd2..c4c97d81e 100644 --- a/DiscImageChef.Filesystems/ISO9660/Super.cs +++ b/DiscImageChef.Filesystems/ISO9660/Super.cs @@ -204,13 +204,14 @@ namespace DiscImageChef.Filesystems.ISO9660 uint pathTableMsbLocation; uint pathTableLsbLocation; + image = imagePlugin; + if(highSierra) { pathTableSizeInSectors = hsvd.Value.path_table_size / 2048; if(hsvd.Value.path_table_size % 2048 > 0) pathTableSizeInSectors++; - pathTableData = - imagePlugin.ReadSectors(Swapping.Swap(hsvd.Value.mandatory_path_table_msb), pathTableSizeInSectors); + pathTableData = ReadSectors(Swapping.Swap(hsvd.Value.mandatory_path_table_msb), pathTableSizeInSectors); fsFormat = "High Sierra Format"; @@ -222,7 +223,7 @@ namespace DiscImageChef.Filesystems.ISO9660 pathTableSizeInSectors = fsvd.Value.path_table_size / 2048; if(fsvd.Value.path_table_size % 2048 > 0) pathTableSizeInSectors++; - pathTableData = imagePlugin.ReadSectors(fsvd.Value.path_table_addr, pathTableSizeInSectors); + pathTableData = ReadSectors(fsvd.Value.path_table_addr, pathTableSizeInSectors); fsFormat = "CD-i"; @@ -239,8 +240,7 @@ namespace DiscImageChef.Filesystems.ISO9660 pathTableSizeInSectors = pvd.Value.path_table_size / 2048; if(pvd.Value.path_table_size % 2048 > 0) pathTableSizeInSectors++; - pathTableData = - imagePlugin.ReadSectors(Swapping.Swap(pvd.Value.type_m_path_table), pathTableSizeInSectors); + pathTableData = ReadSectors(Swapping.Swap(pvd.Value.type_m_path_table), pathTableSizeInSectors); fsFormat = "ISO9660"; @@ -285,7 +285,7 @@ namespace DiscImageChef.Filesystems.ISO9660 { rootLocation = pathTable[0].Extent; - byte[] firstRootSector = imagePlugin.ReadSector(rootLocation); + byte[] firstRootSector = ReadSectors(rootLocation, 1); CdiDirectoryRecord rootEntry = Marshal.ByteArrayToStructureBigEndian(firstRootSector); rootSize = rootEntry.size / fsvd.Value.logical_block_size; @@ -297,9 +297,9 @@ namespace DiscImageChef.Filesystems.ISO9660 if(rootLocation + rootSize >= imagePlugin.Info.Sectors) return Errno.InvalidArgument; - byte[] rootDir = imagePlugin.ReadSectors(rootLocation, rootSize); + byte[] rootDir = ReadSectors(rootLocation, rootSize); - byte[] ipbinSector = imagePlugin.ReadSector(partition.Start); + byte[] ipbinSector = ReadSectors(partition.Start, 1); CD.IPBin? segaCd = CD.DecodeIPBin(ipbinSector); Saturn.IPBin? saturn = Saturn.DecodeIPBin(ipbinSector); Dreamcast.IPBin? dreamcast = Dreamcast.DecodeIPBin(ipbinSector); @@ -446,7 +446,7 @@ namespace DiscImageChef.Filesystems.ISO9660 joliet = true; - rootDir = imagePlugin.ReadSectors(rootLocation, rootSize); + rootDir = ReadSectors(rootLocation, rootSize); rootDirectoryCache = DecodeIsoDirectory(rootDir, rootXattrLength); @@ -558,7 +558,6 @@ namespace DiscImageChef.Filesystems.ISO9660 }; directoryCache = new Dictionary>(); - image = imagePlugin; if(usePathTable) foreach(DecodedDirectoryEntry subDirectory in cdi diff --git a/DiscImageChef.Filesystems/ISO9660/Xattr.cs b/DiscImageChef.Filesystems/ISO9660/Xattr.cs index a20489695..1f33ef5bc 100644 --- a/DiscImageChef.Filesystems/ISO9660/Xattr.cs +++ b/DiscImageChef.Filesystems/ISO9660/Xattr.cs @@ -45,7 +45,7 @@ namespace DiscImageChef.Filesystems.ISO9660 uint eaSizeInSectors = (uint)(entry.XattrLength / 2048); if(entry.XattrLength % 2048 > 0) eaSizeInSectors++; - byte[] ea = image.ReadSectors(entry.Extent, eaSizeInSectors); + byte[] ea = ReadSectors(entry.Extent, eaSizeInSectors); buf = new byte[entry.AssociatedFile.Size]; Array.Copy(ea, 0, buf, 0, buf.LongLength); @@ -66,7 +66,7 @@ namespace DiscImageChef.Filesystems.ISO9660 uint associatedFileSize = entry.AssociatedFile.Size / 2048; if(entry.AssociatedFile.Size % 2048 > 0) associatedFileSize++; - byte[] associatedFile = image.ReadSectors(entry.AssociatedFile.Extent, associatedFileSize); + byte[] associatedFile = ReadSectors(entry.AssociatedFile.Extent, associatedFileSize); buf = new byte[entry.AssociatedFile.Size]; Array.Copy(associatedFile, 0, buf, 0, buf.LongLength); @@ -100,7 +100,7 @@ namespace DiscImageChef.Filesystems.ISO9660 uint rsrcSizeInSectors = entry.ResourceFork.Size / 2048; if(entry.ResourceFork.Size % 2048 > 0) rsrcSizeInSectors++; - byte[] rsrc = image.ReadSectors(entry.ResourceFork.Extent, rsrcSizeInSectors); + byte[] rsrc = ReadSectors(entry.ResourceFork.Extent, rsrcSizeInSectors); buf = new byte[entry.ResourceFork.Size]; Array.Copy(rsrc, 0, buf, 0, buf.LongLength);