Use marshalling.

This commit is contained in:
2017-07-23 21:01:26 +01:00
parent dddf884c05
commit 332c2901fd
5 changed files with 95 additions and 158 deletions

View File

@@ -32,6 +32,7 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using DiscImageChef.CommonTypes;
@@ -113,12 +114,12 @@ namespace DiscImageChef.Filesystems
byte[] sb_sector = imagePlugin.ReadSector(0 + partition.Start);
BigEndianBitConverter.IsLittleEndian = true; // Default for little-endian
bool littleEndian = true;
besb.magic1 = BigEndianBitConverter.ToUInt32(sb_sector, 0x20);
if(besb.magic1 == BEFS_MAGIC1 || besb.magic1 == BEFS_CIGAM1) // Magic is at offset
{
BigEndianBitConverter.IsLittleEndian &= besb.magic1 != BEFS_CIGAM1;
littleEndian = besb.magic1 == BEFS_CIGAM1;
}
else
{
@@ -127,7 +128,7 @@ namespace DiscImageChef.Filesystems
if(besb.magic1 == BEFS_MAGIC1 || besb.magic1 == BEFS_CIGAM1) // There is a boot sector
{
BigEndianBitConverter.IsLittleEndian &= besb.magic1 != BEFS_CIGAM1;
littleEndian = besb.magic1 == BEFS_CIGAM1;
}
else if(sb_sector.Length >= 0x400)
{
@@ -136,7 +137,7 @@ namespace DiscImageChef.Filesystems
if(besb.magic1 == BEFS_MAGIC1 || besb.magic1 == BEFS_CIGAM1) // There is a boot sector
{
BigEndianBitConverter.IsLittleEndian &= besb.magic1 != BEFS_CIGAM1;
littleEndian = besb.magic1 == BEFS_CIGAM1;
sb_sector = new byte[0x200];
Array.Copy(temp, 0x200, sb_sector, 0, 0x200);
}
@@ -147,34 +148,16 @@ namespace DiscImageChef.Filesystems
return;
}
Array.Copy(sb_sector, 0x000, name_bytes, 0, 0x20);
besb.name = StringHandlers.CToString(name_bytes, CurrentEncoding);
besb.magic1 = BigEndianBitConverter.ToUInt32(sb_sector, 0x20);
besb.fs_byte_order = BigEndianBitConverter.ToUInt32(sb_sector, 0x24);
besb.block_size = BigEndianBitConverter.ToUInt32(sb_sector, 0x28);
besb.block_shift = BigEndianBitConverter.ToUInt32(sb_sector, 0x2C);
besb.num_blocks = BigEndianBitConverter.ToInt64(sb_sector, 0x30);
besb.used_blocks = BigEndianBitConverter.ToInt64(sb_sector, 0x38);
besb.inode_size = BigEndianBitConverter.ToInt32(sb_sector, 0x40);
besb.magic2 = BigEndianBitConverter.ToUInt32(sb_sector, 0x44);
besb.blocks_per_ag = BigEndianBitConverter.ToInt32(sb_sector, 0x48);
besb.ag_shift = BigEndianBitConverter.ToInt32(sb_sector, 0x4C);
besb.num_ags = BigEndianBitConverter.ToInt32(sb_sector, 0x50);
besb.flags = BigEndianBitConverter.ToUInt32(sb_sector, 0x54);
besb.log_blocks_ag = BigEndianBitConverter.ToInt32(sb_sector, 0x58);
besb.log_blocks_start = BigEndianBitConverter.ToUInt16(sb_sector, 0x5C);
besb.log_blocks_len = BigEndianBitConverter.ToUInt16(sb_sector, 0x5E);
besb.log_start = BigEndianBitConverter.ToInt64(sb_sector, 0x60);
besb.log_end = BigEndianBitConverter.ToInt64(sb_sector, 0x68);
besb.magic3 = BigEndianBitConverter.ToUInt32(sb_sector, 0x70);
besb.root_dir_ag = BigEndianBitConverter.ToInt32(sb_sector, 0x74);
besb.root_dir_start = BigEndianBitConverter.ToUInt16(sb_sector, 0x78);
besb.root_dir_len = BigEndianBitConverter.ToUInt16(sb_sector, 0x7A);
besb.indices_ag = BigEndianBitConverter.ToInt32(sb_sector, 0x7C);
besb.indices_start = BigEndianBitConverter.ToUInt16(sb_sector, 0x80);
besb.indices_len = BigEndianBitConverter.ToUInt16(sb_sector, 0x82);
if(littleEndian)
{
GCHandle handle = GCHandle.Alloc(sb_sector, GCHandleType.Pinned);
besb = (BeSuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(BeSuperBlock));
handle.Free();
}
else
besb = BigEndianMarshal.ByteArrayToStructureBigEndian<BeSuperBlock>(sb_sector);
if(!BigEndianBitConverter.IsLittleEndian) // Big-endian filesystem
if(littleEndian) // Big-endian filesystem
sb.AppendLine("Little-endian BeFS");
else
sb.AppendLine("Big-endian BeFS");
@@ -207,7 +190,7 @@ namespace DiscImageChef.Filesystems
else
sb.AppendFormat("Unknown flags: {0:X8}", besb.flags).AppendLine();
sb.AppendFormat("Volume name: {0}", besb.name).AppendLine();
sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(besb.name, CurrentEncoding)).AppendLine();
sb.AppendFormat("{0} bytes per block", besb.block_size).AppendLine();
sb.AppendFormat("{0} blocks in volume ({1} bytes)", besb.num_blocks, besb.num_blocks * besb.block_size).AppendLine();
sb.AppendFormat("{0} used blocks ({1} bytes)", besb.used_blocks, besb.used_blocks * besb.block_size).AppendLine();
@@ -231,16 +214,18 @@ namespace DiscImageChef.Filesystems
xmlFSType.FreeClusters = besb.num_blocks - besb.used_blocks;
xmlFSType.FreeClustersSpecified = true;
xmlFSType.Type = "BeFS";
xmlFSType.VolumeName = besb.name;
xmlFSType.VolumeName = StringHandlers.CToString(besb.name, CurrentEncoding);
}
/// <summary>
/// Be superblock
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct BeSuperBlock
{
/// <summary>0x000, Volume name, 32 bytes</summary>
public string name;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public byte[] name;
/// <summary>0x020, "BFS1", 0x42465331</summary>
public uint magic1;
/// <summary>0x024, "BIGE", 0x42494745</summary>

View File

@@ -144,7 +144,6 @@ namespace DiscImageChef.Filesystems
}
catch
{
System.Console.WriteLine("Crash");
return false;
}

