Implement support for ISO9660 Level 3, multiple extents in files.

This commit is contained in:
2019-07-31 19:39:55 +01:00
parent 838b5f8307
commit 816835e667
5 changed files with 235 additions and 99 deletions

View File

@@ -57,17 +57,34 @@ namespace DiscImageChef.Filesystems.ISO9660
if(!entry.Value.Flags.HasFlag(FileFlags.Directory)) return Errno.NotDirectory;
currentPath = p == 0 ? pieces[0] : $"{currentPath}/{pieces[p]}";
uint currentExtent = entry.Value.Extent;
if(directoryCache.TryGetValue(currentPath, out currentDirectory)) continue;
if(currentExtent == 0) return Errno.InvalidArgument;
if(entry.Value.Extents.Count == 0) return Errno.InvalidArgument;
// TODO: XA, High Sierra
uint dirSizeInSectors = entry.Value.Size / 2048;
if(entry.Value.Size % 2048 > 0) dirSizeInSectors++;
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();
byte[] directoryBuffer = ReadSectors(currentExtent, dirSizeInSectors);
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();
}
// TODO: Decode Joliet
currentDirectory = cdi
@@ -138,7 +155,6 @@ namespace DiscImageChef.Filesystems.ISO9660
DecodedDirectoryEntry entry = new DecodedDirectoryEntry
{
Extent = record.size == 0 ? 0 : record.start_lbn,
Size = record.size,
Filename = Encoding.GetString(data, entryOff + DirectoryRecordSize, record.name_len),
VolumeSequenceNumber = record.volume_sequence_number,
@@ -146,6 +162,9 @@ namespace DiscImageChef.Filesystems.ISO9660
XattrLength = record.xattr_len
};
if(record.size != 0)
entry.Extents = new List<(uint extent, uint size)> {(record.start_lbn, record.size)};
if(record.flags.HasFlag(CdiFileFlags.Hidden))
{
entry.Flags |= FileFlags.Hidden;
@@ -197,7 +216,6 @@ namespace DiscImageChef.Filesystems.ISO9660
DecodedDirectoryEntry entry = new DecodedDirectoryEntry
{
Extent = record.size == 0 ? 0 : record.extent,
Size = record.size,
Flags = record.flags,
Interleave = record.interleave,
@@ -207,6 +225,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(entry.Flags.HasFlag(FileFlags.Directory) && usePathTable)
{
entryOff += record.length;
@@ -246,9 +266,8 @@ namespace DiscImageChef.Filesystems.ISO9660
DecodedDirectoryEntry entry = new DecodedDirectoryEntry
{
Extent = record.size == 0 ? 0 : record.extent,
Size = record.size,
Flags = record.flags,
Size = record.size,
Flags = record.flags,
Filename =
joliet
? Encoding.BigEndianUnicode.GetString(data, entryOff + DirectoryRecordSize,
@@ -261,6 +280,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(entry.Flags.HasFlag(FileFlags.Directory) && usePathTable)
{
entryOff += record.length;
@@ -294,19 +315,25 @@ namespace DiscImageChef.Filesystems.ISO9660
DecodeSystemArea(data, systemAreaStart, systemAreaStart + systemAreaLength, ref entry,
out bool hasResourceFork);
// TODO: Multi-extent files
if(entry.Flags.HasFlag(FileFlags.Associated))
{
if(entries.ContainsKey(entry.Filename))
{
if(hasResourceFork) entries[entry.Filename].ResourceFork = entry;
else entries[entry.Filename].AssociatedFile = entry;
if(hasResourceFork)
{
entries[entry.Filename].ResourceFork.Size += entry.Size;
entries[entry.Filename].ResourceFork.Extents.Add(entry.Extents[0]);
}
else
{
entries[entry.Filename].AssociatedFile.Size += entry.Size;
entries[entry.Filename].AssociatedFile.Extents.Add(entry.Extents[0]);
}
}
else
{
entries[entry.Filename] = new DecodedDirectoryEntry
{
Extent = 0,
Size = 0,
Flags = record.flags ^ FileFlags.Associated,
FileUnitSize = 0,
@@ -325,11 +352,24 @@ namespace DiscImageChef.Filesystems.ISO9660
{
if(entries.ContainsKey(entry.Filename))
{
entry.AssociatedFile = entries[entry.Filename].AssociatedFile;
entry.ResourceFork = entries[entry.Filename].ResourceFork;
}
entries[entry.Filename].Size += entry.Size;
entries[entry.Filename] = entry;
// Can appear after an associated file
if(entries[entry.Filename].Extents is null)
{
entries[entry.Filename].Extents = new List<(uint extent, uint size)>();
entries[entry.Filename].Flags = entry.Flags;
entries[entry.Filename].FileUnitSize = entry.FileUnitSize;
entries[entry.Filename].Interleave = entry.Interleave;
entries[entry.Filename].VolumeSequenceNumber = entry.VolumeSequenceNumber;
entries[entry.Filename].Filename = entry.Filename;
entries[entry.Filename].Timestamp = entry.Timestamp;
entries[entry.Filename].XattrLength = entry.XattrLength;
}
entries[entry.Filename].Extents.Add(entry.Extents[0]);
}
else entries[entry.Filename] = entry;
}
entryOff += record.length;
@@ -352,10 +392,11 @@ namespace DiscImageChef.Filesystems.ISO9660
if(transTblEntry.Value == null) return;
uint transTblSectors = transTblEntry.Value.Size / 2048;
// The probability of a TRANS.TBL to be bigger than 2GiB is nil
uint transTblSectors = (uint)transTblEntry.Value.Size / 2048;
if(transTblEntry.Value.Size % 2048 > 0) transTblSectors++;
byte[] transTbl = ReadSectors(transTblEntry.Value.Extent, transTblSectors);
byte[] transTbl = ReadSectors(transTblEntry.Value.Extents[0].extent, transTblSectors);
MemoryStream mr = new MemoryStream(transTbl, 0, (int)transTblEntry.Value.Size, false);
StreamReader sr = new StreamReader(mr, Encoding);
@@ -731,7 +772,8 @@ namespace DiscImageChef.Filesystems.ISO9660
// As per RRIP 4.1.5.1, we leave name as in previous entry, substitute location with the one in
// the CL, and replace all other fields with the ones found in the first entry of the child
entry.Extent = cl.child_dir_lba;
entry.Extents =
new List<(uint extent, uint size)> {(cl.child_dir_lba, childRecord.size)};
entry.Size = childRecord.size;
entry.Flags = childRecord.flags;
entry.FileUnitSize = childRecord.file_unit_size;
@@ -937,7 +979,6 @@ namespace DiscImageChef.Filesystems.ISO9660
DecodedDirectoryEntry entry = new DecodedDirectoryEntry
{
Extent = record.size == 0 ? 0 : record.start_lbn,
Size = record.size,
Filename = tEntry.Name,
VolumeSequenceNumber = record.volume_sequence_number,
@@ -945,6 +986,9 @@ namespace DiscImageChef.Filesystems.ISO9660
XattrLength = tEntry.XattrLength
};
if(record.size != 0)
entry.Extents = new List<(uint extent, uint size)> {(record.start_lbn, record.size)};
if(record.flags.HasFlag(CdiFileFlags.Hidden)) entry.Flags |= FileFlags.Hidden;
entry.CdiSystemArea =
@@ -977,7 +1021,6 @@ namespace DiscImageChef.Filesystems.ISO9660
DecodedDirectoryEntry entry = new DecodedDirectoryEntry
{
Extent = record.size == 0 ? 0 : record.extent,
Size = record.size,
Flags = record.flags,
Filename = tEntry.Name,
@@ -988,6 +1031,8 @@ namespace DiscImageChef.Filesystems.ISO9660
XattrLength = tEntry.XattrLength
};
if(record.size != 0) entry.Extents = new List<(uint extent, uint size)> {(record.extent, record.size)};
// TODO: XA
int systemAreaStart = record.name_len + Marshal.SizeOf<DirectoryRecord>();
int systemAreaLength = record.length - record.name_len - Marshal.SizeOf<DirectoryRecord>();
@@ -1022,7 +1067,6 @@ namespace DiscImageChef.Filesystems.ISO9660
DecodedDirectoryEntry entry = new DecodedDirectoryEntry
{
Extent = record.size == 0 ? 0 : record.extent,
Size = record.size,
Flags = record.flags,
Filename = tEntry.Name,
@@ -1032,6 +1076,8 @@ namespace DiscImageChef.Filesystems.ISO9660
XattrLength = tEntry.XattrLength
};
if(record.size != 0) entry.Extents = new List<(uint extent, uint size)> {(record.extent, record.size)};
entries.Add(entry);
}

View File

@@ -21,7 +21,10 @@ namespace DiscImageChef.Filesystems.ISO9660
if(entry.Flags.HasFlag(FileFlags.Directory) && !debug) return Errno.IsDirectory;
deviceBlock = entry.Extent + fileBlock;
// TODO: Multi-extents
if(entry.Extents.Count > 1) return Errno.NotImplemented;
deviceBlock = entry.Extents[0].extent + fileBlock;
return Errno.NoError;
}
@@ -51,15 +54,18 @@ namespace DiscImageChef.Filesystems.ISO9660
if(entry.Flags.HasFlag(FileFlags.Directory) && !debug) return Errno.IsDirectory;
if(entry.Extents is null) return Errno.InvalidArgument;
if(entry.Size - entry.XattrLength == 0)
{
buf = new byte[0];
return Errno.NoError;
}
if(offset >= entry.Size - entry.XattrLength) return Errno.InvalidArgument;
if(offset >= (long)entry.Size - entry.XattrLength) return Errno.InvalidArgument;
if(size + offset + entry.XattrLength >= entry.Size) size = entry.Size - offset - entry.XattrLength;
if(size + offset + entry.XattrLength >= (long)entry.Size)
size = (long)entry.Size - offset - entry.XattrLength;
offset += entry.XattrLength;
@@ -69,12 +75,18 @@ namespace DiscImageChef.Filesystems.ISO9660
long sizeInSectors = (size + offsetInSector) / 2048;
if((size + offsetInSector) % 2048 > 0) sizeInSectors++;
// No need to check mode, if we know it is CD-DA
byte[] buffer = entry.CdiSystemArea?.attributes.HasFlag(CdiAttributes.DigitalAudio) == true
? image.ReadSectors((ulong)(entry.Extent + firstSector), (uint)sizeInSectors)
: ReadSectors((ulong)(entry.Extent + firstSector), (uint)sizeInSectors);
buf = new byte[size];
Array.Copy(buffer, offsetInSector, buf, 0, size);
if(entry.Extents.Count == 1)
{
// No need to check mode, if we know it is CD-DA
byte[] buffer = entry.CdiSystemArea?.attributes.HasFlag(CdiAttributes.DigitalAudio) == true
? image.ReadSectors((ulong)(entry.Extents[0].extent + firstSector),
(uint)sizeInSectors)
: ReadSectors((ulong)(entry.Extents[0].extent + firstSector), (uint)sizeInSectors);
buf = new byte[size];
Array.Copy(buffer, offsetInSector, buf, 0, size);
}
else buf = ReadWithExtents(offset, size, entry.Extents);
return Errno.NoError;
}
@@ -90,10 +102,10 @@ namespace DiscImageChef.Filesystems.ISO9660
stat = new FileEntryInfo
{
Attributes = new FileAttributes(),
Blocks = entry.Size / 2048, // TODO: XA
Blocks = (long)(entry.Size / 2048), // TODO: XA
BlockSize = 2048,
Length = entry.Size - entry.XattrLength,
Inode = entry.Extent,
Length = (long)(entry.Size - entry.XattrLength),
Inode = entry.Extents?[0].extent ?? 0,
Links = 1,
LastWriteTimeUtc = entry.Timestamp
};
@@ -219,7 +231,7 @@ namespace DiscImageChef.Filesystems.ISO9660
uint eaSizeInSectors = (uint)(entry.XattrLength / 2048);
if(entry.XattrLength % 2048 > 0) eaSizeInSectors++;
byte[] ea = ReadSectors(entry.Extent, eaSizeInSectors);
byte[] ea = ReadSectors(entry.Extents[0].extent, eaSizeInSectors);
ExtendedAttributeRecord ear = Marshal.ByteArrayToStructureLittleEndian<ExtendedAttributeRecord>(ea);
@@ -298,5 +310,54 @@ namespace DiscImageChef.Filesystems.ISO9660
entry = dirent.Value;
return Errno.NoError;
}
// Cannot think how to make this faster, as we don't know the mode sector until it is read, but we have size in bytes
byte[] ReadWithExtents(long offset, long size, List<(uint extent, uint size)> extents)
{
MemoryStream ms = new MemoryStream();
long currentFilePos = 0;
for(int i = 0; i < extents.Count; i++)
{
if(offset - currentFilePos >= extents[i].size)
{
currentFilePos += extents[i].size;
continue;
}
long leftExtentSize = extents[i].size;
uint currentExtentSector = 0;
while(leftExtentSize > 0)
{
byte[] sector = ReadSectors(extents[i].extent + currentExtentSector, 1);
if(offset - currentFilePos > sector.Length)
{
currentExtentSector++;
leftExtentSize -= sector.Length;
currentFilePos += sector.Length;
continue;
}
if(offset - currentFilePos > 0)
ms.Write(sector, (int)(offset - currentFilePos),
(int)(sector.Length - (offset - currentFilePos)));
else ms.Write(sector, 0, sector.Length);
currentExtentSector++;
leftExtentSize -= sector.Length;
currentFilePos += sector.Length;
if(ms.Length >= size) break;
}
if(ms.Length >= size) break;
}
if(ms.Length >= size) ms.SetLength(size);
return ms.ToArray();
}
}
}

View File

@@ -31,6 +31,7 @@
// ****************************************************************************/
using System;
using System.Collections.Generic;
namespace DiscImageChef.Filesystems.ISO9660
{
@@ -57,38 +58,38 @@ namespace DiscImageChef.Filesystems.ISO9660
class DecodedDirectoryEntry
{
public byte[] AmigaComment;
public AmigaProtection? AmigaProtection;
public byte? AppleDosType;
public byte[] AppleIcon;
public ushort? AppleProDosType;
public DecodedDirectoryEntry AssociatedFile;
public CdiSystemArea? CdiSystemArea;
public uint Extent;
public string Filename;
public byte FileUnitSize;
public FinderInfo FinderInfo;
public FileFlags Flags;
public byte Interleave;
public PosixAttributes? PosixAttributes;
public PosixAttributesOld? PosixAttributesOld;
public PosixDeviceNumber? PosixDeviceNumber;
public DecodedDirectoryEntry ResourceFork;
public byte[] RockRidgeAlternateName;
public bool RockRidgeRelocated;
public byte[] RripAccess;
public byte[] RripAttributeChange;
public byte[] RripBackup;
public byte[] RripCreation;
public byte[] RripEffective;
public byte[] RripExpiration;
public byte[] RripModify;
public uint Size;
public string SymbolicLink;
public DateTime? Timestamp;
public ushort VolumeSequenceNumber;
public CdromXa? XA;
public byte XattrLength;
public byte[] AmigaComment;
public AmigaProtection? AmigaProtection;
public byte? AppleDosType;
public byte[] AppleIcon;
public ushort? AppleProDosType;
public DecodedDirectoryEntry AssociatedFile;
public CdiSystemArea? CdiSystemArea;
public List<(uint extent, uint size)> Extents;
public string Filename;
public byte FileUnitSize;
public FinderInfo FinderInfo;
public FileFlags Flags;
public byte Interleave;
public PosixAttributes? PosixAttributes;
public PosixAttributesOld? PosixAttributesOld;
public PosixDeviceNumber? PosixDeviceNumber;
public DecodedDirectoryEntry ResourceFork;
public byte[] RockRidgeAlternateName;
public bool RockRidgeRelocated;
public byte[] RripAccess;
public byte[] RripAttributeChange;
public byte[] RripBackup;
public byte[] RripCreation;
public byte[] RripEffective;
public byte[] RripExpiration;
public byte[] RripModify;
public ulong Size;
public string SymbolicLink;
public DateTime? Timestamp;
public ushort VolumeSequenceNumber;
public CdromXa? XA;
public byte XattrLength;
public override string ToString() => Filename;
}

View File

@@ -327,9 +327,13 @@ namespace DiscImageChef.Filesystems.ISO9660
rootDirectoryCache.Add("$",
new DecodedDirectoryEntry
{
Extent = rootLocation,
Extents =
new List<(uint extent, uint size)>
{
(rootLocation, (uint)rootDir.Length)
},
Filename = "$",
Size = 2048,
Size = (uint)rootDir.Length,
Timestamp = decodedVd.CreationTime
});
@@ -337,7 +341,11 @@ namespace DiscImageChef.Filesystems.ISO9660
rootDirectoryCache.Add("$PATH_TABLE.LSB",
new DecodedDirectoryEntry
{
Extent = pathTableLsbLocation,
Extents =
new List<(uint extent, uint size)>
{
(rootLocation, (uint)pathTableData.Length)
},
Filename = "$PATH_TABLE.LSB",
Size = (uint)pathTableData.Length,
Timestamp = decodedVd.CreationTime
@@ -346,7 +354,11 @@ namespace DiscImageChef.Filesystems.ISO9660
rootDirectoryCache.Add("$PATH_TABLE.MSB",
new DecodedDirectoryEntry
{
Extent = pathTableMsbLocation,
Extents =
new List<(uint extent, uint size)>
{
(rootLocation, (uint)pathTableData.Length)
},
Filename = "$PATH_TABLE.MSB",
Size = (uint)pathTableData.Length,
Timestamp = decodedVd.CreationTime
@@ -356,7 +368,7 @@ namespace DiscImageChef.Filesystems.ISO9660
rootDirectoryCache.Add(i == 0 ? "$BOOT" : $"$BOOT_{i}",
new DecodedDirectoryEntry
{
Extent = (uint)i,
Extents = new List<(uint extent, uint size)> {((uint)i, 2048)},
Filename = i == 0 ? "$BOOT" : $"$BOOT_{i}",
Size = 2048,
Timestamp = decodedVd.CreationTime
@@ -366,7 +378,7 @@ namespace DiscImageChef.Filesystems.ISO9660
rootDirectoryCache.Add(i == 0 ? "$PVD" : $"$PVD{i}",
new DecodedDirectoryEntry
{
Extent = (uint)i,
Extents = new List<(uint extent, uint size)> {((uint)i, 2048)},
Filename = i == 0 ? "$PVD" : $"PVD_{i}",
Size = 2048,
Timestamp = decodedVd.CreationTime
@@ -376,7 +388,7 @@ namespace DiscImageChef.Filesystems.ISO9660
rootDirectoryCache.Add(i == 0 ? "$SVD" : $"$SVD_{i}",
new DecodedDirectoryEntry
{
Extent = (uint)i,
Extents = new List<(uint extent, uint size)> {((uint)i, 2048)},
Filename = i == 0 ? "$SVD" : $"$SVD_{i}",
Size = 2048,
Timestamp = decodedVd.CreationTime
@@ -386,7 +398,7 @@ namespace DiscImageChef.Filesystems.ISO9660
rootDirectoryCache.Add(i == 0 ? "$EVD" : $"$EVD_{i}",
new DecodedDirectoryEntry
{
Extent = (uint)i,
Extents = new List<(uint extent, uint size)> {((uint)i, 2048)},
Filename = i == 0 ? "$EVD" : $"$EVD_{i}",
Size = 2048,
Timestamp = decodedVd.CreationTime
@@ -396,7 +408,7 @@ namespace DiscImageChef.Filesystems.ISO9660
rootDirectoryCache.Add(i == 0 ? "$VPD" : $"$VPD_{i}",
new DecodedDirectoryEntry
{
Extent = (uint)i,
Extents = new List<(uint extent, uint size)> {((uint)i, 2048)},
Filename = i == 0 ? "$VPD" : $"$VPD_{i}",
Size = 2048,
Timestamp = decodedVd.CreationTime
@@ -406,7 +418,10 @@ namespace DiscImageChef.Filesystems.ISO9660
rootDirectoryCache.Add("$IP.BIN",
new DecodedDirectoryEntry
{
Extent = 0,
Extents = new List<(uint extent, uint size)>
{
((uint)partition.Start, (uint)Marshal.SizeOf<CD.IPBin>())
},
Filename = "$IP.BIN",
Size = (uint)Marshal.SizeOf<CD.IPBin>(),
Timestamp = decodedVd.CreationTime
@@ -416,7 +431,10 @@ namespace DiscImageChef.Filesystems.ISO9660
rootDirectoryCache.Add("$IP.BIN",
new DecodedDirectoryEntry
{
Extent = 0,
Extents = new List<(uint extent, uint size)>
{
((uint)partition.Start, (uint)Marshal.SizeOf<Saturn.IPBin>())
},
Filename = "$IP.BIN",
Size = (uint)Marshal.SizeOf<Saturn.IPBin>(),
Timestamp = decodedVd.CreationTime
@@ -426,7 +444,11 @@ namespace DiscImageChef.Filesystems.ISO9660
rootDirectoryCache.Add("$IP.BIN",
new DecodedDirectoryEntry
{
Extent = 0,
Extents = new List<(uint extent, uint size)>
{
((uint)partition.Start,
(uint)Marshal.SizeOf<Dreamcast.IPBin>())
},
Filename = "$IP.BIN",
Size = (uint)Marshal.SizeOf<Dreamcast.IPBin>(),
Timestamp = decodedVd.CreationTime

View File

@@ -41,11 +41,13 @@ namespace DiscImageChef.Filesystems.ISO9660
case "org.iso.9660.ea":
if(entry.XattrLength == 0) return Errno.NoSuchExtendedAttribute;
if(entry.Extents is null) return Errno.InvalidArgument;
// TODO: XA
uint eaSizeInSectors = (uint)(entry.XattrLength / 2048);
if(entry.XattrLength % 2048 > 0) eaSizeInSectors++;
byte[] ea = ReadSectors(entry.Extent, eaSizeInSectors);
byte[] ea = ReadSectors(entry.Extents[0].extent, eaSizeInSectors);
buf = new byte[entry.AssociatedFile.Size];
Array.Copy(ea, 0, buf, 0, buf.LongLength);
@@ -54,7 +56,7 @@ namespace DiscImageChef.Filesystems.ISO9660
case "org.iso.9660.AssociatedFile":
if(entry.AssociatedFile is null) return Errno.NoSuchExtendedAttribute;
if(entry.AssociatedFile.Extent == 0) return Errno.InvalidArgument;
if(entry.AssociatedFile.Extents is null) return Errno.InvalidArgument;
if(entry.AssociatedFile.Size == 0)
{
@@ -62,14 +64,16 @@ namespace DiscImageChef.Filesystems.ISO9660
return Errno.NoError;
}
// TODO: XA
uint associatedFileSize = entry.AssociatedFile.Size / 2048;
if(entry.AssociatedFile.Size % 2048 > 0) associatedFileSize++;
if(entry.AssociatedFile.Extents.Count == 1)
{
uint associatedFileSize = (uint)(entry.AssociatedFile.Size / 2048);
if(entry.AssociatedFile.Size % 2048 > 0) associatedFileSize++;
byte[] buffer = ReadSectors(entry.AssociatedFile.Extents[0].extent, associatedFileSize);
byte[] associatedFile = ReadSectors(entry.AssociatedFile.Extent, associatedFileSize);
buf = new byte[entry.AssociatedFile.Size];
Array.Copy(associatedFile, 0, buf, 0, buf.LongLength);
buf = new byte[entry.AssociatedFile.Size];
Array.Copy(buffer, 0, buf, 0, buf.LongLength);
}
else buf = ReadWithExtents(0, (long)entry.AssociatedFile.Size, entry.AssociatedFile.Extents);
return Errno.NoError;
case "com.apple.dos.type":
@@ -88,7 +92,7 @@ namespace DiscImageChef.Filesystems.ISO9660
case "com.apple.ResourceFork":
if(entry.ResourceFork is null) return Errno.NoSuchExtendedAttribute;
if(entry.ResourceFork.Extent == 0) return Errno.InvalidArgument;
if(entry.ResourceFork.Extents is null) return Errno.InvalidArgument;
if(entry.ResourceFork.Size == 0)
{
@@ -96,14 +100,16 @@ namespace DiscImageChef.Filesystems.ISO9660
return Errno.NoError;
}
// TODO: XA
uint rsrcSizeInSectors = entry.ResourceFork.Size / 2048;
if(entry.ResourceFork.Size % 2048 > 0) rsrcSizeInSectors++;
if(entry.ResourceFork.Extents.Count == 1)
{
uint rsrcSizeInSectors = (uint)(entry.ResourceFork.Size / 2048);
if(entry.AssociatedFile.Size % 2048 > 0) rsrcSizeInSectors++;
byte[] buffer = ReadSectors(entry.ResourceFork.Extents[0].extent, rsrcSizeInSectors);
byte[] rsrc = ReadSectors(entry.ResourceFork.Extent, rsrcSizeInSectors);
buf = new byte[entry.ResourceFork.Size];
Array.Copy(rsrc, 0, buf, 0, buf.LongLength);
buf = new byte[entry.ResourceFork.Size];
Array.Copy(buffer, 0, buf, 0, buf.LongLength);
}
else buf = ReadWithExtents(0, (long)entry.ResourceFork.Size, entry.ResourceFork.Extents);
return Errno.NoError;
case "com.apple.FinderInfo":