Handle when ISO9660 directories have extended attributes.

This commit is contained in:
2019-07-31 05:47:28 +01:00
parent 7b07c1e243
commit 4616f59a6b
4 changed files with 42 additions and 25 deletions

View File

@@ -71,10 +71,10 @@ namespace DiscImageChef.Filesystems.ISO9660
// TODO: Decode Joliet // TODO: Decode Joliet
currentDirectory = cdi currentDirectory = cdi
? DecodeCdiDirectory(directoryBuffer) ? DecodeCdiDirectory(directoryBuffer, entry.Value.XattrLength)
: highSierra : highSierra
? DecodeHighSierraDirectory(directoryBuffer) ? DecodeHighSierraDirectory(directoryBuffer, entry.Value.XattrLength)
: DecodeIsoDirectory(directoryBuffer); : DecodeIsoDirectory(directoryBuffer, entry.Value.XattrLength);
if(usePathTable) if(usePathTable)
foreach(DecodedDirectoryEntry subDirectory in cdi foreach(DecodedDirectoryEntry subDirectory in cdi
@@ -115,10 +115,10 @@ namespace DiscImageChef.Filesystems.ISO9660
return contents; return contents;
} }
Dictionary<string, DecodedDirectoryEntry> DecodeCdiDirectory(byte[] data) Dictionary<string, DecodedDirectoryEntry> DecodeCdiDirectory(byte[] data, byte XattrLength)
{ {
Dictionary<string, DecodedDirectoryEntry> entries = new Dictionary<string, DecodedDirectoryEntry>(); Dictionary<string, DecodedDirectoryEntry> entries = new Dictionary<string, DecodedDirectoryEntry>();
int entryOff = 0; int entryOff = XattrLength;
while(entryOff + DirectoryRecordSize < data.Length) while(entryOff + DirectoryRecordSize < data.Length)
{ {
@@ -167,10 +167,10 @@ namespace DiscImageChef.Filesystems.ISO9660
return entries; return entries;
} }
Dictionary<string, DecodedDirectoryEntry> DecodeHighSierraDirectory(byte[] data) Dictionary<string, DecodedDirectoryEntry> DecodeHighSierraDirectory(byte[] data, byte XattrLength)
{ {
Dictionary<string, DecodedDirectoryEntry> entries = new Dictionary<string, DecodedDirectoryEntry>(); Dictionary<string, DecodedDirectoryEntry> entries = new Dictionary<string, DecodedDirectoryEntry>();
int entryOff = 0; int entryOff = XattrLength;
while(entryOff + DirectoryRecordSize < data.Length) while(entryOff + DirectoryRecordSize < data.Length)
{ {
@@ -217,10 +217,10 @@ namespace DiscImageChef.Filesystems.ISO9660
return entries; return entries;
} }
Dictionary<string, DecodedDirectoryEntry> DecodeIsoDirectory(byte[] data) Dictionary<string, DecodedDirectoryEntry> DecodeIsoDirectory(byte[] data, byte XattrLength)
{ {
Dictionary<string, DecodedDirectoryEntry> entries = new Dictionary<string, DecodedDirectoryEntry>(); Dictionary<string, DecodedDirectoryEntry> entries = new Dictionary<string, DecodedDirectoryEntry>();
int entryOff = 0; int entryOff = XattrLength;
while(entryOff + DirectoryRecordSize < data.Length) while(entryOff + DirectoryRecordSize < data.Length)
{ {
@@ -732,6 +732,7 @@ namespace DiscImageChef.Filesystems.ISO9660
entry.Interleave = childRecord.interleave; entry.Interleave = childRecord.interleave;
entry.VolumeSequenceNumber = childRecord.volume_sequence_number; entry.VolumeSequenceNumber = childRecord.volume_sequence_number;
entry.Timestamp = DecodeIsoDateTime(childRecord.date); entry.Timestamp = DecodeIsoDateTime(childRecord.date);
entry.XattrLength = childRecord.xattr_len;
systemAreaOff += clLength; systemAreaOff += clLength;
@@ -923,7 +924,7 @@ namespace DiscImageChef.Filesystems.ISO9660
{ {
byte[] sector = image.ReadSector(tEntry.Extent); byte[] sector = image.ReadSector(tEntry.Extent);
CdiDirectoryRecord record = CdiDirectoryRecord record =
Marshal.ByteArrayToStructureBigEndian<CdiDirectoryRecord>(sector, 0, Marshal.ByteArrayToStructureBigEndian<CdiDirectoryRecord>(sector, tEntry.XattrLength,
Marshal.SizeOf<CdiDirectoryRecord>()); Marshal.SizeOf<CdiDirectoryRecord>());
if(record.length == 0) break; if(record.length == 0) break;
@@ -934,7 +935,8 @@ namespace DiscImageChef.Filesystems.ISO9660
Size = record.size, Size = record.size,
Filename = tEntry.Name, Filename = tEntry.Name,
VolumeSequenceNumber = record.volume_sequence_number, VolumeSequenceNumber = record.volume_sequence_number,
Timestamp = DecodeHighSierraDateTime(record.date) Timestamp = DecodeHighSierraDateTime(record.date),
XattrLength = tEntry.XattrLength
}; };
if(record.flags.HasFlag(CdiFileFlags.Hidden)) entry.Flags |= FileFlags.Hidden; if(record.flags.HasFlag(CdiFileFlags.Hidden)) entry.Flags |= FileFlags.Hidden;
@@ -962,7 +964,7 @@ namespace DiscImageChef.Filesystems.ISO9660
{ {
byte[] sector = image.ReadSector(tEntry.Extent); byte[] sector = image.ReadSector(tEntry.Extent);
DirectoryRecord record = DirectoryRecord record =
Marshal.ByteArrayToStructureLittleEndian<DirectoryRecord>(sector, 0, Marshal.ByteArrayToStructureLittleEndian<DirectoryRecord>(sector, tEntry.XattrLength,
Marshal.SizeOf<DirectoryRecord>()); Marshal.SizeOf<DirectoryRecord>());
if(record.length == 0) break; if(record.length == 0) break;
@@ -976,7 +978,8 @@ namespace DiscImageChef.Filesystems.ISO9660
FileUnitSize = record.file_unit_size, FileUnitSize = record.file_unit_size,
Interleave = record.interleave, Interleave = record.interleave,
VolumeSequenceNumber = record.volume_sequence_number, VolumeSequenceNumber = record.volume_sequence_number,
Timestamp = DecodeIsoDateTime(record.date) Timestamp = DecodeIsoDateTime(record.date),
XattrLength = tEntry.XattrLength
}; };
// TODO: XA // TODO: XA
@@ -1005,7 +1008,7 @@ namespace DiscImageChef.Filesystems.ISO9660
{ {
byte[] sector = image.ReadSector(tEntry.Extent); byte[] sector = image.ReadSector(tEntry.Extent);
HighSierraDirectoryRecord record = HighSierraDirectoryRecord record =
Marshal.ByteArrayToStructureLittleEndian<HighSierraDirectoryRecord>(sector, 0, Marshal.ByteArrayToStructureLittleEndian<HighSierraDirectoryRecord>(sector, tEntry.XattrLength,
Marshal Marshal
.SizeOf< .SizeOf<
HighSierraDirectoryRecord HighSierraDirectoryRecord
@@ -1019,7 +1022,8 @@ namespace DiscImageChef.Filesystems.ISO9660
Filename = tEntry.Name, Filename = tEntry.Name,
Interleave = record.interleave, Interleave = record.interleave,
VolumeSequenceNumber = record.volume_sequence_number, VolumeSequenceNumber = record.volume_sequence_number,
Timestamp = DecodeHighSierraDateTime(record.date) Timestamp = DecodeHighSierraDateTime(record.date),
XattrLength = tEntry.XattrLength
}; };
entries.Add(entry); entries.Add(entry);

View File

@@ -25,7 +25,10 @@ namespace DiscImageChef.Filesystems.ISO9660
table.Add(new PathTableEntryInternal table.Add(new PathTableEntryInternal
{ {
Extent = entry.start_lbn, Name = name, Parent = entry.parent_dirno Extent = entry.start_lbn,
Name = name,
Parent = entry.parent_dirno,
XattrLength = entry.xattr_len
}); });
off += entry.name_len; off += entry.name_len;
@@ -59,7 +62,10 @@ namespace DiscImageChef.Filesystems.ISO9660
table.Add(new PathTableEntryInternal table.Add(new PathTableEntryInternal
{ {
Extent = entry.start_lbn, Name = name, Parent = entry.parent_dirno Extent = entry.start_lbn,
Name = name,
Parent = entry.parent_dirno,
XattrLength = entry.xattr_len
}); });
off += entry.name_len; off += entry.name_len;

View File

@@ -132,6 +132,7 @@ namespace DiscImageChef.Filesystems.ISO9660
public uint Extent; public uint Extent;
public string Name; public string Name;
public ushort Parent; public ushort Parent;
public byte XattrLength;
public override string ToString() => Name; public override string ToString() => Name;
} }

View File

@@ -229,7 +229,7 @@ namespace DiscImageChef.Filesystems.ISO9660
pathTableMsbLocation = fsvd.Value.path_table_addr; pathTableMsbLocation = fsvd.Value.path_table_addr;
// TODO: Until escape sequences are implemented this is the default CD-i encoding. // TODO: Until escape sequences are implemented this is the default CD-i encoding.
Encoding = System.Text.Encoding.GetEncoding("iso8859-1"); Encoding = Encoding.GetEncoding("iso8859-1");
// TODO: Implement CD-i // TODO: Implement CD-i
return Errno.NotImplemented; return Errno.NotImplemented;
@@ -256,8 +256,9 @@ namespace DiscImageChef.Filesystems.ISO9660
if(jolietvd is null && this.@namespace == Namespace.Joliet) this.@namespace = Namespace.Normal; if(jolietvd is null && this.@namespace == Namespace.Joliet) this.@namespace = Namespace.Normal;
uint rootLocation = 0; uint rootLocation = 0;
uint rootSize = 0; uint rootSize = 0;
byte rootXattrLength = 0;
if(!cdi) if(!cdi)
{ {
@@ -265,6 +266,10 @@ namespace DiscImageChef.Filesystems.ISO9660
? hsvd.Value.root_directory_record.extent ? hsvd.Value.root_directory_record.extent
: pvd.Value.root_directory_record.extent; : pvd.Value.root_directory_record.extent;
rootXattrLength = highSierra
? hsvd.Value.root_directory_record.xattr_len
: pvd.Value.root_directory_record.xattr_len;
if(highSierra) if(highSierra)
{ {
rootSize = hsvd.Value.root_directory_record.size / hsvd.Value.logical_block_size; rootSize = hsvd.Value.root_directory_record.size / hsvd.Value.logical_block_size;
@@ -310,10 +315,10 @@ namespace DiscImageChef.Filesystems.ISO9660
if(this.@namespace != Namespace.Joliet) if(this.@namespace != Namespace.Joliet)
rootDirectoryCache = cdi rootDirectoryCache = cdi
? DecodeCdiDirectory(rootDir) ? DecodeCdiDirectory(rootDir, rootXattrLength)
: highSierra : highSierra
? DecodeHighSierraDirectory(rootDir) ? DecodeHighSierraDirectory(rootDir, rootXattrLength)
: DecodeIsoDirectory(rootDir); : DecodeIsoDirectory(rootDir, rootXattrLength);
XmlFsType.Type = fsFormat; XmlFsType.Type = fsFormat;
@@ -430,7 +435,8 @@ namespace DiscImageChef.Filesystems.ISO9660
if(jolietvd != null && (this.@namespace == Namespace.Joliet || this.@namespace == Namespace.Rrip)) if(jolietvd != null && (this.@namespace == Namespace.Joliet || this.@namespace == Namespace.Rrip))
{ {
rootLocation = jolietvd.Value.root_directory_record.extent; rootLocation = jolietvd.Value.root_directory_record.extent;
rootXattrLength = jolietvd.Value.root_directory_record.xattr_len;
rootSize = jolietvd.Value.root_directory_record.size / jolietvd.Value.logical_block_size; rootSize = jolietvd.Value.root_directory_record.size / jolietvd.Value.logical_block_size;
if(pvd.Value.root_directory_record.size % jolietvd.Value.logical_block_size > 0) if(pvd.Value.root_directory_record.size % jolietvd.Value.logical_block_size > 0)
@@ -442,7 +448,7 @@ namespace DiscImageChef.Filesystems.ISO9660
rootDir = imagePlugin.ReadSectors(rootLocation, rootSize); rootDir = imagePlugin.ReadSectors(rootLocation, rootSize);
rootDirectoryCache = DecodeIsoDirectory(rootDir); rootDirectoryCache = DecodeIsoDirectory(rootDir, rootXattrLength);
XmlFsType.VolumeName = decodedJolietVd.VolumeIdentifier; XmlFsType.VolumeName = decodedJolietVd.VolumeIdentifier;