mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
Added support for SUSP extensions to ISO9660.
This commit is contained in:
@@ -42,6 +42,13 @@ namespace DiscImageChef.Filesystems.ISO9660
|
|||||||
const ushort XaMagic = 0x5841; // "XA"
|
const ushort XaMagic = 0x5841; // "XA"
|
||||||
const ushort AppleMagic = 0x4141; // "AA"
|
const ushort AppleMagic = 0x4141; // "AA"
|
||||||
const ushort AppleMagicOld = 0x4241; // "BA"
|
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]
|
[Flags]
|
||||||
enum FileFlags : byte
|
enum FileFlags : byte
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
// Copyright © 2011-2017 Natalia Portillo
|
// Copyright © 2011-2017 Natalia Portillo
|
||||||
// ****************************************************************************/
|
// ****************************************************************************/
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using DiscImageChef.CommonTypes;
|
using DiscImageChef.CommonTypes;
|
||||||
@@ -255,6 +256,10 @@ namespace DiscImageChef.Filesystems.ISO9660
|
|||||||
int rootOff = 0;
|
int rootOff = 0;
|
||||||
bool XA = false;
|
bool XA = false;
|
||||||
bool Apple = 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;
|
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)
|
if(noneFound)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -342,6 +388,61 @@ namespace DiscImageChef.Filesystems.ISO9660
|
|||||||
break;
|
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
|
// TODO: Check this
|
||||||
/*
|
/*
|
||||||
@@ -376,6 +477,8 @@ namespace DiscImageChef.Filesystems.ISO9660
|
|||||||
ISOMetadata.AppendLine("Apple extensions present.");
|
ISOMetadata.AppendLine("Apple extensions present.");
|
||||||
if(jolietvd != null)
|
if(jolietvd != null)
|
||||||
ISOMetadata.AppendLine("Joliet extensions present.");
|
ISOMetadata.AppendLine("Joliet extensions present.");
|
||||||
|
if(SUSP)
|
||||||
|
ISOMetadata.AppendLine("System Use Sharing Protocol present.");
|
||||||
if(RockRidge)
|
if(RockRidge)
|
||||||
ISOMetadata.AppendLine("Rock Ridge Interchange Protocol present.");
|
ISOMetadata.AppendLine("Rock Ridge Interchange Protocol present.");
|
||||||
if(bvd != null)
|
if(bvd != null)
|
||||||
@@ -605,6 +708,9 @@ namespace DiscImageChef.Filesystems.ISO9660
|
|||||||
}
|
}
|
||||||
|
|
||||||
exit_torito:
|
exit_torito:
|
||||||
|
if(refareas.Count > 0)
|
||||||
|
ISOMetadata.Append(suspInformation.ToString());
|
||||||
|
|
||||||
xmlFSType.Type = HighSierra ? "High Sierra Format" : "ISO9660";
|
xmlFSType.Type = HighSierra ? "High Sierra Format" : "ISO9660";
|
||||||
|
|
||||||
if(jolietvd != null)
|
if(jolietvd != null)
|
||||||
|
|||||||
@@ -429,6 +429,70 @@ namespace DiscImageChef.Filesystems.ISO9660
|
|||||||
public ushort finder_flags;
|
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
|
struct DecodedVolumeDescriptor
|
||||||
{
|
{
|
||||||
public string SystemIdentifier;
|
public string SystemIdentifier;
|
||||||
|
|||||||
Reference in New Issue
Block a user