View File

@@ -32,6 +32,7 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using DiscImageChef.CommonTypes;
@@ -113,11 +114,13 @@ namespace DiscImageChef.Filesystems
xmlFSType = new Schemas.FileSystemType();
bool littleEndian = true;
if(magic == MINIX3_MAGIC || magic == MINIX3_CIGAM)
{
filenamesize = 60;
minixVersion = "Minix V3 filesystem";
BigEndianBitConverter.IsLittleEndian = magic != MINIX3_CIGAM;
littleEndian = magic != MINIX3_CIGAM;
xmlFSType.Type = "Minix V3";
@@ -132,49 +135,49 @@ namespace DiscImageChef.Filesystems
case MINIX_MAGIC:
filenamesize = 14;
minixVersion = "Minix V1 filesystem";
BigEndianBitConverter.IsLittleEndian = true;
littleEndian = true;
xmlFSType.Type = "Minix V1";
break;
case MINIX_MAGIC2:
filenamesize = 30;
minixVersion = "Minix V1 filesystem";
BigEndianBitConverter.IsLittleEndian = true;
littleEndian = true;
xmlFSType.Type = "Minix V1";
break;
case MINIX2_MAGIC:
filenamesize = 14;
minixVersion = "Minix V2 filesystem";
BigEndianBitConverter.IsLittleEndian = true;
littleEndian = true;
xmlFSType.Type = "Minix V2";
break;
case MINIX2_MAGIC2:
filenamesize = 30;
minixVersion = "Minix V2 filesystem";
BigEndianBitConverter.IsLittleEndian = true;
littleEndian = true;
xmlFSType.Type = "Minix V2";
break;
case MINIX_CIGAM:
filenamesize = 14;
minixVersion = "Minix V1 filesystem";
BigEndianBitConverter.IsLittleEndian = false;
littleEndian = false;
xmlFSType.Type = "Minix V1";
break;
case MINIX_CIGAM2:
filenamesize = 30;
minixVersion = "Minix V1 filesystem";
BigEndianBitConverter.IsLittleEndian = false;
littleEndian = false;
xmlFSType.Type = "Minix V1";
break;
case MINIX2_CIGAM:
filenamesize = 14;
minixVersion = "Minix V2 filesystem";
BigEndianBitConverter.IsLittleEndian = false;
littleEndian = false;
xmlFSType.Type = "Minix V2";
break;
case MINIX2_CIGAM2:
filenamesize = 30;
minixVersion = "Minix V2 filesystem";
BigEndianBitConverter.IsLittleEndian = false;
littleEndian = false;
xmlFSType.Type = "Minix V2";
break;
default:
@@ -186,19 +189,14 @@ namespace DiscImageChef.Filesystems
{
Minix3SuperBlock mnx_sb = new Minix3SuperBlock();
mnx_sb.s_ninodes = BigEndianBitConverter.ToUInt32(minix_sb_sector, 0x00);
mnx_sb.s_pad0 = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x04);
mnx_sb.s_imap_blocks = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x06);
mnx_sb.s_zmap_blocks = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x08);
mnx_sb.s_firstdatazone = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x0A);
mnx_sb.s_log_zone_size = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x0C);
mnx_sb.s_pad1 = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x0E);
mnx_sb.s_max_size = BigEndianBitConverter.ToUInt32(minix_sb_sector, 0x10);
mnx_sb.s_zones = BigEndianBitConverter.ToUInt32(minix_sb_sector, 0x14);
mnx_sb.s_magic = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x18);
mnx_sb.s_pad2 = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x1A);
mnx_sb.s_blocksize = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x1C);
mnx_sb.s_disk_version = minix_sb_sector[0x1E];
if(littleEndian)
{
GCHandle handle = GCHandle.Alloc(minix_sb_sector, GCHandleType.Pinned);
mnx_sb = (Minix3SuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(Minix3SuperBlock));
handle.Free();
}
else
mnx_sb = BigEndianMarshal.ByteArrayToStructureBigEndian<Minix3SuperBlock>(minix_sb_sector);
sb.AppendLine(minixVersion);
sb.AppendFormat("{0} chars in filename", filenamesize).AppendLine();
@@ -219,16 +217,14 @@ namespace DiscImageChef.Filesystems
{
MinixSuperBlock mnx_sb = new MinixSuperBlock();
mnx_sb.s_ninodes = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x00);
mnx_sb.s_nzones = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x02);
mnx_sb.s_imap_blocks = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x04);
mnx_sb.s_zmap_blocks = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x06);
mnx_sb.s_firstdatazone = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x08);
mnx_sb.s_log_zone_size = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x0A);
mnx_sb.s_max_size = BigEndianBitConverter.ToUInt32(minix_sb_sector, 0x0C);
mnx_sb.s_magic = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x10);
mnx_sb.s_state = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x12);
mnx_sb.s_zones = BigEndianBitConverter.ToUInt32(minix_sb_sector, 0x14);
if(littleEndian)
{
GCHandle handle = GCHandle.Alloc(minix_sb_sector, GCHandleType.Pinned);
mnx_sb = (MinixSuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(MinixSuperBlock));
handle.Free();
}
else
mnx_sb = BigEndianMarshal.ByteArrayToStructureBigEndian<MinixSuperBlock>(minix_sb_sector);
sb.AppendLine(minixVersion);
sb.AppendFormat("{0} chars in filename", filenamesize).AppendLine();
@@ -252,6 +248,7 @@ namespace DiscImageChef.Filesystems
/// <summary>
/// Superblock for Minix V1 and V2 filesystems
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct MinixSuperBlock
{
/// <summary>0x00, inodes on volume</summary>
@@ -279,6 +276,7 @@ namespace DiscImageChef.Filesystems
/// <summary>
/// Superblock for Minix V3 filesystems
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct Minix3SuperBlock
{
/// <summary>0x00, inodes on volume</summary>

View File

@@ -32,6 +32,7 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using DiscImageChef.CommonTypes;
@@ -93,56 +94,12 @@ namespace DiscImageChef.Filesystems
byte[] hb_sector = imagePlugin.ReadSector(1 + partition.Start);
homeblock.homelbn = BitConverter.ToUInt32(hb_sector, 0x000);
homeblock.alhomelbn = BitConverter.ToUInt32(hb_sector, 0x004);
homeblock.altidxlbn = BitConverter.ToUInt32(hb_sector, 0x008);
homeblock.struclev = BitConverter.ToUInt16(hb_sector, 0x00C);
homeblock.cluster = BitConverter.ToUInt16(hb_sector, 0x00E);
homeblock.homevbn = BitConverter.ToUInt16(hb_sector, 0x010);
homeblock.alhomevbn = BitConverter.ToUInt16(hb_sector, 0x012);
homeblock.altidxvbn = BitConverter.ToUInt16(hb_sector, 0x014);
homeblock.ibmapvbn = BitConverter.ToUInt16(hb_sector, 0x016);
homeblock.ibmaplbn = BitConverter.ToUInt32(hb_sector, 0x018);
homeblock.maxfiles = BitConverter.ToUInt32(hb_sector, 0x01C);
homeblock.ibmapsize = BitConverter.ToUInt16(hb_sector, 0x020);
homeblock.resfiles = BitConverter.ToUInt16(hb_sector, 0x022);
homeblock.devtype = BitConverter.ToUInt16(hb_sector, 0x024);
homeblock.rvn = BitConverter.ToUInt16(hb_sector, 0x026);
homeblock.setcount = BitConverter.ToUInt16(hb_sector, 0x028);
homeblock.volchar = BitConverter.ToUInt16(hb_sector, 0x02A);
homeblock.volowner = BitConverter.ToUInt32(hb_sector, 0x02C);
homeblock.sec_mask = BitConverter.ToUInt32(hb_sector, 0x030);
homeblock.protect = BitConverter.ToUInt16(hb_sector, 0x034);
homeblock.fileprot = BitConverter.ToUInt16(hb_sector, 0x036);
homeblock.recprot = BitConverter.ToUInt16(hb_sector, 0x038);
homeblock.checksum1 = BitConverter.ToUInt16(hb_sector, 0x03A);
homeblock.credate = BitConverter.ToUInt64(hb_sector, 0x03C);
homeblock.window = hb_sector[0x044];
homeblock.lru_lim = hb_sector[0x045];
homeblock.extend = BitConverter.ToUInt16(hb_sector, 0x046);
homeblock.retainmin = BitConverter.ToUInt64(hb_sector, 0x048);
homeblock.retainmax = BitConverter.ToUInt64(hb_sector, 0x050);
homeblock.revdate = BitConverter.ToUInt64(hb_sector, 0x058);
Array.Copy(hb_sector, 0x060, homeblock.min_class, 0, 20);
Array.Copy(hb_sector, 0x074, homeblock.max_class, 0, 20);
homeblock.filetab_fid1 = BitConverter.ToUInt16(hb_sector, 0x088);
homeblock.filetab_fid2 = BitConverter.ToUInt16(hb_sector, 0x08A);
homeblock.filetab_fid3 = BitConverter.ToUInt16(hb_sector, 0x08C);
homeblock.lowstruclev = BitConverter.ToUInt16(hb_sector, 0x08E);
homeblock.highstruclev = BitConverter.ToUInt16(hb_sector, 0x090);
homeblock.copydate = BitConverter.ToUInt64(hb_sector, 0x092);
homeblock.serialnum = BitConverter.ToUInt32(hb_sector, 0x1C8);
Array.Copy(hb_sector, 0x1CC, temp_string, 0, 12);
homeblock.strucname = StringHandlers.CToString(temp_string, CurrentEncoding);
Array.Copy(hb_sector, 0x1D8, temp_string, 0, 12);
homeblock.volname = StringHandlers.CToString(temp_string, CurrentEncoding);
Array.Copy(hb_sector, 0x1E4, temp_string, 0, 12);
homeblock.ownername = StringHandlers.CToString(temp_string, CurrentEncoding);
Array.Copy(hb_sector, 0x1F0, temp_string, 0, 12);
homeblock.format = StringHandlers.CToString(temp_string, CurrentEncoding);
homeblock.checksum2 = BitConverter.ToUInt16(hb_sector, 0x1FE);
GCHandle handle = GCHandle.Alloc(hb_sector, GCHandleType.Pinned);
homeblock = (ODSHomeBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(ODSHomeBlock));
handle.Free();
if((homeblock.struclev & 0xFF00) != 0x0200 || (homeblock.struclev & 0xFF) != 1 || homeblock.format != "DECFILE11B ")
if((homeblock.struclev & 0xFF00) != 0x0200 || (homeblock.struclev & 0xFF) != 1 || StringHandlers.CToString(homeblock.format) != "DECFILE11B ")
sb.AppendLine("The following information may be incorrect for this volume.");
if(homeblock.resfiles < 5 || homeblock.devtype != 0)
sb.AppendLine("This volume may be corrupted.");
@@ -159,7 +116,7 @@ namespace DiscImageChef.Filesystems
sb.AppendFormat("Backup INDEXF.SYS;1 is in sector {0} (cluster {1})", homeblock.altidxlbn, homeblock.altidxvbn).AppendLine();
sb.AppendFormat("{0} maximum files on the volume", homeblock.maxfiles).AppendLine();
sb.AppendFormat("{0} reserved files", homeblock.resfiles).AppendLine();
if(homeblock.rvn > 0 && homeblock.setcount > 0 && homeblock.strucname != " ")
if(homeblock.rvn > 0 && homeblock.setcount > 0 && StringHandlers.CToString(homeblock.strucname) != " ")
sb.AppendFormat("Volume is {0} of {1} in set \"{2}\".", homeblock.rvn, homeblock.setcount, homeblock.strucname).AppendLine();
sb.AppendFormat("Volume owner is \"{0}\" (ID 0x{1:X8})", homeblock.ownername, homeblock.volowner).AppendLine();
sb.AppendFormat("Volume label: \"{0}\"", homeblock.volname).AppendLine();
@@ -262,12 +219,14 @@ namespace DiscImageChef.Filesystems
sb.AppendFormat("File protection: 0x{0:X4}", homeblock.fileprot).AppendLine();
sb.AppendFormat("Record protection: 0x{0:X4}", homeblock.recprot).AppendLine();
xmlFSType = new Schemas.FileSystemType();
xmlFSType.Type = "FILES-11";
xmlFSType.ClusterSize = homeblock.cluster * 512;
xmlFSType.Clusters = homeblock.cluster;
xmlFSType.VolumeName = homeblock.volname;
xmlFSType.VolumeSerial = string.Format("{0:X8}", homeblock.serialnum);
xmlFSType = new Schemas.FileSystemType
{
Type = "FILES-11",
ClusterSize = homeblock.cluster * 512,
Clusters = homeblock.cluster,
VolumeName = StringHandlers.CToString(homeblock.volname, CurrentEncoding),
VolumeSerial = string.Format("{0:X8}", homeblock.serialnum)
};
if(homeblock.credate > 0)
{
xmlFSType.CreationDate = DateHandlers.VMSToDateTime(homeblock.credate);
@@ -282,6 +241,7 @@ namespace DiscImageChef.Filesystems
information = sb.ToString();
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct ODSHomeBlock
{
/// <summary>0x000, LBN of THIS home block</summary>
@@ -345,8 +305,10 @@ namespace DiscImageChef.Filesystems
/// <summary>0x058, Last modification date</summary>
public ulong revdate;
/// <summary>0x060, Minimum security class, 20 bytes</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
public byte[] min_class;
/// <summary>0x074, Maximum security class, 20 bytes</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
public byte[] max_class;
/// <summary>0x088, File lookup table FID</summary>
public ushort filetab_fid1;
@@ -361,17 +323,22 @@ namespace DiscImageChef.Filesystems
/// <summary>0x092, Volume copy date (??)</summary>
public ulong copydate;
/// <summary>0x09A, 302 bytes</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 302)]
public byte[] reserved1;
/// <summary>0x1C8, Physical drive serial number</summary>
public uint serialnum;
/// <summary>0x1CC, Name of the volume set, 12 bytes</summary>
public string strucname;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
public byte[] strucname;
/// <summary>0x1D8, Volume label, 12 bytes</summary>
public string volname;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
public byte[] volname;
/// <summary>0x1E4, Name of the volume owner, 12 bytes</summary>
public string ownername;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
public byte[] ownername;
/// <summary>0x1F0, ODS-2 defines it as "DECFILE11B", 12 bytes</summary>
public string format;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
public byte[] format;
/// <summary>0x1FC, Reserved</summary>
public ushort reserved2;
/// <summary>0x1FE, Checksum of preceding 255 words (16 bit units)</summary>

View File

@@ -32,6 +32,7 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using DiscImageChef.CommonTypes;
@@ -82,40 +83,21 @@ namespace DiscImageChef.Filesystems
byte[] sb_sector = imagePlugin.ReadSector(0 + partition.Start);
OperaSuperBlock sb = new OperaSuperBlock();
OperaSuperBlock sb = BigEndianMarshal.ByteArrayToStructureBigEndian<OperaSuperBlock>(sb_sector);
byte[] cString = new byte[32];
sb.sync_bytes = new byte[5];
sb.record_type = sb_sector[0x000];
Array.Copy(sb_sector, 0x001, sb.sync_bytes, 0, 5);
sb.record_version = sb_sector[0x006];
sb.volume_flags = sb_sector[0x007];
Array.Copy(sb_sector, 0x008, cString, 0, 32);
sb.volume_comment = StringHandlers.CToString(cString);
Array.Copy(sb_sector, 0x028, cString, 0, 32);
sb.volume_label = StringHandlers.CToString(cString);
sb.volume_id = BigEndianBitConverter.ToInt32(sb_sector, 0x048);
sb.block_size = BigEndianBitConverter.ToInt32(sb_sector, 0x04C);
sb.block_count = BigEndianBitConverter.ToInt32(sb_sector, 0x050);
sb.root_dirid = BigEndianBitConverter.ToInt32(sb_sector, 0x054);
sb.rootdir_blocks = BigEndianBitConverter.ToInt32(sb_sector, 0x058);
sb.rootdir_bsize = BigEndianBitConverter.ToInt32(sb_sector, 0x05C);
sb.last_root_copy = BigEndianBitConverter.ToInt32(sb_sector, 0x060);
if(sb.record_type != 1 || sb.record_version != 1)
return;
if(Encoding.ASCII.GetString(sb.sync_bytes) != "ZZZZZ")
return;
if(sb.volume_comment.Length == 0)
sb.volume_comment = "Not set.";
if(sb.volume_label.Length == 0)
sb.volume_label = "Not set.";
SuperBlockMetadata.AppendFormat("Opera filesystem disc.").AppendLine();
SuperBlockMetadata.AppendFormat("Volume label: {0}", sb.volume_label).AppendLine();
SuperBlockMetadata.AppendFormat("Volume comment: {0}", sb.volume_comment).AppendLine();
if(!string.IsNullOrEmpty(StringHandlers.CToString(sb.volume_label, CurrentEncoding)))
SuperBlockMetadata.AppendFormat("Volume label: {0}", StringHandlers.CToString(sb.volume_label, CurrentEncoding)).AppendLine();
if(!string.IsNullOrEmpty(StringHandlers.CToString(sb.volume_comment, CurrentEncoding)))
SuperBlockMetadata.AppendFormat("Volume comment: {0}", StringHandlers.CToString(sb.volume_comment, CurrentEncoding)).AppendLine();
SuperBlockMetadata.AppendFormat("Volume identifier: 0x{0:X8}", sb.volume_id).AppendLine();
SuperBlockMetadata.AppendFormat("Block size: {0} bytes", sb.block_size).AppendLine();
if(imagePlugin.GetSectorSize() == 2336 || imagePlugin.GetSectorSize() == 2352 || imagePlugin.GetSectorSize() == 2448)
@@ -135,27 +117,33 @@ namespace DiscImageChef.Filesystems
information = SuperBlockMetadata.ToString();
xmlFSType = new Schemas.FileSystemType();
xmlFSType.Type = "Opera";
xmlFSType.VolumeName = sb.volume_label;
xmlFSType.ClusterSize = sb.block_size;
xmlFSType.Clusters = sb.block_count;
xmlFSType = new Schemas.FileSystemType
{
Type = "Opera",
VolumeName = StringHandlers.CToString(sb.volume_label, CurrentEncoding),
ClusterSize = sb.block_size,
Clusters = sb.block_count
};
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct OperaSuperBlock
{
/// <summary>0x000, Record type, must be 1</summary>
public byte record_type;
/// <summary>0x001, 5 bytes, "ZZZZZ"</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
public byte[] sync_bytes;
/// <summary>0x006, Record version, must be 1</summary>
public byte record_version;
/// <summary>0x007, Volume flags</summary>
public byte volume_flags;
/// <summary>0x008, 32 bytes, volume comment</summary>
public string volume_comment;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public byte[] volume_comment;
/// <summary>0x028, 32 bytes, volume label</summary>
public string volume_label;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public byte[] volume_label;
/// <summary>0x048, Volume ID</summary>
public int volume_id;
/// <summary>0x04C, Block size in bytes</summary>