Added support for SUSP extensions to ISO9660.

This commit is contained in:
2017-10-09 11:25:47 +01:00
parent be104ae04a
commit bdc6eda811
3 changed files with 177 additions and 0 deletions

View File

@@ -42,6 +42,13 @@ namespace DiscImageChef.Filesystems.ISO9660
const ushort XaMagic = 0x5841; // "XA"
const ushort AppleMagic = 0x4141; // "AA"
const ushort AppleMagicOld = 0x4241; // "BA"
const ushort SUSP_Continuation = 0x4345; // "CE"
const ushort SUSP_Padding = 0x5044; // "PD"
const ushort SUSP_Indicator = 0x5350; // "SP"
const ushort SUSP_Terminator = 0x5354; // "ST"
const ushort SUSP_Reference = 0x4552; // "ER"
const ushort SUSP_Selector = 0x4553; // "ES"
const ushort SUSP_Magic = 0xBEEF;
[Flags]
enum FileFlags : byte

View File

@@ -30,6 +30,7 @@
// Copyright © 2011-2017 Natalia Portillo
// ****************************************************************************/
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using DiscImageChef.CommonTypes;
@@ -255,6 +256,10 @@ namespace DiscImageChef.Filesystems.ISO9660
int rootOff = 0;
bool XA = false;
bool Apple = false;
bool SUSP = false;
List<ContinuationArea> contareas = new List<ContinuationArea>();
List<byte[]> refareas = new List<byte[]>();
StringBuilder suspInformation = new StringBuilder();
BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;
@@ -331,6 +336,47 @@ namespace DiscImageChef.Filesystems.ISO9660
}
}
// IEEE-P1281 aka SUSP 1.12
if(nextSignature == SUSP_Indicator)
{
SUSP = true;
sa_off += sa[sa_off + 2];
noneFound = false;
while(sa_off < sa_len)
{
nextSignature = BigEndianBitConverter.ToUInt16(sa, sa_off);
if(nextSignature == AppleMagic)
{
// Can collide with AAIP
if(sa[sa_off + 3] == 1 && sa[sa_off + 2] == 7)
Apple = true;
else Apple |= sa[sa_off + 3] != 1;
}
if(nextSignature == SUSP_Continuation && sa_off + sa[sa_off + 2] <= sa_len)
{
byte[] ce = new byte[sa[sa_off + 2]];
Array.Copy(sa, sa_off, ce, 0, ce.Length);
ContinuationArea ca = BigEndianMarshal.ByteArrayToStructureBigEndian<ContinuationArea>(ce);
contareas.Add(ca);
}
if(nextSignature == SUSP_Reference && sa_off + sa[sa_off + 2] <= sa_len)
{
byte[] er = new byte[sa[sa_off + 2]];
Array.Copy(sa, sa_off, er, 0, er.Length);
refareas.Add(er);
}
sa_off += sa[sa_off + 2];
if(nextSignature == SUSP_Terminator)
break;
}
}
if(noneFound)
break;
}
@@ -342,6 +388,61 @@ namespace DiscImageChef.Filesystems.ISO9660
break;
}
foreach(ContinuationArea ca in contareas)
{
uint ca_len = (ca.ca_length_be + ca.offset_be) / (HighSierra ? hsvd.Value.logical_block_size : pvd.Value.logical_block_size);
if((ca.ca_length_be + ca.offset_be) % (HighSierra ? hsvd.Value.logical_block_size : pvd.Value.logical_block_size) > 0)
ca_len++;
byte[] ca_sectors = imagePlugin.ReadSectors(ca.block_be, ca_len);
byte[] ca_data = new byte[ca.ca_length_be];
Array.Copy(ca_sectors, ca.offset_be, ca_data, 0, ca.ca_length_be);
int ca_off = 0;
while(ca_off < ca.ca_length_be)
{
ushort nextSignature = BigEndianBitConverter.ToUInt16(ca_data, ca_off);
// Apple never said to include its extensions inside a continuation area, but just in case
if(nextSignature == AppleMagic)
{
// Can collide with AAIP
if(ca_data[ca_off + 3] == 1 && ca_data[ca_off + 2] == 7)
Apple = true;
else Apple |= ca_data[ca_off + 3] != 1;
}
if(nextSignature == SUSP_Reference && ca_off + ca_data[ca_off + 2] <= ca.ca_length_be)
{
byte[] er = new byte[ca_data[ca_off + 2]];
Array.Copy(ca_data, ca_off, er, 0, er.Length);
refareas.Add(er);
}
ca_off += ca_data[ca_off + 2];
}
}
if(refareas.Count > 0)
{
suspInformation.AppendLine("----------------------------------------");
suspInformation.AppendLine("SYSTEM USE SHARING PROTOCOL INFORMATION:");
suspInformation.AppendLine("----------------------------------------");
counter = 1;
foreach(byte[] erb in refareas)
{
ReferenceArea er = BigEndianMarshal.ByteArrayToStructureBigEndian<ReferenceArea>(erb);
string ext_id = CurrentEncoding.GetString(erb, Marshal.SizeOf(er), er.id_len);
string ext_des = CurrentEncoding.GetString(erb, Marshal.SizeOf(er) + er.id_len, er.des_len);
string ext_src = CurrentEncoding.GetString(erb, Marshal.SizeOf(er) + er.id_len + er.des_len, er.src_len);
suspInformation.AppendFormat("Extension: {0}", counter).AppendLine();
suspInformation.AppendFormat("\tID: {0}, version {1}", ext_id, er.ext_ver).AppendLine();
suspInformation.AppendFormat("\tDescription: {0}", ext_des).AppendLine();
suspInformation.AppendFormat("\tSource: {0}", ext_src).AppendLine();
counter++;
}
}
// TODO: Check this
/*
@@ -376,6 +477,8 @@ namespace DiscImageChef.Filesystems.ISO9660
ISOMetadata.AppendLine("Apple extensions present.");
if(jolietvd != null)
ISOMetadata.AppendLine("Joliet extensions present.");
if(SUSP)
ISOMetadata.AppendLine("System Use Sharing Protocol present.");
if(RockRidge)
ISOMetadata.AppendLine("Rock Ridge Interchange Protocol present.");
if(bvd != null)
@@ -605,6 +708,9 @@ namespace DiscImageChef.Filesystems.ISO9660
}
exit_torito:
if(refareas.Count > 0)
ISOMetadata.Append(suspInformation.ToString());
xmlFSType.Type = HighSierra ? "High Sierra Format" : "ISO9660";
if(jolietvd != null)

View File

@@ -429,6 +429,70 @@ namespace DiscImageChef.Filesystems.ISO9660
public ushort finder_flags;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct ContinuationArea
{
public ushort signature;
public byte length;
public byte version;
public uint block;
public uint block_be;
public uint offset;
public uint offset_be;
public uint ca_length;
public uint ca_length_be;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct PaddingArea
{
public ushort signature;
public byte length;
public byte version;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct IndicatorArea
{
public ushort signature;
public byte length;
public byte version;
public ushort magic;
public byte skipped;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct TerminatorArea
{
public ushort signature;
public byte length;
public byte version;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct ReferenceArea
{
public ushort signature;
public byte length;
public byte version;
public byte id_len;
public byte des_len;
public byte src_len;
public byte ext_ver;
// Follows extension identifier for id_len bytes
// Follows extension descriptor for des_len bytes
// Follows extension source for src_len bytes
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct SelectorArea
{
public ushort signature;
public byte length;
public byte version;
public byte sequence;
}
struct DecodedVolumeDescriptor
{
public string SystemIdentifier;