From 28ad9dac86ac3c2dda199d56e045f9589d79fbcf Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Mon, 29 Jul 2019 02:45:46 +0100 Subject: [PATCH] Decode ISO9660 path tables. --- .../DiscImageChef.Filesystems.csproj | 1 + DiscImageChef.Filesystems/ISO9660/ISO9660.cs | 1 + .../ISO9660/PathTable.cs | 39 ++++++++++++++++ .../ISO9660/Structs/Internal.cs | 9 ++++ DiscImageChef.Filesystems/ISO9660/Super.cs | 46 +++++++++++++++++-- 5 files changed, 91 insertions(+), 5 deletions(-) create mode 100644 DiscImageChef.Filesystems/ISO9660/PathTable.cs diff --git a/DiscImageChef.Filesystems/DiscImageChef.Filesystems.csproj b/DiscImageChef.Filesystems/DiscImageChef.Filesystems.csproj index 5a7f27db6..f1bc91d6a 100644 --- a/DiscImageChef.Filesystems/DiscImageChef.Filesystems.csproj +++ b/DiscImageChef.Filesystems/DiscImageChef.Filesystems.csproj @@ -75,6 +75,7 @@ + diff --git a/DiscImageChef.Filesystems/ISO9660/ISO9660.cs b/DiscImageChef.Filesystems/ISO9660/ISO9660.cs index 45d6cd59a..a6c081a89 100644 --- a/DiscImageChef.Filesystems/ISO9660/ISO9660.cs +++ b/DiscImageChef.Filesystems/ISO9660/ISO9660.cs @@ -49,6 +49,7 @@ namespace DiscImageChef.Filesystems.ISO9660 bool joliet; bool mounted; Namespace @namespace; + PathTableEntryInternal[] pathTable; Dictionary rootDirectoryCache; FileSystemInfo statfs; diff --git a/DiscImageChef.Filesystems/ISO9660/PathTable.cs b/DiscImageChef.Filesystems/ISO9660/PathTable.cs new file mode 100644 index 000000000..143f55d9d --- /dev/null +++ b/DiscImageChef.Filesystems/ISO9660/PathTable.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; +using DiscImageChef.Helpers; + +namespace DiscImageChef.Filesystems.ISO9660 +{ + public partial class ISO9660 + { + PathTableEntryInternal[] DecodePathTable(byte[] data) + { + if(data is null) return null; + + List table = new List(); + + int off = 0; + while(off < data.Length) + { + PathTableEntry entry = + Marshal.ByteArrayToStructureBigEndian(data, off, Marshal.SizeOf()); + + if(entry.name_len == 0) break; + + off += Marshal.SizeOf(); + + string name = Encoding.GetString(data, off, entry.name_len); + + table.Add(new PathTableEntryInternal + { + Extent = entry.start_lbn, Name = name, Parent = entry.parent_dirno + }); + + off += entry.name_len; + + if(entry.name_len % 2 != 0) off++; + } + + return table.ToArray(); + } + } +} \ No newline at end of file diff --git a/DiscImageChef.Filesystems/ISO9660/Structs/Internal.cs b/DiscImageChef.Filesystems/ISO9660/Structs/Internal.cs index 5181e9c06..48cd64875 100644 --- a/DiscImageChef.Filesystems/ISO9660/Structs/Internal.cs +++ b/DiscImageChef.Filesystems/ISO9660/Structs/Internal.cs @@ -123,5 +123,14 @@ namespace DiscImageChef.Filesystems.ISO9660 public Point fdLocation; public uint fdType; } + + class PathTableEntryInternal + { + public uint Extent; + public string Name; + public ushort Parent; + + public override string ToString() => Name; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/ISO9660/Super.cs b/DiscImageChef.Filesystems/ISO9660/Super.cs index 6b8e08005..64f046520 100644 --- a/DiscImageChef.Filesystems/ISO9660/Super.cs +++ b/DiscImageChef.Filesystems/ISO9660/Super.cs @@ -160,15 +160,44 @@ namespace DiscImageChef.Filesystems.ISO9660 if(jolietvd != null) decodedJolietVd = DecodeJolietDescriptor(jolietvd.Value); + if(this.@namespace != Namespace.Romeo) Encoding = Encoding.ASCII; + string fsFormat; - if(highSierra) fsFormat = "High Sierra Format"; + byte[] pathTableData; + uint pathTableSizeInSectors = 0; + 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); + + fsFormat = "High Sierra Format"; + } else if(cdi) { + 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); + fsFormat = "CD-i"; // TODO: Implement CD-i return Errno.NotImplemented; } - else fsFormat = "ISO9660"; + else + { + 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); + + fsFormat = "ISO9660"; + } + + pathTable = DecodePathTable(pathTableData); // High Sierra and CD-i do not support Joliet or RRIP if((highSierra || cdi) && this.@namespace != Namespace.Normal && this.@namespace != Namespace.Vms) @@ -179,7 +208,6 @@ namespace DiscImageChef.Filesystems.ISO9660 uint rootLocation = 0; uint rootSize = 0; - // TODO: Read CD-i root directory if(!cdi) { rootLocation = highSierra @@ -197,6 +225,16 @@ namespace DiscImageChef.Filesystems.ISO9660 if(pvd.Value.root_directory_record.size % pvd.Value.logical_block_size > 0) rootSize++; } } + else + { + rootLocation = pathTable[0].Extent; + + byte[] firstRootSector = imagePlugin.ReadSector(rootLocation); + CdiDirectoryRecord rootEntry = + Marshal.ByteArrayToStructureBigEndian(firstRootSector); + rootSize = rootEntry.size / fsvd.Value.logical_block_size; + if(rootEntry.size % fsvd.Value.logical_block_size > 0) rootSize++; + } if(rootLocation + rootSize >= imagePlugin.Info.Sectors) return Errno.InvalidArgument; @@ -210,8 +248,6 @@ namespace DiscImageChef.Filesystems.ISO9660 // TODO: Add IP.BIN to debug root directory // TODO: Add volume descriptors to debug root directory - if(this.@namespace != Namespace.Romeo) Encoding = Encoding.ASCII; - if(this.@namespace != Namespace.Joliet) rootDirectoryCache = cdi ? DecodeCdiDirectory(rootDir)