diff --git a/DiscImageChef.Filesystems/ISO9660/Consts.cs b/DiscImageChef.Filesystems/ISO9660/Consts.cs index b17f09b84..4a977d480 100644 --- a/DiscImageChef.Filesystems/ISO9660/Consts.cs +++ b/DiscImageChef.Filesystems/ISO9660/Consts.cs @@ -39,6 +39,7 @@ namespace DiscImageChef.Filesystems.ISO9660 readonly string HighSierraMagic = "CDROM"; const ushort ElToritoMagic = 0xAA55; const int ElToritoEntrySize = 32; + const ushort XaMagic = 0x5841; // "XA" [Flags] enum FileFlags : byte @@ -64,6 +65,22 @@ namespace DiscImageChef.Filesystems.ISO9660 OtherExecute = 0x4000, } + [Flags] + enum XaAttributes : ushort + { + SystemRead = 0x01, + SystemExecute = 0x04, + OwnerRead = 0x10, + OwnerExecute = 0x40, + GroupRead = 0x100, + GroupExecute = 0x400, + Mode2Form1 = 0x800, + Mode2Form2 = 0x1000, + Interleaved = 0x2000, + Cdda = 0x4000, + Directory = 0x8000, + } + enum RecordFormat : byte { Unspecified = 0, diff --git a/DiscImageChef.Filesystems/ISO9660/Info.cs b/DiscImageChef.Filesystems/ISO9660/Info.cs index cc1f076d4..78504bd50 100644 --- a/DiscImageChef.Filesystems/ISO9660/Info.cs +++ b/DiscImageChef.Filesystems/ISO9660/Info.cs @@ -235,8 +235,44 @@ namespace DiscImageChef.Filesystems.ISO9660 if(jolietvd != null) decodedJolietVD = DecodeJolietDescriptor(jolietvd.Value); - ulong i = (ulong)BitConverter.ToInt32(VDPathTableStart, 0); - DicConsole.DebugWriteLine("ISO9660 plugin", "VDPathTableStart = {0} + {1} = {2}", i, partition.Start, i + partition.Start); + uint rootLocation = HighSierra ? hsvd.Value.root_directory_record.extent : pvd.Value.root_directory_record.extent; + uint rootSize = HighSierra ? hsvd.Value.root_directory_record.size / hsvd.Value.logical_block_size : pvd.Value.root_directory_record.size / pvd.Value.logical_block_size; + + byte[] root_dir = imagePlugin.ReadSectors(rootLocation + partition.Start, rootSize); + int rootOff = 0; + bool XA = false; + + // Walk thru root directory to see system area extensions in use + while(rootOff < root_dir.Length) + { + DirectoryRecord record = new DirectoryRecord(); + IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(record)); + Marshal.Copy(root_dir, rootOff, ptr, Marshal.SizeOf(record)); + record = (DirectoryRecord)Marshal.PtrToStructure(ptr, typeof(DirectoryRecord)); + Marshal.FreeHGlobal(ptr); + + int sa_off = Marshal.SizeOf(record) + record.name_len; + int sa_len = record.length - sa_off; + + if(sa_len > 0 && rootOff + sa_off + sa_len <= root_dir.Length) + { + byte[] sa = new byte[sa_len]; + Array.Copy(root_dir, rootOff + sa_off, sa, 0, sa_len); + + if(sa_len >= Marshal.SizeOf(typeof(CdromXa))) + { + CdromXa xa = BigEndianMarshal.ByteArrayToStructureBigEndian(sa); + if(xa.signature == XaMagic) + XA = true; + } + } + + rootOff += record.length; + + if(record.length == 0) + break; + } + // TODO: Check this /* @@ -265,10 +301,12 @@ namespace DiscImageChef.Filesystems.ISO9660 Decoders.Sega.Dreamcast.IPBin? Dreamcast = Decoders.Sega.Dreamcast.DecodeIPBin(ipbin_sector); ISOMetadata.AppendFormat("{0} file system", HighSierra ? "High Sierra Format" : "ISO9660").AppendLine(); + if(XA) + ISOMetadata.AppendLine("CD-ROM XA extensions present."); if(jolietvd != null) - ISOMetadata.AppendFormat("Joliet extensions present.").AppendLine(); + ISOMetadata.AppendLine("Joliet extensions present."); if(RockRidge) - ISOMetadata.AppendFormat("Rock Ridge Interchange Protocol present.").AppendLine(); + ISOMetadata.AppendLine("Rock Ridge Interchange Protocol present."); if(bvd != null) ISOMetadata.AppendFormat("Disc bootable following {0} specifications.", BootSpec).AppendLine(); if(SegaCD != null) diff --git a/DiscImageChef.Filesystems/ISO9660/Structs.cs b/DiscImageChef.Filesystems/ISO9660/Structs.cs index ba378540a..1460027b6 100644 --- a/DiscImageChef.Filesystems/ISO9660/Structs.cs +++ b/DiscImageChef.Filesystems/ISO9660/Structs.cs @@ -234,6 +234,7 @@ namespace DiscImageChef.Filesystems.ISO9660 public ushort volume_sequence_number; public ushort volume_sequence_number_be; public byte name_len; + // Followed by name[name_len] and then system area until length arrives } [StructLayout(LayoutKind.Sequential, Pack = 1)] @@ -254,6 +255,7 @@ namespace DiscImageChef.Filesystems.ISO9660 public ushort volume_sequence_number; public ushort volume_sequence_number_be; public byte name_len; + // Followed by name[name_len] and then system area until length arrives } [StructLayout(LayoutKind.Sequential, Pack = 1)] @@ -348,6 +350,18 @@ namespace DiscImageChef.Filesystems.ISO9660 public byte[] selection_criterias; } + // Big-endian + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct CdromXa + { + public ushort group; + public ushort user; + public XaAttributes attributes; + public ushort signature; + public byte filenumber; + public byte[] reserved; + } + struct DecodedVolumeDescriptor { public string SystemIdentifier;