mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
Fix reading ISO9660, CD-i and HSF directories that span several sectors.
This commit is contained in:
@@ -94,35 +94,17 @@ namespace DiscImageChef.Filesystems.ISO9660
|
||||
|
||||
if(entry.Value.Extents.Count == 0) return Errno.InvalidArgument;
|
||||
|
||||
byte[] directoryBuffer;
|
||||
if(entry.Value.Extents.Count == 1)
|
||||
{
|
||||
uint dirSizeInSectors = entry.Value.Extents[0].size / 2048;
|
||||
if(entry.Value.Size % 2048 > 0) dirSizeInSectors++;
|
||||
directoryBuffer = ReadSectors(entry.Value.Extents[0].extent, dirSizeInSectors);
|
||||
}
|
||||
else
|
||||
{
|
||||
MemoryStream ms = new MemoryStream();
|
||||
|
||||
foreach((uint extent, uint size) extent in entry.Value.Extents)
|
||||
{
|
||||
uint extentSizeInSectors = extent.size / 2048;
|
||||
if(extent.size % 2048 > 0) extentSizeInSectors++;
|
||||
|
||||
byte[] extentData = ReadSectors(extent.extent, extentSizeInSectors);
|
||||
|
||||
ms.Write(extentData, 0, extentData.Length);
|
||||
}
|
||||
|
||||
directoryBuffer = ms.ToArray();
|
||||
}
|
||||
|
||||
currentDirectory = cdi
|
||||
? DecodeCdiDirectory(directoryBuffer, entry.Value.XattrLength)
|
||||
? DecodeCdiDirectory(entry.Value.Extents[0].extent, dirSizeInSectors,
|
||||
entry.Value.XattrLength)
|
||||
: highSierra
|
||||
? DecodeHighSierraDirectory(directoryBuffer, entry.Value.XattrLength)
|
||||
: DecodeIsoDirectory(directoryBuffer, entry.Value.XattrLength);
|
||||
? DecodeHighSierraDirectory(entry.Value.Extents[0].extent, dirSizeInSectors,
|
||||
entry.Value.XattrLength)
|
||||
: DecodeIsoDirectory(entry.Value.Extents[0].extent, dirSizeInSectors,
|
||||
entry.Value.XattrLength);
|
||||
|
||||
if(usePathTable)
|
||||
foreach(DecodedDirectoryEntry subDirectory in cdi
|
||||
@@ -163,15 +145,20 @@ namespace DiscImageChef.Filesystems.ISO9660
|
||||
return contents;
|
||||
}
|
||||
|
||||
Dictionary<string, DecodedDirectoryEntry> DecodeCdiDirectory(byte[] data, byte xattrLength)
|
||||
Dictionary<string, DecodedDirectoryEntry> DecodeCdiDirectory(ulong start, uint count, byte xattrLength)
|
||||
{
|
||||
Dictionary<string, DecodedDirectoryEntry> entries = new Dictionary<string, DecodedDirectoryEntry>();
|
||||
int entryOff = xattrLength;
|
||||
|
||||
for(ulong sector = start; sector < start + count; sector++)
|
||||
{
|
||||
byte[] data = ReadSectors(sector, 1);
|
||||
|
||||
while(entryOff + CdiDirectoryRecordSize < data.Length)
|
||||
{
|
||||
CdiDirectoryRecord record =
|
||||
Marshal.ByteArrayToStructureBigEndian<CdiDirectoryRecord>(data, entryOff, CdiDirectoryRecordSize);
|
||||
Marshal.ByteArrayToStructureBigEndian<CdiDirectoryRecord>(data, entryOff,
|
||||
CdiDirectoryRecordSize);
|
||||
|
||||
if(record.length == 0) break;
|
||||
|
||||
@@ -186,7 +173,8 @@ namespace DiscImageChef.Filesystems.ISO9660
|
||||
DecodedDirectoryEntry entry = new DecodedDirectoryEntry
|
||||
{
|
||||
Size = record.size,
|
||||
Filename = Encoding.GetString(data, entryOff + DirectoryRecordSize, record.name_len),
|
||||
Filename =
|
||||
Encoding.GetString(data, entryOff + DirectoryRecordSize, record.name_len),
|
||||
VolumeSequenceNumber = record.volume_sequence_number,
|
||||
Timestamp = DecodeHighSierraDateTime(record.date),
|
||||
XattrLength = record.xattr_len
|
||||
@@ -218,14 +206,21 @@ namespace DiscImageChef.Filesystems.ISO9660
|
||||
entryOff += record.length;
|
||||
}
|
||||
|
||||
entryOff = 0;
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
Dictionary<string, DecodedDirectoryEntry> DecodeHighSierraDirectory(byte[] data, byte xattrLength)
|
||||
Dictionary<string, DecodedDirectoryEntry> DecodeHighSierraDirectory(ulong start, uint count, byte xattrLength)
|
||||
{
|
||||
Dictionary<string, DecodedDirectoryEntry> entries = new Dictionary<string, DecodedDirectoryEntry>();
|
||||
int entryOff = xattrLength;
|
||||
|
||||
for(ulong sector = start; sector < start + count; sector++)
|
||||
{
|
||||
byte[] data = ReadSectors(sector, 1);
|
||||
|
||||
while(entryOff + DirectoryRecordSize < data.Length)
|
||||
{
|
||||
HighSierraDirectoryRecord record =
|
||||
@@ -248,12 +243,14 @@ namespace DiscImageChef.Filesystems.ISO9660
|
||||
Flags = record.flags,
|
||||
Interleave = record.interleave,
|
||||
VolumeSequenceNumber = record.volume_sequence_number,
|
||||
Filename = Encoding.GetString(data, entryOff + DirectoryRecordSize, record.name_len),
|
||||
Filename =
|
||||
Encoding.GetString(data, entryOff + DirectoryRecordSize, record.name_len),
|
||||
Timestamp = DecodeHighSierraDateTime(record.date),
|
||||
XattrLength = record.xattr_len
|
||||
};
|
||||
|
||||
if(record.size != 0) entry.Extents = new List<(uint extent, uint size)> {(record.extent, record.size)};
|
||||
if(record.size != 0)
|
||||
entry.Extents = new List<(uint extent, uint size)> {(record.extent, record.size)};
|
||||
|
||||
if(entry.Flags.HasFlag(FileFlags.Directory) && usePathTable)
|
||||
{
|
||||
@@ -266,16 +263,23 @@ namespace DiscImageChef.Filesystems.ISO9660
|
||||
entryOff += record.length;
|
||||
}
|
||||
|
||||
entryOff = 0;
|
||||
}
|
||||
|
||||
if(useTransTbl) DecodeTransTable(entries);
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
Dictionary<string, DecodedDirectoryEntry> DecodeIsoDirectory(byte[] data, byte xattrLength)
|
||||
Dictionary<string, DecodedDirectoryEntry> DecodeIsoDirectory(ulong start, uint count, byte xattrLength)
|
||||
{
|
||||
Dictionary<string, DecodedDirectoryEntry> entries = new Dictionary<string, DecodedDirectoryEntry>();
|
||||
int entryOff = xattrLength;
|
||||
|
||||
for(ulong sector = start; sector < start + count; sector++)
|
||||
{
|
||||
byte[] data = ReadSectors(sector, 1);
|
||||
|
||||
while(entryOff + DirectoryRecordSize < data.Length)
|
||||
{
|
||||
DirectoryRecord record =
|
||||
@@ -307,7 +311,8 @@ namespace DiscImageChef.Filesystems.ISO9660
|
||||
XattrLength = record.xattr_len
|
||||
};
|
||||
|
||||
if(record.size != 0) entry.Extents = new List<(uint extent, uint size)> {(record.extent, record.size)};
|
||||
if(record.size != 0)
|
||||
entry.Extents = new List<(uint extent, uint size)> {(record.extent, record.size)};
|
||||
|
||||
if(entry.Flags.HasFlag(FileFlags.Directory) && usePathTable)
|
||||
{
|
||||
@@ -401,6 +406,9 @@ namespace DiscImageChef.Filesystems.ISO9660
|
||||
entryOff += record.length;
|
||||
}
|
||||
|
||||
entryOff = 0;
|
||||
}
|
||||
|
||||
if(useTransTbl) DecodeTransTable(entries);
|
||||
|
||||
// Relocated directories should be shown in correct place when using Rock Ridge namespace
|
||||
|
||||
@@ -348,10 +348,10 @@ namespace DiscImageChef.Filesystems.ISO9660
|
||||
|
||||
if(this.@namespace != Namespace.Joliet)
|
||||
rootDirectoryCache = cdi
|
||||
? DecodeCdiDirectory(rootDir, rootXattrLength)
|
||||
? DecodeCdiDirectory(rootLocation, rootSize, rootXattrLength)
|
||||
: highSierra
|
||||
? DecodeHighSierraDirectory(rootDir, rootXattrLength)
|
||||
: DecodeIsoDirectory(rootDir, rootXattrLength);
|
||||
? DecodeHighSierraDirectory(rootLocation, rootSize, rootXattrLength)
|
||||
: DecodeIsoDirectory(rootLocation, rootSize, rootXattrLength);
|
||||
|
||||
XmlFsType.Type = fsFormat;
|
||||
|
||||
@@ -500,9 +500,7 @@ namespace DiscImageChef.Filesystems.ISO9660
|
||||
|
||||
joliet = true;
|
||||
|
||||
rootDir = ReadSectors(rootLocation, rootSize);
|
||||
|
||||
rootDirectoryCache = DecodeIsoDirectory(rootDir, rootXattrLength);
|
||||
rootDirectoryCache = DecodeIsoDirectory(rootLocation, rootSize, rootXattrLength);
|
||||
|
||||
XmlFsType.VolumeName = decodedJolietVd.VolumeIdentifier;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user