diff --git a/DiscImageChef.Filesystems/ISO9660/Dir.cs b/DiscImageChef.Filesystems/ISO9660/Dir.cs index c48cb9ba6..07169af2d 100644 --- a/DiscImageChef.Filesystems/ISO9660/Dir.cs +++ b/DiscImageChef.Filesystems/ISO9660/Dir.cs @@ -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(); int systemAreaLength = record.length - record.name_len - Marshal.SizeOf(); @@ -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); } diff --git a/DiscImageChef.Filesystems/ISO9660/File.cs b/DiscImageChef.Filesystems/ISO9660/File.cs index cef70e59d..df5d07f9f 100644 --- a/DiscImageChef.Filesystems/ISO9660/File.cs +++ b/DiscImageChef.Filesystems/ISO9660/File.cs @@ -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(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(); + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/ISO9660/Structs/Internal.cs b/DiscImageChef.Filesystems/ISO9660/Structs/Internal.cs index aa243ecc6..c078ee64d 100644 --- a/DiscImageChef.Filesystems/ISO9660/Structs/Internal.cs +++ b/DiscImageChef.Filesystems/ISO9660/Structs/Internal.cs @@ -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; } diff --git a/DiscImageChef.Filesystems/ISO9660/Super.cs b/DiscImageChef.Filesystems/ISO9660/Super.cs index 4f7267bdc..04e1e7786 100644 --- a/DiscImageChef.Filesystems/ISO9660/Super.cs +++ b/DiscImageChef.Filesystems/ISO9660/Super.cs @@ -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()) + }, Filename = "$IP.BIN", Size = (uint)Marshal.SizeOf(), 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()) + }, Filename = "$IP.BIN", Size = (uint)Marshal.SizeOf(), 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()) + }, Filename = "$IP.BIN", Size = (uint)Marshal.SizeOf(), Timestamp = decodedVd.CreationTime diff --git a/DiscImageChef.Filesystems/ISO9660/Xattr.cs b/DiscImageChef.Filesystems/ISO9660/Xattr.cs index 1f33ef5bc..5d7aa98d2 100644 --- a/DiscImageChef.Filesystems/ISO9660/Xattr.cs +++ b/DiscImageChef.Filesystems/ISO9660/Xattr.cs @@ -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":