mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
Implement path table traversal in ISO9660.
This commit is contained in:
4
.idea/.idea.DiscImageChef/.idea/contentModel.xml
generated
4
.idea/.idea.DiscImageChef/.idea/contentModel.xml
generated
@@ -1,11 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ContentModelStore">
|
<component name="ContentModelStore">
|
||||||
<e p="$APPLICATION_CONFIG_DIR$/consoles/db" t="IncludeRecursive" />
|
|
||||||
<e p="$APPLICATION_CONFIG_DIR$/extensions" t="IncludeRecursive" />
|
|
||||||
<e p="$APPLICATION_PLUGINS_DIR$/puppet/lib/stubs" t="IncludeRecursive" />
|
<e p="$APPLICATION_PLUGINS_DIR$/puppet/lib/stubs" t="IncludeRecursive" />
|
||||||
<e p="$USER_HOME$/.Rider2019.1/system/extResources" t="IncludeRecursive" />
|
<e p="$USER_HOME$/.Rider2019.1/system/extResources" t="IncludeRecursive" />
|
||||||
<e p="$USER_HOME$/.Rider2019.1/system/resharper-host/local/Transient/ReSharperHost/v191/SolutionCaches/_DiscImageChef.-1491758497.00" t="ExcludeRecursive" />
|
<e p="$USER_HOME$/.Rider2019.1/system/resharper-host/local/Transient/ReSharperHost/v191/SolutionCaches/_DiscImageChef.-1491758497.00" t="ExcludeRecursive" />
|
||||||
|
<e p="$USER_HOME$/.config/git/ignore" t="IncludeRecursive" />
|
||||||
<e p="$USER_HOME$/.nuget/packages/sqlitepclraw.lib.e_sqlite3.linux/1.1.12/runtimes/linux-x64/native/libe_sqlite3.so" t="Include" />
|
<e p="$USER_HOME$/.nuget/packages/sqlitepclraw.lib.e_sqlite3.linux/1.1.12/runtimes/linux-x64/native/libe_sqlite3.so" t="Include" />
|
||||||
<e p="$PROJECT_DIR$" t="IncludeFlat">
|
<e p="$PROJECT_DIR$" t="IncludeFlat">
|
||||||
<e p=".git/info/exclude" t="IncludeRecursive" />
|
<e p=".git/info/exclude" t="IncludeRecursive" />
|
||||||
@@ -1312,6 +1311,7 @@
|
|||||||
<e p="File.cs" t="Include" />
|
<e p="File.cs" t="Include" />
|
||||||
<e p="ISO9660.cs" t="Include" />
|
<e p="ISO9660.cs" t="Include" />
|
||||||
<e p="Info.cs" t="Include" />
|
<e p="Info.cs" t="Include" />
|
||||||
|
<e p="PathTable.cs" t="Include" />
|
||||||
<e p="Structs" t="Include">
|
<e p="Structs" t="Include">
|
||||||
<e p="Amiga.cs" t="Include" />
|
<e p="Amiga.cs" t="Include" />
|
||||||
<e p="Apple.cs" t="Include" />
|
<e p="Apple.cs" t="Include" />
|
||||||
|
|||||||
@@ -75,6 +75,14 @@ namespace DiscImageChef.Filesystems.ISO9660
|
|||||||
? DecodeHighSierraDirectory(directoryBuffer)
|
? DecodeHighSierraDirectory(directoryBuffer)
|
||||||
: DecodeIsoDirectory(directoryBuffer);
|
: DecodeIsoDirectory(directoryBuffer);
|
||||||
|
|
||||||
|
if(usePathTable)
|
||||||
|
foreach(DecodedDirectoryEntry subDirectory in cdi
|
||||||
|
? GetSubdirsFromCdiPathTable(currentPath)
|
||||||
|
: highSierra
|
||||||
|
? GetSubdirsFromHighSierraPathTable(currentPath)
|
||||||
|
: GetSubdirsFromIsoPathTable(currentPath))
|
||||||
|
currentDirectory[subDirectory.Filename] = subDirectory;
|
||||||
|
|
||||||
directoryCache.Add(currentPath, currentDirectory);
|
directoryCache.Add(currentPath, currentDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,6 +150,12 @@ namespace DiscImageChef.Filesystems.ISO9660
|
|||||||
Timestamp = DecodeHighSierraDateTime(record.date)
|
Timestamp = DecodeHighSierraDateTime(record.date)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if(entry.Flags.HasFlag(FileFlags.Directory) && usePathTable)
|
||||||
|
{
|
||||||
|
entryOff += record.length;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if(!entries.ContainsKey(entry.Filename)) entries.Add(entry.Filename, entry);
|
if(!entries.ContainsKey(entry.Filename)) entries.Add(entry.Filename, entry);
|
||||||
|
|
||||||
entryOff += record.length;
|
entryOff += record.length;
|
||||||
@@ -187,6 +201,12 @@ namespace DiscImageChef.Filesystems.ISO9660
|
|||||||
Timestamp = DecodeIsoDateTime(record.date)
|
Timestamp = DecodeIsoDateTime(record.date)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if(entry.Flags.HasFlag(FileFlags.Directory) && usePathTable)
|
||||||
|
{
|
||||||
|
entryOff += record.length;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: XA
|
// TODO: XA
|
||||||
int systemAreaStart = entryOff + record.name_len + Marshal.SizeOf<DirectoryRecord>();
|
int systemAreaStart = entryOff + record.name_len + Marshal.SizeOf<DirectoryRecord>();
|
||||||
int systemAreaLength = record.length - record.name_len - Marshal.SizeOf<DirectoryRecord>();
|
int systemAreaLength = record.length - record.name_len - Marshal.SizeOf<DirectoryRecord>();
|
||||||
@@ -700,5 +720,117 @@ namespace DiscImageChef.Filesystems.ISO9660
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PathTableEntryInternal[] GetPathTableEntries(string path)
|
||||||
|
{
|
||||||
|
IEnumerable<PathTableEntryInternal> tableEntries = new PathTableEntryInternal[0];
|
||||||
|
List<PathTableEntryInternal> pathTableList = new List<PathTableEntryInternal>(pathTable);
|
||||||
|
|
||||||
|
if(path == "" || path == "/") tableEntries = pathTable.Where(p => p.Parent == 1 && p != pathTable[0]);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string cutPath = path.StartsWith("/", StringComparison.Ordinal)
|
||||||
|
? path.Substring(1).ToLower(CultureInfo.CurrentUICulture)
|
||||||
|
: path.ToLower(CultureInfo.CurrentUICulture);
|
||||||
|
|
||||||
|
string[] pieces = cutPath.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
|
||||||
|
int currentParent = 1;
|
||||||
|
int currentPiece = 0;
|
||||||
|
|
||||||
|
while(currentPiece < pieces.Length)
|
||||||
|
{
|
||||||
|
PathTableEntryInternal currentEntry = pathTable.FirstOrDefault(p => p.Parent == currentParent &&
|
||||||
|
p.Name.ToLower(CultureInfo
|
||||||
|
.CurrentUICulture) ==
|
||||||
|
pieces[currentPiece]);
|
||||||
|
|
||||||
|
if(currentEntry is null) break;
|
||||||
|
|
||||||
|
currentPiece++;
|
||||||
|
currentParent = pathTableList.IndexOf(currentEntry) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tableEntries = pathTable.Where(p => p.Parent == currentParent);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tableEntries.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
DecodedDirectoryEntry[] GetSubdirsFromCdiPathTable(string path) => throw new NotImplementedException();
|
||||||
|
|
||||||
|
DecodedDirectoryEntry[] GetSubdirsFromIsoPathTable(string path)
|
||||||
|
{
|
||||||
|
PathTableEntryInternal[] tableEntries = GetPathTableEntries(path);
|
||||||
|
List<DecodedDirectoryEntry> entries = new List<DecodedDirectoryEntry>();
|
||||||
|
foreach(PathTableEntryInternal tEntry in tableEntries)
|
||||||
|
{
|
||||||
|
byte[] sector = image.ReadSector(tEntry.Extent);
|
||||||
|
DirectoryRecord record =
|
||||||
|
Marshal.ByteArrayToStructureLittleEndian<DirectoryRecord>(sector, 0,
|
||||||
|
Marshal.SizeOf<DirectoryRecord>());
|
||||||
|
|
||||||
|
if(record.length == 0) break;
|
||||||
|
|
||||||
|
DecodedDirectoryEntry entry = new DecodedDirectoryEntry
|
||||||
|
{
|
||||||
|
Extent = record.size == 0 ? 0 : record.extent,
|
||||||
|
Size = record.size,
|
||||||
|
Flags = record.flags,
|
||||||
|
Filename = tEntry.Name,
|
||||||
|
FileUnitSize = record.file_unit_size,
|
||||||
|
Interleave = record.interleave,
|
||||||
|
VolumeSequenceNumber = record.volume_sequence_number,
|
||||||
|
Timestamp = DecodeIsoDateTime(record.date)
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: XA
|
||||||
|
int systemAreaStart = record.name_len + Marshal.SizeOf<DirectoryRecord>();
|
||||||
|
int systemAreaLength = record.length - record.name_len - Marshal.SizeOf<DirectoryRecord>();
|
||||||
|
|
||||||
|
if(systemAreaStart % 2 != 0)
|
||||||
|
{
|
||||||
|
systemAreaStart++;
|
||||||
|
systemAreaLength--;
|
||||||
|
}
|
||||||
|
|
||||||
|
DecodeSystemArea(sector, systemAreaStart, systemAreaStart + systemAreaLength, ref entry, out _);
|
||||||
|
|
||||||
|
entries.Add(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
return entries.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
DecodedDirectoryEntry[] GetSubdirsFromHighSierraPathTable(string path)
|
||||||
|
{
|
||||||
|
PathTableEntryInternal[] tableEntries = GetPathTableEntries(path);
|
||||||
|
List<DecodedDirectoryEntry> entries = new List<DecodedDirectoryEntry>();
|
||||||
|
foreach(PathTableEntryInternal tEntry in tableEntries)
|
||||||
|
{
|
||||||
|
byte[] sector = image.ReadSector(tEntry.Extent);
|
||||||
|
HighSierraDirectoryRecord record =
|
||||||
|
Marshal.ByteArrayToStructureLittleEndian<HighSierraDirectoryRecord>(sector, 0,
|
||||||
|
Marshal
|
||||||
|
.SizeOf<
|
||||||
|
HighSierraDirectoryRecord
|
||||||
|
>());
|
||||||
|
|
||||||
|
DecodedDirectoryEntry entry = new DecodedDirectoryEntry
|
||||||
|
{
|
||||||
|
Extent = record.size == 0 ? 0 : record.extent,
|
||||||
|
Size = record.size,
|
||||||
|
Flags = record.flags,
|
||||||
|
Filename = tEntry.Name,
|
||||||
|
Interleave = record.interleave,
|
||||||
|
VolumeSequenceNumber = record.volume_sequence_number,
|
||||||
|
Timestamp = DecodeHighSierraDateTime(record.date)
|
||||||
|
};
|
||||||
|
|
||||||
|
entries.Add(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
return entries.ToArray();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -52,6 +52,7 @@ namespace DiscImageChef.Filesystems.ISO9660
|
|||||||
PathTableEntryInternal[] pathTable;
|
PathTableEntryInternal[] pathTable;
|
||||||
Dictionary<string, DecodedDirectoryEntry> rootDirectoryCache;
|
Dictionary<string, DecodedDirectoryEntry> rootDirectoryCache;
|
||||||
FileSystemInfo statfs;
|
FileSystemInfo statfs;
|
||||||
|
bool usePathTable;
|
||||||
|
|
||||||
public FileSystemType XmlFsType { get; private set; }
|
public FileSystemType XmlFsType { get; private set; }
|
||||||
public Encoding Encoding { get; private set; }
|
public Encoding Encoding { get; private set; }
|
||||||
@@ -60,7 +61,10 @@ namespace DiscImageChef.Filesystems.ISO9660
|
|||||||
public string Author => "Natalia Portillo";
|
public string Author => "Natalia Portillo";
|
||||||
|
|
||||||
public IEnumerable<(string name, Type type, string description)> SupportedOptions =>
|
public IEnumerable<(string name, Type type, string description)> SupportedOptions =>
|
||||||
new (string name, Type type, string description)[] { };
|
new (string name, Type type, string description)[]
|
||||||
|
{
|
||||||
|
("use_path_table", typeof(bool), "Use path table for directory traversal")
|
||||||
|
};
|
||||||
|
|
||||||
public Dictionary<string, string> Namespaces =>
|
public Dictionary<string, string> Namespaces =>
|
||||||
new Dictionary<string, string>
|
new Dictionary<string, string>
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ namespace DiscImageChef.Filesystems.ISO9660
|
|||||||
|
|
||||||
if(options == null) options = GetDefaultOptions();
|
if(options == null) options = GetDefaultOptions();
|
||||||
if(options.TryGetValue("debug", out string debugString)) bool.TryParse(debugString, out debug);
|
if(options.TryGetValue("debug", out string debugString)) bool.TryParse(debugString, out debug);
|
||||||
|
if(options.TryGetValue("use_path_table", out string usePathTableString))
|
||||||
|
bool.TryParse(usePathTableString, out usePathTable);
|
||||||
|
|
||||||
// Default namespace
|
// Default namespace
|
||||||
if(@namespace is null) @namespace = "joliet";
|
if(@namespace is null) @namespace = "joliet";
|
||||||
@@ -234,6 +236,8 @@ namespace DiscImageChef.Filesystems.ISO9660
|
|||||||
Marshal.ByteArrayToStructureBigEndian<CdiDirectoryRecord>(firstRootSector);
|
Marshal.ByteArrayToStructureBigEndian<CdiDirectoryRecord>(firstRootSector);
|
||||||
rootSize = rootEntry.size / fsvd.Value.logical_block_size;
|
rootSize = rootEntry.size / fsvd.Value.logical_block_size;
|
||||||
if(rootEntry.size % fsvd.Value.logical_block_size > 0) rootSize++;
|
if(rootEntry.size % fsvd.Value.logical_block_size > 0) rootSize++;
|
||||||
|
|
||||||
|
usePathTable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(rootLocation + rootSize >= imagePlugin.Info.Sectors) return Errno.InvalidArgument;
|
if(rootLocation + rootSize >= imagePlugin.Info.Sectors) return Errno.InvalidArgument;
|
||||||
@@ -248,6 +252,8 @@ 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.Joliet || this.@namespace == Namespace.Rrip) usePathTable = false;
|
||||||
|
|
||||||
if(this.@namespace != Namespace.Joliet)
|
if(this.@namespace != Namespace.Joliet)
|
||||||
rootDirectoryCache = cdi
|
rootDirectoryCache = cdi
|
||||||
? DecodeCdiDirectory(rootDir)
|
? DecodeCdiDirectory(rootDir)
|
||||||
@@ -382,7 +388,16 @@ namespace DiscImageChef.Filesystems.ISO9660
|
|||||||
|
|
||||||
directoryCache = new Dictionary<string, Dictionary<string, DecodedDirectoryEntry>>();
|
directoryCache = new Dictionary<string, Dictionary<string, DecodedDirectoryEntry>>();
|
||||||
image = imagePlugin;
|
image = imagePlugin;
|
||||||
mounted = true;
|
|
||||||
|
if(usePathTable)
|
||||||
|
foreach(DecodedDirectoryEntry subDirectory in cdi
|
||||||
|
? GetSubdirsFromCdiPathTable("")
|
||||||
|
: highSierra
|
||||||
|
? GetSubdirsFromHighSierraPathTable("")
|
||||||
|
: GetSubdirsFromIsoPathTable(""))
|
||||||
|
rootDirectoryCache[subDirectory.Filename] = subDirectory;
|
||||||
|
|
||||||
|
mounted = true;
|
||||||
|
|
||||||
return Errno.NoError;
|
return Errno.NoError;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user