Decode ISO9660 path tables.

This commit is contained in:
2019-07-29 02:45:46 +01:00
parent 8cc11c160e
commit 28ad9dac86
5 changed files with 91 additions and 5 deletions

View File

@@ -75,6 +75,7 @@
<Compile Include="ISO9660\Date.cs" /> <Compile Include="ISO9660\Date.cs" />
<Compile Include="ISO9660\Dir.cs" /> <Compile Include="ISO9660\Dir.cs" />
<Compile Include="ISO9660\File.cs" /> <Compile Include="ISO9660\File.cs" />
<Compile Include="ISO9660\PathTable.cs" />
<Compile Include="ISO9660\Super.cs" /> <Compile Include="ISO9660\Super.cs" />
<Compile Include="ISO9660\Xattr.cs" /> <Compile Include="ISO9660\Xattr.cs" />
<Compile Include="PCFX.cs" /> <Compile Include="PCFX.cs" />

View File

@@ -49,6 +49,7 @@ namespace DiscImageChef.Filesystems.ISO9660
bool joliet; bool joliet;
bool mounted; bool mounted;
Namespace @namespace; Namespace @namespace;
PathTableEntryInternal[] pathTable;
Dictionary<string, DecodedDirectoryEntry> rootDirectoryCache; Dictionary<string, DecodedDirectoryEntry> rootDirectoryCache;
FileSystemInfo statfs; FileSystemInfo statfs;

View File

@@ -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<PathTableEntryInternal> table = new List<PathTableEntryInternal>();
int off = 0;
while(off < data.Length)
{
PathTableEntry entry =
Marshal.ByteArrayToStructureBigEndian<PathTableEntry>(data, off, Marshal.SizeOf<PathTableEntry>());
if(entry.name_len == 0) break;
off += Marshal.SizeOf<PathTableEntry>();
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();
}
}
}

View File

@@ -123,5 +123,14 @@ namespace DiscImageChef.Filesystems.ISO9660
public Point fdLocation; public Point fdLocation;
public uint fdType; public uint fdType;
} }
class PathTableEntryInternal
{
public uint Extent;
public string Name;
public ushort Parent;
public override string ToString() => Name;
}
} }
} }

View File

@@ -160,15 +160,44 @@ namespace DiscImageChef.Filesystems.ISO9660
if(jolietvd != null) decodedJolietVd = DecodeJolietDescriptor(jolietvd.Value); if(jolietvd != null) decodedJolietVd = DecodeJolietDescriptor(jolietvd.Value);
if(this.@namespace != Namespace.Romeo) Encoding = Encoding.ASCII;
string fsFormat; 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) 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"; fsFormat = "CD-i";
// TODO: Implement CD-i // TODO: Implement CD-i
return Errno.NotImplemented; 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 // High Sierra and CD-i do not support Joliet or RRIP
if((highSierra || cdi) && this.@namespace != Namespace.Normal && this.@namespace != Namespace.Vms) if((highSierra || cdi) && this.@namespace != Namespace.Normal && this.@namespace != Namespace.Vms)
@@ -179,7 +208,6 @@ namespace DiscImageChef.Filesystems.ISO9660
uint rootLocation = 0; uint rootLocation = 0;
uint rootSize = 0; uint rootSize = 0;
// TODO: Read CD-i root directory
if(!cdi) if(!cdi)
{ {
rootLocation = highSierra rootLocation = highSierra
@@ -197,6 +225,16 @@ namespace DiscImageChef.Filesystems.ISO9660
if(pvd.Value.root_directory_record.size % pvd.Value.logical_block_size > 0) rootSize++; 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<CdiDirectoryRecord>(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; 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 IP.BIN to debug root directory
// TODO: Add volume descriptors 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) if(this.@namespace != Namespace.Joliet)
rootDirectoryCache = cdi rootDirectoryCache = cdi
? DecodeCdiDirectory(rootDir) ? DecodeCdiDirectory(rootDir)