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)