From 332c2901fd74cbd1f4f14730ee1dc459333bac4c Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Sun, 23 Jul 2017 21:01:26 +0100 Subject: [PATCH] Use marshalling. --- DiscImageChef.Filesystems/BFS.cs | 53 ++++++----------- DiscImageChef.Filesystems/BTRFS.cs | 1 - DiscImageChef.Filesystems/MinixFS.cs | 62 ++++++++++---------- DiscImageChef.Filesystems/ODS.cs | 87 +++++++++------------------- DiscImageChef.Filesystems/Opera.cs | 50 ++++++---------- 5 files changed, 95 insertions(+), 158 deletions(-) diff --git a/DiscImageChef.Filesystems/BFS.cs b/DiscImageChef.Filesystems/BFS.cs index 85ff350d..d0f1a9c9 100644 --- a/DiscImageChef.Filesystems/BFS.cs +++ b/DiscImageChef.Filesystems/BFS.cs @@ -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(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); } /// /// Be superblock /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] struct BeSuperBlock { /// 0x000, Volume name, 32 bytes - public string name; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] + public byte[] name; /// 0x020, "BFS1", 0x42465331 public uint magic1; /// 0x024, "BIGE", 0x42494745 diff --git a/DiscImageChef.Filesystems/BTRFS.cs b/DiscImageChef.Filesystems/BTRFS.cs index 7b83ed6f..20ddab93 100644 --- a/DiscImageChef.Filesystems/BTRFS.cs +++ b/DiscImageChef.Filesystems/BTRFS.cs @@ -144,7 +144,6 @@ namespace DiscImageChef.Filesystems } catch { - System.Console.WriteLine("Crash"); return false; } diff --git a/DiscImageChef.Filesystems/MinixFS.cs b/DiscImageChef.Filesystems/MinixFS.cs index 0cb0e6d8..183e5a7e 100644 --- a/DiscImageChef.Filesystems/MinixFS.cs +++ b/DiscImageChef.Filesystems/MinixFS.cs @@ -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(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(minix_sb_sector); sb.AppendLine(minixVersion); sb.AppendFormat("{0} chars in filename", filenamesize).AppendLine(); @@ -252,6 +248,7 @@ namespace DiscImageChef.Filesystems /// /// Superblock for Minix V1 and V2 filesystems /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct MinixSuperBlock { /// 0x00, inodes on volume @@ -279,6 +276,7 @@ namespace DiscImageChef.Filesystems /// /// Superblock for Minix V3 filesystems /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct Minix3SuperBlock { /// 0x00, inodes on volume diff --git a/DiscImageChef.Filesystems/ODS.cs b/DiscImageChef.Filesystems/ODS.cs index c85fc4f3..aa6e9b3a 100644 --- a/DiscImageChef.Filesystems/ODS.cs +++ b/DiscImageChef.Filesystems/ODS.cs @@ -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 { /// 0x000, LBN of THIS home block @@ -345,8 +305,10 @@ namespace DiscImageChef.Filesystems /// 0x058, Last modification date public ulong revdate; /// 0x060, Minimum security class, 20 bytes + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] public byte[] min_class; /// 0x074, Maximum security class, 20 bytes + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] public byte[] max_class; /// 0x088, File lookup table FID public ushort filetab_fid1; @@ -361,17 +323,22 @@ namespace DiscImageChef.Filesystems /// 0x092, Volume copy date (??) public ulong copydate; /// 0x09A, 302 bytes + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 302)] public byte[] reserved1; /// 0x1C8, Physical drive serial number public uint serialnum; /// 0x1CC, Name of the volume set, 12 bytes - public string strucname; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] + public byte[] strucname; /// 0x1D8, Volume label, 12 bytes - public string volname; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] + public byte[] volname; /// 0x1E4, Name of the volume owner, 12 bytes - public string ownername; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] + public byte[] ownername; /// 0x1F0, ODS-2 defines it as "DECFILE11B", 12 bytes - public string format; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] + public byte[] format; /// 0x1FC, Reserved public ushort reserved2; /// 0x1FE, Checksum of preceding 255 words (16 bit units) diff --git a/DiscImageChef.Filesystems/Opera.cs b/DiscImageChef.Filesystems/Opera.cs index 558743d0..9c56ca5e 100644 --- a/DiscImageChef.Filesystems/Opera.cs +++ b/DiscImageChef.Filesystems/Opera.cs @@ -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(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 { /// 0x000, Record type, must be 1 public byte record_type; /// 0x001, 5 bytes, "ZZZZZ" + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] public byte[] sync_bytes; /// 0x006, Record version, must be 1 public byte record_version; /// 0x007, Volume flags public byte volume_flags; /// 0x008, 32 bytes, volume comment - public string volume_comment; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] + public byte[] volume_comment; /// 0x028, 32 bytes, volume label - public string volume_label; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] + public byte[] volume_label; /// 0x048, Volume ID public int volume_id; /// 0x04C, Block size in bytes