From a02ef2c4d621fcfb1f1b3064c3ddc72193e0b197 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Mon, 9 Oct 2017 12:07:48 +0100 Subject: [PATCH] Added support for RRIP extensions to ISO9660. --- DiscImageChef.Filesystems/ISO9660/Consts.cs | 73 ++++++++++++ DiscImageChef.Filesystems/ISO9660/Info.cs | 37 +++--- DiscImageChef.Filesystems/ISO9660/Structs.cs | 116 +++++++++++++++++++ 3 files changed, 203 insertions(+), 23 deletions(-) diff --git a/DiscImageChef.Filesystems/ISO9660/Consts.cs b/DiscImageChef.Filesystems/ISO9660/Consts.cs index fb653779e..ac381cd07 100644 --- a/DiscImageChef.Filesystems/ISO9660/Consts.cs +++ b/DiscImageChef.Filesystems/ISO9660/Consts.cs @@ -49,6 +49,16 @@ namespace DiscImageChef.Filesystems.ISO9660 const ushort SUSP_Reference = 0x4552; // "ER" const ushort SUSP_Selector = 0x4553; // "ES" const ushort SUSP_Magic = 0xBEEF; + const ushort RRIP_Magic = 0x5252; // "RR" + const ushort RRIP_PosixAttributes = 0x5058; // "PX" + const ushort RRIP_PosixDevNo = 0x504E; // "PN" + const ushort RRIP_Symlink = 0x534C; // "SL" + const ushort RRIP_Name = 0x4E4D; // "NM" + const ushort RRIP_Childlink = 0x434C; // "CL" + const ushort RRIP_Parentlink = 0x504C; // "PL" + const ushort RRIP_RelocatedDir = 0x5245; // "RE" + const ushort RRIP_Timestamps = 0x5446; // "TF" + const ushort RRIP_Sparse = 0x5346; // "SF" [Flags] enum FileFlags : byte @@ -155,5 +165,68 @@ namespace DiscImageChef.Filesystems.ISO9660 TypeCreatorIconBundle = 5, HFS = 6 } + + [Flags] + enum PosixMode : uint + { + OwnerRead = 0x100, + OwnerWrite = 0x80, + OwnerExecute = 0x40, + GroupRead = 0x20, + GroupWrite = 0x10, + GroupExecute = 0x8, + OtherRead = 0x4, + OtherWrite = 0x2, + OtherExecute = 0x1, + SetUID = 0x800, + SetGid = 0x400, + IsVTX = 0x200, + Socket = 0xC000, + Symlink = 0xA000, + Regular = 0x8000, + Block = 0x6000, + Character = 0x2000, + Directory = 0x4000, + Pipe = 0x1000 + } + + [Flags] + enum SymlinkFlags : byte + { + Continue = 1 + } + + [Flags] + enum SymlinkComponentFlags : byte + { + Continue = 1, + Current = 2, + Parent = 4, + Root = 8, + Mountpoint = 16, + Networkname = 32 + } + + [Flags] + enum AlternateNameFlags : byte + { + Continue = 1, + Current = 2, + Parent = 4, + Networkname = 32 + } + + [Flags] + enum TimestampFlags : byte + { + Creation = 1 << 0, + Modification = 1 << 1, + Access = 1 << 2, + AttributeChange = 1 << 3, + Backup = 1 << 4, + Expiration = 1 << 5, + Effective = 1 << 6, + LongFormat = 1 << 7, + } } } diff --git a/DiscImageChef.Filesystems/ISO9660/Info.cs b/DiscImageChef.Filesystems/ISO9660/Info.cs index f528fa253..2dbb4625c 100644 --- a/DiscImageChef.Filesystems/ISO9660/Info.cs +++ b/DiscImageChef.Filesystems/ISO9660/Info.cs @@ -80,7 +80,6 @@ namespace DiscImageChef.Filesystems.ISO9660 { information = ""; StringBuilder ISOMetadata = new StringBuilder(); - bool RockRidge = false; byte VDType; // Volume Descriptor Type, should be 1 or 2. byte[] VDMagic = new byte[5]; // Volume Descriptor magic "CD001" byte[] HSMagic = new byte[5]; // Volume Descriptor magic "CDROM" @@ -257,6 +256,7 @@ namespace DiscImageChef.Filesystems.ISO9660 bool XA = false; bool Apple = false; bool SUSP = false; + bool RRIP = false; List contareas = new List(); List refareas = new List(); StringBuilder suspInformation = new StringBuilder(); @@ -370,6 +370,12 @@ namespace DiscImageChef.Filesystems.ISO9660 refareas.Add(er); } + RRIP |= nextSignature == RRIP_Magic || nextSignature == RRIP_PosixAttributes || + nextSignature == RRIP_PosixDevNo || nextSignature == RRIP_Symlink || + nextSignature == RRIP_Name || nextSignature == RRIP_Childlink || + nextSignature == RRIP_Parentlink || nextSignature == RRIP_RelocatedDir || + nextSignature == RRIP_Timestamps || nextSignature == RRIP_Sparse; + sa_off += sa[sa_off + 2]; if(nextSignature == SUSP_Terminator) @@ -419,6 +425,12 @@ namespace DiscImageChef.Filesystems.ISO9660 refareas.Add(er); } + RRIP |= nextSignature == RRIP_Magic || nextSignature == RRIP_PosixAttributes || + nextSignature == RRIP_PosixDevNo || nextSignature == RRIP_Symlink || + nextSignature == RRIP_Name || nextSignature == RRIP_Childlink || + nextSignature == RRIP_Parentlink || nextSignature == RRIP_RelocatedDir || + nextSignature == RRIP_Timestamps || nextSignature == RRIP_Sparse; + ca_off += ca_data[ca_off + 2]; } } @@ -444,27 +456,6 @@ namespace DiscImageChef.Filesystems.ISO9660 } } - // TODO: Check this - /* - if((i + partition.Start) < partition.End) - { - - byte[] path_table = imagePlugin.ReadSector(i + partition.Start); - Array.Copy(path_table, 2, RootDirectoryLocation, 0, 4); - // Check for Rock Ridge - byte[] root_dir = imagePlugin.ReadSector((ulong)BitConverter.ToInt32(RootDirectoryLocation, 0) + partition.Start); - - byte[] SUSPMagic = new byte[2]; - byte[] RRMagic = new byte[2]; - - Array.Copy(root_dir, 0x22, SUSPMagic, 0, 2); - if(CurrentEncoding.GetString(SUSPMagic) == "SP") - { - Array.Copy(root_dir, 0x29, RRMagic, 0, 2); - RockRidge |= CurrentEncoding.GetString(RRMagic) == "RR"; - } - }*/ - byte[] ipbin_sector = imagePlugin.ReadSector(0 + partition.Start); Decoders.Sega.CD.IPBin? SegaCD = Decoders.Sega.CD.DecodeIPBin(ipbin_sector); Decoders.Sega.Saturn.IPBin? Saturn = Decoders.Sega.Saturn.DecodeIPBin(ipbin_sector); @@ -479,7 +470,7 @@ namespace DiscImageChef.Filesystems.ISO9660 ISOMetadata.AppendLine("Joliet extensions present."); if(SUSP) ISOMetadata.AppendLine("System Use Sharing Protocol present."); - if(RockRidge) + if(RRIP) ISOMetadata.AppendLine("Rock Ridge Interchange Protocol present."); if(bvd != null) ISOMetadata.AppendFormat("Disc bootable following {0} specifications.", BootSpec).AppendLine(); diff --git a/DiscImageChef.Filesystems/ISO9660/Structs.cs b/DiscImageChef.Filesystems/ISO9660/Structs.cs index 6c7896587..26239d51e 100644 --- a/DiscImageChef.Filesystems/ISO9660/Structs.cs +++ b/DiscImageChef.Filesystems/ISO9660/Structs.cs @@ -493,6 +493,122 @@ namespace DiscImageChef.Filesystems.ISO9660 public byte sequence; } + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct PosixAttributes + { + public ushort signature; + public byte length; + public byte version; + public PosixMode st_mode; + public PosixMode st_mode_be; + public uint st_nlink; + public uint st_nlink_be; + public uint st_uid; + public uint st_uid_be; + public uint st_gid; + public uint st_gid_be; + public uint st_ino; + public uint st_ino_be; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct PosixDeviceNumber + { + public ushort signature; + public byte length; + public byte version; + public uint dev_t_high; + public uint dev_t_high_be; + public uint dev_t_low; + public uint dev_t_low_be; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct SymbolicLink + { + public ushort signature; + public byte length; + public byte version; + public SymlinkFlags flags; + // Followed by SymbolicLinkComponent (link to /bar/foo uses at least two of these structs) + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct SymbolicLinkComponent + { + public SymlinkComponentFlags flags; + public byte length; + // Followed by component content + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct AlternateName + { + public ushort signature; + public byte length; + public byte version; + public AlternateNameFlags flags; + // Folowed by name, can be divided in pieces + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct ChildLink + { + public ushort signature; + public byte length; + public byte version; + public uint child_dir_lba; + public uint child_dir_lba_be; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct ParentLink + { + public ushort signature; + public byte length; + public byte version; + public uint parent_dir_lba; + public uint parent_dir_lba_be; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct RelocatedDirectory + { + public ushort signature; + public byte length; + public byte version; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct Timestamps + { + public ushort signature; + public byte length; + public byte version; + public TimestampFlags flags; + // If flags indicate long format, timestamps are 17 bytes, if not, 7 bytes + // Followed by creation time if present + // Followed by modification time if present + // Followed by access time if present + // Followed by attribute change time if present + // Followed by backup time if present + // Followed by expiration time if present + // Followed by effective time if present + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct SparseFile + { + public ushort signature; + public byte length; + public byte version; + public uint virtual_size_high; + public uint virtual_size_high_be; + public uint virtual_size_low; + public uint virtual_size_low_be; + public byte table_depth; + } + struct DecodedVolumeDescriptor { public string SystemIdentifier;