diff --git a/.idea/.idea.DiscImageChef/.idea/contentModel.xml b/.idea/.idea.DiscImageChef/.idea/contentModel.xml index 34a1ebf7..bb726e68 100644 --- a/.idea/.idea.DiscImageChef/.idea/contentModel.xml +++ b/.idea/.idea.DiscImageChef/.idea/contentModel.xml @@ -413,11 +413,12 @@ + + - - + @@ -435,6 +436,7 @@ + @@ -500,10 +502,10 @@ - + @@ -609,10 +611,10 @@ - + @@ -690,10 +692,10 @@ + - diff --git a/DiscImageChef.Core/Devices/Dumping/ATA.cs b/DiscImageChef.Core/Devices/Dumping/ATA.cs index 2672f917..2dae0eed 100644 --- a/DiscImageChef.Core/Devices/Dumping/ATA.cs +++ b/DiscImageChef.Core/Devices/Dumping/ATA.cs @@ -469,10 +469,10 @@ namespace DiscImageChef.Core.Devices.Dumping (double)blockSize * (double)(blocks + 1) / 1024 / (totalChkDuration / 1000)); PluginBase plugins = new PluginBase(); - plugins.RegisterAllPlugins(encoding); + plugins.RegisterAllPlugins(); FiltersList filtersList = new FiltersList(); - Filter inputFilter = filtersList.GetFilter(outputPrefix + ".bin"); + IFilter inputFilter = filtersList.GetFilter(outputPrefix + ".bin"); if(inputFilter == null) { @@ -480,7 +480,7 @@ namespace DiscImageChef.Core.Devices.Dumping return; } - ImagePlugin imageFormat = ImageFormat.Detect(inputFilter); + IMediaImage imageFormat = ImageFormat.Detect(inputFilter); PartitionType[] xmlFileSysInfo = null; try { if(!imageFormat.OpenImage(inputFilter)) imageFormat = null; } @@ -513,15 +513,15 @@ namespace DiscImageChef.Core.Devices.Dumping i, partitions[i].Start, partitions[i].End, partitions[i].Type, partitions[i].Scheme); - foreach(Filesystem plugin in plugins.PluginsList.Values) + foreach(IFilesystem plugin in plugins.PluginsList.Values) try { if(!plugin.Identify(imageFormat, partitions[i])) continue; - plugin.GetInformation(imageFormat, partitions[i], out _); - lstFs.Add(plugin.XmlFSType); - Statistics.AddFilesystem(plugin.XmlFSType.Type); - dumpLog.WriteLine("Filesystem {0} found.", plugin.XmlFSType.Type); + plugin.GetInformation(imageFormat, partitions[i], out _, encoding); + lstFs.Add(plugin.XmlFsType); + Statistics.AddFilesystem(plugin.XmlFsType.Type); + dumpLog.WriteLine("Filesystem {0} found.", plugin.XmlFsType.Type); } #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body catch @@ -548,15 +548,15 @@ namespace DiscImageChef.Core.Devices.Dumping Size = blocks * blockSize }; - foreach(Filesystem plugin in plugins.PluginsList.Values) + foreach(IFilesystem plugin in plugins.PluginsList.Values) try { if(!plugin.Identify(imageFormat, wholePart)) continue; - plugin.GetInformation(imageFormat, wholePart, out _); - lstFs.Add(plugin.XmlFSType); - Statistics.AddFilesystem(plugin.XmlFSType.Type); - dumpLog.WriteLine("Filesystem {0} found.", plugin.XmlFSType.Type); + plugin.GetInformation(imageFormat, wholePart, out _, encoding); + lstFs.Add(plugin.XmlFsType); + Statistics.AddFilesystem(plugin.XmlFsType.Type); + dumpLog.WriteLine("Filesystem {0} found.", plugin.XmlFsType.Type); } #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body catch diff --git a/DiscImageChef.Core/Devices/Dumping/SBC.cs b/DiscImageChef.Core/Devices/Dumping/SBC.cs index 903a295e..8229560f 100644 --- a/DiscImageChef.Core/Devices/Dumping/SBC.cs +++ b/DiscImageChef.Core/Devices/Dumping/SBC.cs @@ -594,9 +594,9 @@ namespace DiscImageChef.Core.Devices.Dumping (double)blockSize * (double)(blocks + 1) / 1024 / (totalChkDuration / 1000)); PluginBase plugins = new PluginBase(); - plugins.RegisterAllPlugins(encoding); + plugins.RegisterAllPlugins(); FiltersList filtersList = new FiltersList(); - Filter inputFilter = filtersList.GetFilter(outputPrefix + outputExtension); + IFilter inputFilter = filtersList.GetFilter(outputPrefix + outputExtension); if(inputFilter == null) { @@ -604,7 +604,7 @@ namespace DiscImageChef.Core.Devices.Dumping return; } - ImagePlugin imageFormat = ImageFormat.Detect(inputFilter); + IMediaImage imageFormat = ImageFormat.Detect(inputFilter); PartitionType[] xmlFileSysInfo = null; try { if(!imageFormat.OpenImage(inputFilter)) imageFormat = null; } @@ -636,17 +636,17 @@ namespace DiscImageChef.Core.Devices.Dumping i, partitions[i].Start, partitions[i].End, partitions[i].Type, partitions[i].Scheme); - foreach(Filesystem plugin in plugins.PluginsList.Values) + foreach(IFilesystem plugin in plugins.PluginsList.Values) try { if(!plugin.Identify(imageFormat, partitions[i])) continue; - plugin.GetInformation(imageFormat, partitions[i], out _); - lstFs.Add(plugin.XmlFSType); - Statistics.AddFilesystem(plugin.XmlFSType.Type); - dumpLog.WriteLine("Filesystem {0} found.", plugin.XmlFSType.Type); + plugin.GetInformation(imageFormat, partitions[i], out _, encoding); + lstFs.Add(plugin.XmlFsType); + Statistics.AddFilesystem(plugin.XmlFsType.Type); + dumpLog.WriteLine("Filesystem {0} found.", plugin.XmlFsType.Type); - switch(plugin.XmlFSType.Type) + switch(plugin.XmlFsType.Type) { case "Opera": dskType = MediaType.ThreeDO; @@ -682,17 +682,17 @@ namespace DiscImageChef.Core.Devices.Dumping Partition wholePart = new Partition {Name = "Whole device", Length = blocks, Size = blocks * blockSize}; - foreach(Filesystem plugin in plugins.PluginsList.Values) + foreach(IFilesystem plugin in plugins.PluginsList.Values) try { if(!plugin.Identify(imageFormat, wholePart)) continue; - plugin.GetInformation(imageFormat, wholePart, out _); - lstFs.Add(plugin.XmlFSType); - Statistics.AddFilesystem(plugin.XmlFSType.Type); - dumpLog.WriteLine("Filesystem {0} found.", plugin.XmlFSType.Type); + plugin.GetInformation(imageFormat, wholePart, out _, encoding); + lstFs.Add(plugin.XmlFsType); + Statistics.AddFilesystem(plugin.XmlFsType.Type); + dumpLog.WriteLine("Filesystem {0} found.", plugin.XmlFsType.Type); - switch(plugin.XmlFSType.Type) + switch(plugin.XmlFsType.Type) { case "Opera": dskType = MediaType.ThreeDO; diff --git a/DiscImageChef.Core/Devices/Dumping/SecureDigital.cs b/DiscImageChef.Core/Devices/Dumping/SecureDigital.cs index 1f29fcc1..09a34d20 100644 --- a/DiscImageChef.Core/Devices/Dumping/SecureDigital.cs +++ b/DiscImageChef.Core/Devices/Dumping/SecureDigital.cs @@ -451,10 +451,10 @@ namespace DiscImageChef.Core.Devices.Dumping (double)blockSize * (double)(blocks + 1) / 1024 / (totalChkDuration / 1000)); PluginBase plugins = new PluginBase(); - plugins.RegisterAllPlugins(encoding); + plugins.RegisterAllPlugins(); FiltersList filtersList = new FiltersList(); - Filter inputFilter = filtersList.GetFilter(outputPrefix + ".bin"); + IFilter inputFilter = filtersList.GetFilter(outputPrefix + ".bin"); if(inputFilter == null) { @@ -462,7 +462,7 @@ namespace DiscImageChef.Core.Devices.Dumping return; } - ImagePlugin imageFormat = ImageFormat.Detect(inputFilter); + IMediaImage imageFormat = ImageFormat.Detect(inputFilter); PartitionType[] xmlFileSysInfo = null; try { if(!imageFormat.OpenImage(inputFilter)) imageFormat = null; } @@ -494,15 +494,15 @@ namespace DiscImageChef.Core.Devices.Dumping i, partitions[i].Start, partitions[i].End, partitions[i].Type, partitions[i].Scheme); - foreach(Filesystem plugin in plugins.PluginsList.Values) + foreach(IFilesystem plugin in plugins.PluginsList.Values) try { if(!plugin.Identify(imageFormat, partitions[i])) continue; - plugin.GetInformation(imageFormat, partitions[i], out _); - lstFs.Add(plugin.XmlFSType); - Statistics.AddFilesystem(plugin.XmlFSType.Type); - dumpLog.WriteLine("Filesystem {0} found.", plugin.XmlFSType.Type); + plugin.GetInformation(imageFormat, partitions[i], out _, encoding); + lstFs.Add(plugin.XmlFsType); + Statistics.AddFilesystem(plugin.XmlFsType.Type); + dumpLog.WriteLine("Filesystem {0} found.", plugin.XmlFsType.Type); } #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body catch @@ -525,15 +525,15 @@ namespace DiscImageChef.Core.Devices.Dumping Partition wholePart = new Partition {Name = "Whole device", Length = blocks, Size = blocks * blockSize}; - foreach(Filesystem plugin in plugins.PluginsList.Values) + foreach(IFilesystem plugin in plugins.PluginsList.Values) try { if(!plugin.Identify(imageFormat, wholePart)) continue; - plugin.GetInformation(imageFormat, wholePart, out _); - lstFs.Add(plugin.XmlFSType); - Statistics.AddFilesystem(plugin.XmlFSType.Type); - dumpLog.WriteLine("Filesystem {0} found.", plugin.XmlFSType.Type); + plugin.GetInformation(imageFormat, wholePart, out _, encoding); + lstFs.Add(plugin.XmlFsType); + Statistics.AddFilesystem(plugin.XmlFsType.Type); + dumpLog.WriteLine("Filesystem {0} found.", plugin.XmlFsType.Type); } #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body catch diff --git a/DiscImageChef.Core/Devices/Dumping/XGD.cs b/DiscImageChef.Core/Devices/Dumping/XGD.cs index 3ccc18f5..76abd234 100644 --- a/DiscImageChef.Core/Devices/Dumping/XGD.cs +++ b/DiscImageChef.Core/Devices/Dumping/XGD.cs @@ -794,9 +794,9 @@ namespace DiscImageChef.Core.Devices.Dumping (double)BLOCK_SIZE * (double)(blocks + 1) / 1024 / (totalChkDuration / 1000)); PluginBase plugins = new PluginBase(); - plugins.RegisterAllPlugins(encoding); + plugins.RegisterAllPlugins(); FiltersList filtersList = new FiltersList(); - Filter inputFilter = filtersList.GetFilter(outputPrefix + ".iso"); + IFilter inputFilter = filtersList.GetFilter(outputPrefix + ".iso"); if(inputFilter == null) { @@ -804,7 +804,7 @@ namespace DiscImageChef.Core.Devices.Dumping return; } - ImagePlugin imageFormat = ImageFormat.Detect(inputFilter); + IMediaImage imageFormat = ImageFormat.Detect(inputFilter); PartitionType[] xmlFileSysInfo = null; try { if(!imageFormat.OpenImage(inputFilter)) imageFormat = null; } @@ -836,17 +836,17 @@ namespace DiscImageChef.Core.Devices.Dumping i, partitions[i].Start, partitions[i].End, partitions[i].Type, partitions[i].Scheme); - foreach(Filesystem plugin in plugins.PluginsList.Values) + foreach(IFilesystem plugin in plugins.PluginsList.Values) try { if(!plugin.Identify(imageFormat, partitions[i])) continue; - plugin.GetInformation(imageFormat, partitions[i], out _); - lstFs.Add(plugin.XmlFSType); - Statistics.AddFilesystem(plugin.XmlFSType.Type); - dumpLog.WriteLine("Filesystem {0} found.", plugin.XmlFSType.Type); + plugin.GetInformation(imageFormat, partitions[i], out _, encoding); + lstFs.Add(plugin.XmlFsType); + Statistics.AddFilesystem(plugin.XmlFsType.Type); + dumpLog.WriteLine("Filesystem {0} found.", plugin.XmlFsType.Type); - switch(plugin.XmlFSType.Type) + switch(plugin.XmlFsType.Type) { case "Opera": dskType = MediaType.ThreeDO; @@ -882,17 +882,17 @@ namespace DiscImageChef.Core.Devices.Dumping Partition wholePart = new Partition {Name = "Whole device", Length = blocks, Size = blocks * BLOCK_SIZE}; - foreach(Filesystem plugin in plugins.PluginsList.Values) + foreach(IFilesystem plugin in plugins.PluginsList.Values) try { if(!plugin.Identify(imageFormat, wholePart)) continue; - plugin.GetInformation(imageFormat, wholePart, out _); - lstFs.Add(plugin.XmlFSType); - Statistics.AddFilesystem(plugin.XmlFSType.Type); - dumpLog.WriteLine("Filesystem {0} found.", plugin.XmlFSType.Type); + plugin.GetInformation(imageFormat, wholePart, out _, encoding); + lstFs.Add(plugin.XmlFsType); + Statistics.AddFilesystem(plugin.XmlFsType.Type); + dumpLog.WriteLine("Filesystem {0} found.", plugin.XmlFsType.Type); - switch(plugin.XmlFSType.Type) + switch(plugin.XmlFsType.Type) { case "Opera": dskType = MediaType.ThreeDO; diff --git a/DiscImageChef.Core/Filesystems.cs b/DiscImageChef.Core/Filesystems.cs index 3f050e37..7135807f 100644 --- a/DiscImageChef.Core/Filesystems.cs +++ b/DiscImageChef.Core/Filesystems.cs @@ -46,7 +46,7 @@ namespace DiscImageChef.Core /// Media image /// List of plugins recognizing the filesystem /// Partition - public static void Identify(ImagePlugin imagePlugin, out List idPlugins, Partition partition) + public static void Identify(IMediaImage imagePlugin, out List idPlugins, Partition partition) { PluginBase plugins = new PluginBase(); plugins.RegisterAllPlugins(); diff --git a/DiscImageChef.Core/ImageFormat.cs b/DiscImageChef.Core/ImageFormat.cs index e7607c3d..b097ba4f 100644 --- a/DiscImageChef.Core/ImageFormat.cs +++ b/DiscImageChef.Core/ImageFormat.cs @@ -45,18 +45,18 @@ namespace DiscImageChef.Core /// /// Filter /// Detected image plugin - public static ImagePlugin Detect(Filter imageFilter) + public static IMediaImage Detect(IFilter imageFilter) { try { PluginBase plugins = new PluginBase(); plugins.RegisterAllPlugins(); - ImagePlugin imageFormat = null; + IMediaImage imageFormat = null; // Check all but RAW plugin - foreach(ImagePlugin imageplugin in plugins.ImagePluginsList.Values.Where(imageplugin => - imageplugin.PluginUuid != + foreach(IMediaImage imageplugin in plugins.ImagePluginsList.Values.Where(imageplugin => + imageplugin.Id != new Guid("12345678-AAAA-BBBB-CCCC-123456789000")) ) @@ -77,8 +77,8 @@ namespace DiscImageChef.Core if(imageFormat != null) return imageFormat; // Check only RAW plugin - foreach(ImagePlugin imageplugin in plugins.ImagePluginsList.Values.Where(imageplugin => - imageplugin.PluginUuid == + foreach(IMediaImage imageplugin in plugins.ImagePluginsList.Values.Where(imageplugin => + imageplugin.Id == new Guid("12345678-AAAA-BBBB-CCCC-123456789000")) ) diff --git a/DiscImageChef.Core/Partitions.cs b/DiscImageChef.Core/Partitions.cs index 7d5e92b9..38e81aff 100644 --- a/DiscImageChef.Core/Partitions.cs +++ b/DiscImageChef.Core/Partitions.cs @@ -49,7 +49,7 @@ namespace DiscImageChef.Core /// /// Image /// List of found partitions - public static List GetAll(ImagePlugin image) + public static List GetAll(IMediaImage image) { PluginBase plugins = new PluginBase(); plugins.RegisterAllPlugins(); @@ -58,10 +58,10 @@ namespace DiscImageChef.Core List checkedLocations = new List(); // Getting all partitions from device (e.g. tracks) - if(image.ImageInfo.HasPartitions) + if(image.Info.HasPartitions) foreach(Partition imagePartition in image.Partitions) { - foreach(PartitionPlugin partitionPlugin in plugins.PartPluginsList.Values) + foreach(IPartition partitionPlugin in plugins.PartPluginsList.Values) if(partitionPlugin.GetInformation(image, out List partitions, imagePartition.Start)) { foundPartitions.AddRange(partitions); @@ -74,7 +74,7 @@ namespace DiscImageChef.Core // Getting all partitions at start of device else { - foreach(PartitionPlugin partitionPlugin in plugins.PartPluginsList.Values) + foreach(IPartition partitionPlugin in plugins.PartPluginsList.Values) if(partitionPlugin.GetInformation(image, out List partitions, 0)) { foundPartitions.AddRange(partitions); @@ -95,7 +95,7 @@ namespace DiscImageChef.Core List childs = new List(); - foreach(PartitionPlugin partitionPlugin in plugins.PartPluginsList.Values) + foreach(IPartition partitionPlugin in plugins.PartPluginsList.Values) { DicConsole.DebugWriteLine("Partitions", "Trying {0} @ {1}", partitionPlugin.Name, foundPartitions[0].Start); @@ -130,7 +130,7 @@ namespace DiscImageChef.Core } // Be sure that device partitions are not excluded if not mapped by any scheme... - if(image.ImageInfo.HasPartitions) + if(image.Info.HasPartitions) { List startLocations = childPartitions.Select(detectedPartition => detectedPartition.Start).ToList(); diff --git a/DiscImageChef.Core/PluginBase.cs b/DiscImageChef.Core/PluginBase.cs index 1436cabf..5a16837c 100644 --- a/DiscImageChef.Core/PluginBase.cs +++ b/DiscImageChef.Core/PluginBase.cs @@ -32,6 +32,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Reflection; using System.Text; using DiscImageChef.Console; @@ -49,86 +50,75 @@ namespace DiscImageChef.Core /// /// List of all media image plugins /// - public SortedDictionary ImagePluginsList; + public SortedDictionary ImagePluginsList; /// /// List of all partition plugins /// - public SortedDictionary PartPluginsList; + public SortedDictionary PartPluginsList; /// /// List of all filesystem plugins /// - public SortedDictionary PluginsList; + public SortedDictionary PluginsList; /// /// Initializes the plugins lists /// public PluginBase() { - PluginsList = new SortedDictionary(); - PartPluginsList = new SortedDictionary(); - ImagePluginsList = new SortedDictionary(); + PluginsList = new SortedDictionary(); + PartPluginsList = new SortedDictionary(); + ImagePluginsList = new SortedDictionary(); } /// /// Fills the plugins lists /// - /// Which encoding to pass to plugins - public void RegisterAllPlugins(Encoding encoding = null) + public void RegisterAllPlugins() { - Assembly assembly = Assembly.GetAssembly(typeof(ImagePlugin)); + Assembly assembly = Assembly.GetAssembly(typeof(IMediaImage)); - foreach(Type type in assembly.GetTypes()) + foreach(Type type in assembly.GetTypes().Where(t => t.GetInterfaces().Contains(typeof(IMediaImage)))) try { - if(!type.IsSubclassOf(typeof(ImagePlugin))) continue; - - ImagePlugin plugin = (ImagePlugin)type.GetConstructor(Type.EmptyTypes)?.Invoke(new object[] { }); + IMediaImage plugin = (IMediaImage)type.GetConstructor(Type.EmptyTypes)?.Invoke(new object[] { }); RegisterImagePlugin(plugin); } catch(Exception exception) { DicConsole.ErrorWriteLine("Exception {0}", exception); } - assembly = Assembly.GetAssembly(typeof(PartitionPlugin)); + assembly = Assembly.GetAssembly(typeof(IPartition)); - foreach(Type type in assembly.GetTypes()) + foreach(Type type in assembly.GetTypes().Where(t => t.GetInterfaces().Contains(typeof(IPartition)))) try { - if(!type.IsSubclassOf(typeof(PartitionPlugin))) continue; - - PartitionPlugin plugin = - (PartitionPlugin)type.GetConstructor(Type.EmptyTypes)?.Invoke(new object[] { }); + IPartition plugin = + (IPartition)type.GetConstructor(Type.EmptyTypes)?.Invoke(new object[] { }); RegisterPartPlugin(plugin); } catch(Exception exception) { DicConsole.ErrorWriteLine("Exception {0}", exception); } - assembly = Assembly.GetAssembly(typeof(Filesystem)); + assembly = Assembly.GetAssembly(typeof(IFilesystem)); - foreach(Type type in assembly.GetTypes()) + foreach(Type type in assembly.GetTypes().Where(t => t.GetInterfaces().Contains(typeof(IFilesystem)))) try { - if(!type.IsSubclassOf(typeof(Filesystem))) continue; - - Filesystem plugin; - if(encoding != null) - plugin = (Filesystem)type.GetConstructor(new[] {encoding.GetType()}) - ?.Invoke(new object[] {encoding}); - else plugin = (Filesystem)type.GetConstructor(Type.EmptyTypes)?.Invoke(new object[] { }); + IFilesystem plugin = (IFilesystem)type.GetConstructor(Type.EmptyTypes)?.Invoke(new object[] { }); RegisterPlugin(plugin); } catch(Exception exception) { DicConsole.ErrorWriteLine("Exception {0}", exception); } } - void RegisterImagePlugin(ImagePlugin plugin) + void RegisterImagePlugin(IMediaImage plugin) { if(!ImagePluginsList.ContainsKey(plugin.Name.ToLower())) ImagePluginsList.Add(plugin.Name.ToLower(), plugin); } - void RegisterPlugin(Filesystem plugin) + void RegisterPlugin(IFilesystem plugin) { if(!PluginsList.ContainsKey(plugin.Name.ToLower())) PluginsList.Add(plugin.Name.ToLower(), plugin); } - void RegisterPartPlugin(PartitionPlugin partplugin) + void RegisterPartPlugin(IPartition partplugin) { if(!PartPluginsList.ContainsKey(partplugin.Name.ToLower())) PartPluginsList.Add(partplugin.Name.ToLower(), partplugin); diff --git a/DiscImageChef.Core/Sidecar/AudioMedia.cs b/DiscImageChef.Core/Sidecar/AudioMedia.cs index 5f356ce6..c8d2f88b 100644 --- a/DiscImageChef.Core/Sidecar/AudioMedia.cs +++ b/DiscImageChef.Core/Sidecar/AudioMedia.cs @@ -33,6 +33,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Text; using DiscImageChef.DiscImages; using Schemas; @@ -51,8 +52,8 @@ namespace DiscImageChef.Core /// Image plugins /// List of image checksums /// Metadata sidecar - static void AudioMedia(ImagePlugin image, Guid filterId, string imagePath, FileInfo fi, PluginBase plugins, - List imgChecksums, ref CICMMetadataType sidecar) + static void AudioMedia(IMediaImage image, Guid filterId, string imagePath, FileInfo fi, PluginBase plugins, + List imgChecksums, ref CICMMetadataType sidecar, Encoding encoding) { sidecar.AudioMedia = new[] { @@ -67,14 +68,14 @@ namespace DiscImageChef.Core Value = Path.GetFileName(imagePath) }, Size = fi.Length, - Sequence = new SequenceType {MediaTitle = image.ImageInfo.MediaTitle} + Sequence = new SequenceType {MediaTitle = image.Info.MediaTitle} } }; - if(image.ImageInfo.MediaSequence != 0 && image.ImageInfo.LastMediaSequence != 0) + if(image.Info.MediaSequence != 0 && image.Info.LastMediaSequence != 0) { - sidecar.AudioMedia[0].Sequence.MediaSequence = image.ImageInfo.MediaSequence; - sidecar.AudioMedia[0].Sequence.TotalMedia = image.ImageInfo.LastMediaSequence; + sidecar.AudioMedia[0].Sequence.MediaSequence = image.Info.MediaSequence; + sidecar.AudioMedia[0].Sequence.TotalMedia = image.Info.LastMediaSequence; } else { diff --git a/DiscImageChef.Core/Sidecar/BlockMedia.cs b/DiscImageChef.Core/Sidecar/BlockMedia.cs index bf609851..1b8b3fd2 100644 --- a/DiscImageChef.Core/Sidecar/BlockMedia.cs +++ b/DiscImageChef.Core/Sidecar/BlockMedia.cs @@ -34,6 +34,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Text; using DiscImageChef.CommonTypes; using DiscImageChef.Console; using DiscImageChef.Decoders.ATA; @@ -60,8 +61,8 @@ namespace DiscImageChef.Core /// Image plugins /// List of image checksums /// Metadata sidecar - static void BlockMedia(ImagePlugin image, Guid filterId, string imagePath, FileInfo fi, PluginBase plugins, - List imgChecksums, ref CICMMetadataType sidecar) + static void BlockMedia(IMediaImage image, Guid filterId, string imagePath, FileInfo fi, PluginBase plugins, + List imgChecksums, ref CICMMetadataType sidecar, Encoding encoding) { sidecar.BlockMedia = new[] { @@ -76,14 +77,14 @@ namespace DiscImageChef.Core Value = Path.GetFileName(imagePath) }, Size = fi.Length, - Sequence = new SequenceType {MediaTitle = image.ImageInfo.MediaTitle} + Sequence = new SequenceType {MediaTitle = image.Info.MediaTitle} } }; - if(image.ImageInfo.MediaSequence != 0 && image.ImageInfo.LastMediaSequence != 0) + if(image.Info.MediaSequence != 0 && image.Info.LastMediaSequence != 0) { - sidecar.BlockMedia[0].Sequence.MediaSequence = image.ImageInfo.MediaSequence; - sidecar.BlockMedia[0].Sequence.TotalMedia = image.ImageInfo.LastMediaSequence; + sidecar.BlockMedia[0].Sequence.MediaSequence = image.Info.MediaSequence; + sidecar.BlockMedia[0].Sequence.TotalMedia = image.Info.LastMediaSequence; } else { @@ -91,7 +92,7 @@ namespace DiscImageChef.Core sidecar.BlockMedia[0].Sequence.TotalMedia = 1; } - foreach(MediaTagType tagType in image.ImageInfo.ReadableMediaTags) + foreach(MediaTagType tagType in image.Info.ReadableMediaTags) switch(tagType) { case MediaTagType.ATAPI_IDENTIFY: @@ -242,7 +243,7 @@ namespace DiscImageChef.Core } // If there is only one track, and it's the same as the image file (e.g. ".iso" files), don't re-checksum. - if(image.PluginUuid == new Guid("12345678-AAAA-BBBB-CCCC-123456789000") && + if(image.Id == new Guid("12345678-AAAA-BBBB-CCCC-123456789000") && filterId == new Guid("12345678-AAAA-BBBB-CCCC-123456789000")) sidecar.BlockMedia[0].ContentChecksums = sidecar.BlockMedia[0].Checksums; else @@ -253,7 +254,7 @@ namespace DiscImageChef.Core //goto skipImageChecksum; uint sectorsToRead = 512; - ulong sectors = image.ImageInfo.Sectors; + ulong sectors = image.Info.Sectors; ulong doneSectors = 0; InitProgress2(); @@ -287,17 +288,17 @@ namespace DiscImageChef.Core EndProgress2(); } - MediaType.MediaTypeToString(image.ImageInfo.MediaType, out string dskType, out string dskSubType); + MediaType.MediaTypeToString(image.Info.MediaType, out string dskType, out string dskSubType); sidecar.BlockMedia[0].DiskType = dskType; sidecar.BlockMedia[0].DiskSubType = dskSubType; - Statistics.AddMedia(image.ImageInfo.MediaType, false); + Statistics.AddMedia(image.Info.MediaType, false); - sidecar.BlockMedia[0].Dimensions = Dimensions.DimensionsFromMediaType(image.ImageInfo.MediaType); + sidecar.BlockMedia[0].Dimensions = Dimensions.DimensionsFromMediaType(image.Info.MediaType); - sidecar.BlockMedia[0].LogicalBlocks = (long)image.ImageInfo.Sectors; - sidecar.BlockMedia[0].LogicalBlockSize = (int)image.ImageInfo.SectorSize; + sidecar.BlockMedia[0].LogicalBlocks = (long)image.Info.Sectors; + sidecar.BlockMedia[0].LogicalBlockSize = (int)image.Info.SectorSize; // TODO: Detect it - sidecar.BlockMedia[0].PhysicalBlockSize = (int)image.ImageInfo.SectorSize; + sidecar.BlockMedia[0].PhysicalBlockSize = (int)image.Info.SectorSize; UpdateStatus("Checking filesystems..."); @@ -321,14 +322,14 @@ namespace DiscImageChef.Core }; List lstFs = new List(); - foreach(Filesystem plugin in plugins.PluginsList.Values) + foreach(IFilesystem plugin in plugins.PluginsList.Values) try { if(!plugin.Identify(image, partitions[i])) continue; - plugin.GetInformation(image, partitions[i], out _); - lstFs.Add(plugin.XmlFSType); - Statistics.AddFilesystem(plugin.XmlFSType.Type); + plugin.GetInformation(image, partitions[i], out _, encoding); + lstFs.Add(plugin.XmlFsType); + Statistics.AddFilesystem(plugin.XmlFsType.Type); } #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body catch @@ -345,26 +346,26 @@ namespace DiscImageChef.Core sidecar.BlockMedia[0].FileSystemInformation[0] = new PartitionType { StartSector = 0, - EndSector = (int)(image.ImageInfo.Sectors - 1) + EndSector = (int)(image.Info.Sectors - 1) }; Partition wholePart = new Partition { Name = "Whole device", - Length = image.ImageInfo.Sectors, - Size = image.ImageInfo.Sectors * image.ImageInfo.SectorSize + Length = image.Info.Sectors, + Size = image.Info.Sectors * image.Info.SectorSize }; List lstFs = new List(); - foreach(Filesystem plugin in plugins.PluginsList.Values) + foreach(IFilesystem plugin in plugins.PluginsList.Values) try { if(!plugin.Identify(image, wholePart)) continue; - plugin.GetInformation(image, wholePart, out _); - lstFs.Add(plugin.XmlFSType); - Statistics.AddFilesystem(plugin.XmlFSType.Type); + plugin.GetInformation(image, wholePart, out _, encoding); + lstFs.Add(plugin.XmlFsType); + Statistics.AddFilesystem(plugin.XmlFsType.Type); } #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body catch @@ -376,17 +377,17 @@ namespace DiscImageChef.Core if(lstFs.Count > 0) sidecar.BlockMedia[0].FileSystemInformation[0].FileSystems = lstFs.ToArray(); } - if(image.ImageInfo.Cylinders > 0 && image.ImageInfo.Heads > 0 && image.ImageInfo.SectorsPerTrack > 0) + if(image.Info.Cylinders > 0 && image.Info.Heads > 0 && image.Info.SectorsPerTrack > 0) { sidecar.BlockMedia[0].CylindersSpecified = true; sidecar.BlockMedia[0].HeadsSpecified = true; sidecar.BlockMedia[0].SectorsPerTrackSpecified = true; - sidecar.BlockMedia[0].Cylinders = image.ImageInfo.Cylinders; - sidecar.BlockMedia[0].Heads = image.ImageInfo.Heads; - sidecar.BlockMedia[0].SectorsPerTrack = image.ImageInfo.SectorsPerTrack; + sidecar.BlockMedia[0].Cylinders = image.Info.Cylinders; + sidecar.BlockMedia[0].Heads = image.Info.Heads; + sidecar.BlockMedia[0].SectorsPerTrack = image.Info.SectorsPerTrack; } - if(image.ImageInfo.ReadableMediaTags.Contains(MediaTagType.ATA_IDENTIFY)) + if(image.Info.ReadableMediaTags.Contains(MediaTagType.ATA_IDENTIFY)) { Identify.IdentifyDevice? ataId = Identify.Decode(image.ReadDiskTag(MediaTagType.ATA_IDENTIFY)); if(ataId.HasValue) @@ -414,7 +415,7 @@ namespace DiscImageChef.Core // TODO: This is more of a hack, redo it planned for >4.0 string trkFormat = null; - switch(image.ImageInfo.MediaType) + switch(image.Info.MediaType) { case CommonTypes.MediaType.Apple32SS: case CommonTypes.MediaType.Apple32DS: @@ -541,14 +542,14 @@ namespace DiscImageChef.Core ZZZNoFilter scpFilter = new ZZZNoFilter(); scpFilter.Open(scpFilePath); - if(image.ImageInfo.Heads <= 2 && scpImage.IdentifyImage(scpFilter)) + if(image.Info.Heads <= 2 && scpImage.IdentifyImage(scpFilter)) { try { scpImage.OpenImage(scpFilter); } catch(NotImplementedException) { } - if(image.ImageInfo.Heads == 2 && scpImage.Header.heads == 0 || image.ImageInfo.Heads == 1 && + if(image.Info.Heads == 2 && scpImage.Header.heads == 0 || image.Info.Heads == 1 && (scpImage.Header.heads == 1 || scpImage.Header.heads == 2)) - if(scpImage.Header.end + 1 >= image.ImageInfo.Cylinders) + if(scpImage.Header.end + 1 >= image.Info.Cylinders) { List scpBlockTrackTypes = new List(); long currentSector = 0; @@ -558,8 +559,8 @@ namespace DiscImageChef.Core { BlockTrackType scpBlockTrackType = new BlockTrackType { - Cylinder = t / image.ImageInfo.Heads, - Head = t % image.ImageInfo.Heads, + Cylinder = t / image.Info.Heads, + Head = t % image.Info.Heads, Image = new ImageType { format = scpImage.ImageFormat, @@ -568,13 +569,13 @@ namespace DiscImageChef.Core } }; - if(scpBlockTrackType.Cylinder < image.ImageInfo.Cylinders) + if(scpBlockTrackType.Cylinder < image.Info.Cylinders) { scpBlockTrackType.StartSector = currentSector; - currentSector += image.ImageInfo.SectorsPerTrack; + currentSector += image.Info.SectorsPerTrack; scpBlockTrackType.EndSector = currentSector - 1; - scpBlockTrackType.Sectors = image.ImageInfo.SectorsPerTrack; - scpBlockTrackType.BytesPerSector = (int)image.ImageInfo.SectorSize; + scpBlockTrackType.Sectors = image.Info.SectorsPerTrack; + scpBlockTrackType.BytesPerSector = (int)image.Info.SectorSize; scpBlockTrackType.Format = trkFormat; } @@ -598,11 +599,11 @@ namespace DiscImageChef.Core else DicConsole .ErrorWriteLine("SuperCardPro image do not contain same number of tracks ({0}) than disk image ({1}), ignoring...", - scpImage.Header.end + 1, image.ImageInfo.Cylinders); + scpImage.Header.end + 1, image.Info.Cylinders); else DicConsole .ErrorWriteLine("SuperCardPro image do not contain same number of heads ({0}) than disk image ({1}), ignoring...", - 2, image.ImageInfo.Heads); + 2, image.Info.Heads); } } #endregion @@ -630,24 +631,24 @@ namespace DiscImageChef.Core KryoFlux kfImage = new KryoFlux(); ZZZNoFilter kfFilter = new ZZZNoFilter(); kfFilter.Open(kfFile); - if(image.ImageInfo.Heads <= 2 && kfImage.IdentifyImage(kfFilter)) + if(image.Info.Heads <= 2 && kfImage.IdentifyImage(kfFilter)) { try { kfImage.OpenImage(kfFilter); } catch(NotImplementedException) { } - if(kfImage.ImageInfo.Heads == image.ImageInfo.Heads) - if(kfImage.ImageInfo.Cylinders >= image.ImageInfo.Cylinders) + if(kfImage.Info.Heads == image.Info.Heads) + if(kfImage.Info.Cylinders >= image.Info.Cylinders) { List kfBlockTrackTypes = new List(); long currentSector = 0; - foreach(KeyValuePair kvp in kfImage.tracks) + foreach(KeyValuePair kvp in kfImage.tracks) { BlockTrackType kfBlockTrackType = new BlockTrackType { - Cylinder = kvp.Key / image.ImageInfo.Heads, - Head = kvp.Key % image.ImageInfo.Heads, + Cylinder = kvp.Key / image.Info.Heads, + Head = kvp.Key % image.Info.Heads, Image = new ImageType { format = kfImage.ImageFormat, @@ -660,13 +661,13 @@ namespace DiscImageChef.Core } }; - if(kfBlockTrackType.Cylinder < image.ImageInfo.Cylinders) + if(kfBlockTrackType.Cylinder < image.Info.Cylinders) { kfBlockTrackType.StartSector = currentSector; - currentSector += image.ImageInfo.SectorsPerTrack; + currentSector += image.Info.SectorsPerTrack; kfBlockTrackType.EndSector = currentSector - 1; - kfBlockTrackType.Sectors = image.ImageInfo.SectorsPerTrack; - kfBlockTrackType.BytesPerSector = (int)image.ImageInfo.SectorSize; + kfBlockTrackType.Sectors = image.Info.SectorsPerTrack; + kfBlockTrackType.BytesPerSector = (int)image.Info.SectorSize; kfBlockTrackType.Format = trkFormat; } @@ -686,11 +687,11 @@ namespace DiscImageChef.Core else DicConsole .ErrorWriteLine("KryoFlux image do not contain same number of tracks ({0}) than disk image ({1}), ignoring...", - kfImage.ImageInfo.Cylinders, image.ImageInfo.Cylinders); + kfImage.Info.Cylinders, image.Info.Cylinders); else DicConsole .ErrorWriteLine("KryoFluximage do not contain same number of heads ({0}) than disk image ({1}), ignoring...", - kfImage.ImageInfo.Heads, image.ImageInfo.Heads); + kfImage.Info.Heads, image.Info.Heads); } } #endregion @@ -710,8 +711,8 @@ namespace DiscImageChef.Core try { dfiImage.OpenImage(dfiFilter); } catch(NotImplementedException) { } - if(image.ImageInfo.Heads == dfiImage.ImageInfo.Heads) - if(dfiImage.ImageInfo.Cylinders >= image.ImageInfo.Cylinders) + if(image.Info.Heads == dfiImage.Info.Heads) + if(dfiImage.Info.Cylinders >= image.Info.Cylinders) { List dfiBlockTrackTypes = new List(); long currentSector = 0; @@ -721,18 +722,18 @@ namespace DiscImageChef.Core { BlockTrackType dfiBlockTrackType = new BlockTrackType { - Cylinder = t / image.ImageInfo.Heads, - Head = t % image.ImageInfo.Heads, + Cylinder = t / image.Info.Heads, + Head = t % image.Info.Heads, Image = new ImageType {format = dfiImage.ImageFormat, Value = Path.GetFileName(dfiFilePath)} }; - if(dfiBlockTrackType.Cylinder < image.ImageInfo.Cylinders) + if(dfiBlockTrackType.Cylinder < image.Info.Cylinders) { dfiBlockTrackType.StartSector = currentSector; - currentSector += image.ImageInfo.SectorsPerTrack; + currentSector += image.Info.SectorsPerTrack; dfiBlockTrackType.EndSector = currentSector - 1; - dfiBlockTrackType.Sectors = image.ImageInfo.SectorsPerTrack; - dfiBlockTrackType.BytesPerSector = (int)image.ImageInfo.SectorSize; + dfiBlockTrackType.Sectors = image.Info.SectorsPerTrack; + dfiBlockTrackType.BytesPerSector = (int)image.Info.SectorSize; dfiBlockTrackType.Format = trkFormat; } @@ -756,11 +757,11 @@ namespace DiscImageChef.Core else DicConsole .ErrorWriteLine("DiscFerret image do not contain same number of tracks ({0}) than disk image ({1}), ignoring...", - dfiImage.ImageInfo.Cylinders, image.ImageInfo.Cylinders); + dfiImage.Info.Cylinders, image.Info.Cylinders); else DicConsole .ErrorWriteLine("DiscFerret image do not contain same number of heads ({0}) than disk image ({1}), ignoring...", - dfiImage.ImageInfo.Heads, image.ImageInfo.Heads); + dfiImage.Info.Heads, image.Info.Heads); #endregion // TODO: Implement support for getting CHS from SCSI mode pages diff --git a/DiscImageChef.Core/Sidecar/LinearMedia.cs b/DiscImageChef.Core/Sidecar/LinearMedia.cs index 9f17c93d..11603121 100644 --- a/DiscImageChef.Core/Sidecar/LinearMedia.cs +++ b/DiscImageChef.Core/Sidecar/LinearMedia.cs @@ -33,6 +33,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Text; using DiscImageChef.DiscImages; using Schemas; @@ -51,8 +52,8 @@ namespace DiscImageChef.Core /// Image plugins /// List of image checksums /// Metadata sidecar - static void LinearMedia(ImagePlugin image, Guid filterId, string imagePath, FileInfo fi, PluginBase plugins, - List imgChecksums, ref CICMMetadataType sidecar) + static void LinearMedia(IMediaImage image, Guid filterId, string imagePath, FileInfo fi, PluginBase plugins, + List imgChecksums, ref CICMMetadataType sidecar, Encoding encoding) { sidecar.LinearMedia = new[] { diff --git a/DiscImageChef.Core/Sidecar/OpticalDisc.cs b/DiscImageChef.Core/Sidecar/OpticalDisc.cs index 9acfc0e3..3820cadf 100644 --- a/DiscImageChef.Core/Sidecar/OpticalDisc.cs +++ b/DiscImageChef.Core/Sidecar/OpticalDisc.cs @@ -33,6 +33,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Text; using DiscImageChef.CommonTypes; using DiscImageChef.Decoders.CD; using DiscImageChef.Decoders.DVD; @@ -57,8 +58,8 @@ namespace DiscImageChef.Core /// Image plugins /// List of image checksums /// Metadata sidecar - static void OpticalDisc(ImagePlugin image, Guid filterId, string imagePath, FileInfo fi, PluginBase plugins, - List imgChecksums, ref CICMMetadataType sidecar) + static void OpticalDisc(IMediaImage image, Guid filterId, string imagePath, FileInfo fi, PluginBase plugins, + List imgChecksums, ref CICMMetadataType sidecar, Encoding encoding) { sidecar.OpticalDisc = new[] { @@ -73,14 +74,14 @@ namespace DiscImageChef.Core Value = Path.GetFileName(imagePath) }, Size = fi.Length, - Sequence = new SequenceType {MediaTitle = image.ImageInfo.MediaTitle} + Sequence = new SequenceType {MediaTitle = image.Info.MediaTitle} } }; - if(image.ImageInfo.MediaSequence != 0 && image.ImageInfo.LastMediaSequence != 0) + if(image.Info.MediaSequence != 0 && image.Info.LastMediaSequence != 0) { - sidecar.OpticalDisc[0].Sequence.MediaSequence = image.ImageInfo.MediaSequence; - sidecar.OpticalDisc[0].Sequence.TotalMedia = image.ImageInfo.LastMediaSequence; + sidecar.OpticalDisc[0].Sequence.MediaSequence = image.Info.MediaSequence; + sidecar.OpticalDisc[0].Sequence.TotalMedia = image.Info.LastMediaSequence; } else { @@ -88,9 +89,9 @@ namespace DiscImageChef.Core sidecar.OpticalDisc[0].Sequence.TotalMedia = 1; } - MediaType dskType = image.ImageInfo.MediaType; + MediaType dskType = image.Info.MediaType; - foreach(MediaTagType tagType in image.ImageInfo.ReadableMediaTags) + foreach(MediaTagType tagType in image.Info.ReadableMediaTags) switch(tagType) { case MediaTagType.CD_ATIP: @@ -341,7 +342,7 @@ namespace DiscImageChef.Core ulong doneSectors = 0; // If there is only one track, and it's the same as the image file (e.g. ".iso" files), don't re-checksum. - if(image.PluginUuid == new Guid("12345678-AAAA-BBBB-CCCC-123456789000") && + if(image.Id == new Guid("12345678-AAAA-BBBB-CCCC-123456789000") && // Only if filter is none... (filterId == new Guid("12345678-AAAA-BBBB-CCCC-123456789000") || // ...or AppleDouble @@ -483,16 +484,16 @@ namespace DiscImageChef.Core }; List lstFs = new List(); - foreach(Filesystem plugin in plugins.PluginsList.Values) + foreach(IFilesystem plugin in plugins.PluginsList.Values) try { if(!plugin.Identify(image, partitions[i])) continue; - plugin.GetInformation(image, partitions[i], out _); - lstFs.Add(plugin.XmlFSType); - Statistics.AddFilesystem(plugin.XmlFSType.Type); + plugin.GetInformation(image, partitions[i], out _, encoding); + lstFs.Add(plugin.XmlFsType); + Statistics.AddFilesystem(plugin.XmlFsType.Type); - switch(plugin.XmlFSType.Type) + switch(plugin.XmlFsType.Type) { case "Opera": dskType = MediaType.ThreeDO; @@ -535,16 +536,16 @@ namespace DiscImageChef.Core Size = (ulong)xmlTrk.Size, Sequence = (ulong)xmlTrk.Sequence.TrackNumber }; - foreach(Filesystem plugin in plugins.PluginsList.Values) + foreach(IFilesystem plugin in plugins.PluginsList.Values) try { if(!plugin.Identify(image, xmlPart)) continue; - plugin.GetInformation(image, xmlPart, out _); - lstFs.Add(plugin.XmlFSType); - Statistics.AddFilesystem(plugin.XmlFSType.Type); + plugin.GetInformation(image, xmlPart, out _, encoding); + lstFs.Add(plugin.XmlFsType); + Statistics.AddFilesystem(plugin.XmlFsType.Type); - switch(plugin.XmlFSType.Type) + switch(plugin.XmlFsType.Type) { case "Opera": dskType = MediaType.ThreeDO; @@ -593,23 +594,23 @@ namespace DiscImageChef.Core sidecar.OpticalDisc[0].DiscSubType = dscSubType; Statistics.AddMedia(dskType, false); - if(!string.IsNullOrEmpty(image.ImageInfo.DriveManufacturer) || - !string.IsNullOrEmpty(image.ImageInfo.DriveModel) || - !string.IsNullOrEmpty(image.ImageInfo.DriveFirmwareRevision) || - !string.IsNullOrEmpty(image.ImageInfo.DriveSerialNumber)) + if(!string.IsNullOrEmpty(image.Info.DriveManufacturer) || + !string.IsNullOrEmpty(image.Info.DriveModel) || + !string.IsNullOrEmpty(image.Info.DriveFirmwareRevision) || + !string.IsNullOrEmpty(image.Info.DriveSerialNumber)) sidecar.OpticalDisc[0].DumpHardwareArray = new[] { new DumpHardwareType { - Extents = new[] {new ExtentType {Start = 0, End = image.ImageInfo.Sectors}}, - Manufacturer = image.ImageInfo.DriveManufacturer, - Model = image.ImageInfo.DriveModel, - Firmware = image.ImageInfo.DriveFirmwareRevision, - Serial = image.ImageInfo.DriveSerialNumber, + Extents = new[] {new ExtentType {Start = 0, End = image.Info.Sectors}}, + Manufacturer = image.Info.DriveManufacturer, + Model = image.Info.DriveModel, + Firmware = image.Info.DriveFirmwareRevision, + Serial = image.Info.DriveSerialNumber, Software = new SoftwareType { - Name = image.ImageInfo.Application, - Version = image.ImageInfo.ApplicationVersion + Name = image.Info.Application, + Version = image.Info.ApplicationVersion } } }; diff --git a/DiscImageChef.Core/Sidecar/Sidecar.cs b/DiscImageChef.Core/Sidecar/Sidecar.cs index 17624174..078af7c4 100644 --- a/DiscImageChef.Core/Sidecar/Sidecar.cs +++ b/DiscImageChef.Core/Sidecar/Sidecar.cs @@ -49,11 +49,11 @@ namespace DiscImageChef.Core /// Filter uuid /// Encoding for analysis /// The metadata sidecar - public static CICMMetadataType Create(ImagePlugin image, string imagePath, Guid filterId, Encoding encoding) + public static CICMMetadataType Create(IMediaImage image, string imagePath, Guid filterId, Encoding encoding) { CICMMetadataType sidecar = new CICMMetadataType(); PluginBase plugins = new PluginBase(); - plugins.RegisterAllPlugins(encoding); + plugins.RegisterAllPlugins(); FileInfo fi = new FileInfo(imagePath); FileStream fs = new FileStream(imagePath, FileMode.Open, FileAccess.Read); @@ -93,19 +93,19 @@ namespace DiscImageChef.Core List imgChecksums = imgChkWorker.End(); - switch(image.ImageInfo.XmlMediaType) + switch(image.Info.XmlMediaType) { case XmlMediaType.OpticalDisc: - OpticalDisc(image, filterId, imagePath, fi, plugins, imgChecksums, ref sidecar); + OpticalDisc(image, filterId, imagePath, fi, plugins, imgChecksums, ref sidecar, encoding); break; case XmlMediaType.BlockMedia: - BlockMedia(image, filterId, imagePath, fi, plugins, imgChecksums, ref sidecar); + BlockMedia(image, filterId, imagePath, fi, plugins, imgChecksums, ref sidecar, encoding); break; case XmlMediaType.LinearMedia: - LinearMedia(image, filterId, imagePath, fi, plugins, imgChecksums, ref sidecar); + LinearMedia(image, filterId, imagePath, fi, plugins, imgChecksums, ref sidecar, encoding); break; case XmlMediaType.AudioMedia: - AudioMedia(image, filterId, imagePath, fi, plugins, imgChecksums, ref sidecar); + AudioMedia(image, filterId, imagePath, fi, plugins, imgChecksums, ref sidecar, encoding); break; } diff --git a/DiscImageChef.DiscImages/Alcohol120.cs b/DiscImageChef.DiscImages/Alcohol120.cs index 36719518..c41da625 100644 --- a/DiscImageChef.DiscImages/Alcohol120.cs +++ b/DiscImageChef.DiscImages/Alcohol120.cs @@ -47,10 +47,10 @@ using DMI = DiscImageChef.Decoders.Xbox.DMI; namespace DiscImageChef.DiscImages { - public class Alcohol120 : ImagePlugin + public class Alcohol120 : IMediaImage { AlcoholFooter alcFooter; - Filter alcImage; + IFilter alcImage; Dictionary alcSessions; Dictionary> alcToc; Dictionary alcTrackExtras; @@ -58,6 +58,7 @@ namespace DiscImageChef.DiscImages byte[] bca; byte[] dmi; byte[] fullToc; + ImageInfo imageInfo; Stream imageStream; bool isDvd; Dictionary offsetmap; @@ -67,9 +68,7 @@ namespace DiscImageChef.DiscImages public Alcohol120() { - Name = "Alcohol 120% Media Descriptor Structure"; - PluginUuid = new Guid("A78FBEBA-0307-4915-BDE3-B8A3B57F843F"); - ImageInfo = new ImageInfo + imageInfo = new ImageInfo { ReadableSectorTags = new List(), ReadableMediaTags = new List(), @@ -94,11 +93,15 @@ namespace DiscImageChef.DiscImages }; } - public override string ImageFormat => "Alcohol 120% Media Descriptor Structure"; + public virtual ImageInfo Info => imageInfo; + public virtual string Name => "Alcohol 120% Media Descriptor Structure"; + public virtual Guid Id => new Guid("A78FBEBA-0307-4915-BDE3-B8A3B57F843F"); - public override List Partitions => partitions; + public virtual string ImageFormat => "Alcohol 120% Media Descriptor Structure"; - public override List Tracks + public virtual List Partitions => partitions; + + public virtual List Tracks { get { @@ -151,9 +154,9 @@ namespace DiscImageChef.DiscImages } } - public override List Sessions => sessions; + public virtual List Sessions => sessions; - public override bool IdentifyImage(Filter imageFilter) + public virtual bool IdentifyImage(IFilter imageFilter) { Stream stream = imageFilter.GetDataForkStream(); stream.Seek(0, SeekOrigin.Begin); @@ -169,7 +172,7 @@ namespace DiscImageChef.DiscImages return header.signature == "MEDIA DESCRIPTO"; } - public override bool OpenImage(Filter imageFilter) + public virtual bool OpenImage(IFilter imageFilter) { Stream stream = imageFilter.GetDataForkStream(); stream.Seek(0, SeekOrigin.Begin); @@ -387,12 +390,12 @@ namespace DiscImageChef.DiscImages { case AlcoholMediumType.DVD: case AlcoholMediumType.DVDR: - ImageInfo.ReadableMediaTags.Add(MediaTagType.DVD_BCA); + imageInfo.ReadableMediaTags.Add(MediaTagType.DVD_BCA); break; } } - ImageInfo.MediaType = AlcoholMediumTypeToMediaType(header.type); + imageInfo.MediaType = AlcoholMediumTypeToMediaType(header.type); if(isDvd) { @@ -422,55 +425,55 @@ namespace DiscImageChef.DiscImages switch(pfi0.Value.DiskCategory) { case DiskCategory.DVDPR: - ImageInfo.MediaType = MediaType.DVDPR; + imageInfo.MediaType = MediaType.DVDPR; break; case DiskCategory.DVDPRDL: - ImageInfo.MediaType = MediaType.DVDPRDL; + imageInfo.MediaType = MediaType.DVDPRDL; break; case DiskCategory.DVDPRW: - ImageInfo.MediaType = MediaType.DVDPRW; + imageInfo.MediaType = MediaType.DVDPRW; break; case DiskCategory.DVDPRWDL: - ImageInfo.MediaType = MediaType.DVDPRWDL; + imageInfo.MediaType = MediaType.DVDPRWDL; break; case DiskCategory.DVDR: - ImageInfo.MediaType = pfi0.Value.PartVersion == 6 ? MediaType.DVDRDL : MediaType.DVDR; + imageInfo.MediaType = pfi0.Value.PartVersion == 6 ? MediaType.DVDRDL : MediaType.DVDR; break; case DiskCategory.DVDRAM: - ImageInfo.MediaType = MediaType.DVDRAM; + imageInfo.MediaType = MediaType.DVDRAM; break; default: - ImageInfo.MediaType = MediaType.DVDROM; + imageInfo.MediaType = MediaType.DVDROM; break; case DiskCategory.DVDRW: - ImageInfo.MediaType = pfi0.Value.PartVersion == 3 ? MediaType.DVDRWDL : MediaType.DVDRW; + imageInfo.MediaType = pfi0.Value.PartVersion == 3 ? MediaType.DVDRWDL : MediaType.DVDRW; break; case DiskCategory.HDDVDR: - ImageInfo.MediaType = MediaType.HDDVDR; + imageInfo.MediaType = MediaType.HDDVDR; break; case DiskCategory.HDDVDRAM: - ImageInfo.MediaType = MediaType.HDDVDRAM; + imageInfo.MediaType = MediaType.HDDVDRAM; break; case DiskCategory.HDDVDROM: - ImageInfo.MediaType = MediaType.HDDVDROM; + imageInfo.MediaType = MediaType.HDDVDROM; break; case DiskCategory.HDDVDRW: - ImageInfo.MediaType = MediaType.HDDVDRW; + imageInfo.MediaType = MediaType.HDDVDRW; break; case DiskCategory.Nintendo: - ImageInfo.MediaType = + imageInfo.MediaType = pfi0.Value.DiscSize == DVDSize.Eighty ? MediaType.GOD : MediaType.WOD; break; case DiskCategory.UMD: - ImageInfo.MediaType = MediaType.UMD; + imageInfo.MediaType = MediaType.UMD; break; } - if(DMI.IsXbox(dmi)) ImageInfo.MediaType = MediaType.XGD; - else if(DMI.IsXbox360(dmi)) ImageInfo.MediaType = MediaType.XGD2; + if(DMI.IsXbox(dmi)) imageInfo.MediaType = MediaType.XGD; + else if(DMI.IsXbox360(dmi)) imageInfo.MediaType = MediaType.XGD2; - ImageInfo.ReadableMediaTags.Add(MediaTagType.DVD_PFI); - ImageInfo.ReadableMediaTags.Add(MediaTagType.DVD_DMI); + imageInfo.ReadableMediaTags.Add(MediaTagType.DVD_PFI); + imageInfo.ReadableMediaTags.Add(MediaTagType.DVD_DMI); } } } @@ -506,14 +509,14 @@ namespace DiscImageChef.DiscImages } } - if(!data && !firstdata) ImageInfo.MediaType = MediaType.CDDA; - else if(firstaudio && data && sessions.Count > 1 && mode2) ImageInfo.MediaType = MediaType.CDPLUS; - else if(firstdata && audio || mode2) ImageInfo.MediaType = MediaType.CDROMXA; - else if(!audio) ImageInfo.MediaType = MediaType.CDROM; - else ImageInfo.MediaType = MediaType.CD; + if(!data && !firstdata) imageInfo.MediaType = MediaType.CDDA; + else if(firstaudio && data && sessions.Count > 1 && mode2) imageInfo.MediaType = MediaType.CDPLUS; + else if(firstdata && audio || mode2) imageInfo.MediaType = MediaType.CDROMXA; + else if(!audio) imageInfo.MediaType = MediaType.CDROM; + else imageInfo.MediaType = MediaType.CD; } - DicConsole.DebugWriteLine("Alcohol 120% plugin", "ImageInfo.mediaType = {0}", ImageInfo.MediaType); + DicConsole.DebugWriteLine("Alcohol 120% plugin", "ImageInfo.mediaType = {0}", imageInfo.MediaType); sessions = new List(); foreach(AlcoholSession alcSes in alcSessions.Values) @@ -553,7 +556,7 @@ namespace DiscImageChef.DiscImages }; partitions.Add(partition); - ImageInfo.Sectors += extra.sectors; + imageInfo.Sectors += extra.sectors; byteOffset += partition.Size; } @@ -564,45 +567,45 @@ namespace DiscImageChef.DiscImages case AlcoholTrackMode.Mode1: case AlcoholTrackMode.Mode2F1: case AlcoholTrackMode.Mode2F1Alt: - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEcc)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccP)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccQ)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc); - if(ImageInfo.SectorSize < 2048) ImageInfo.SectorSize = 2048; + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEcc)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccP)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccQ)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc); + if(imageInfo.SectorSize < 2048) imageInfo.SectorSize = 2048; break; case AlcoholTrackMode.Mode2: - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); - if(ImageInfo.SectorSize < 2336) ImageInfo.SectorSize = 2336; + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); + if(imageInfo.SectorSize < 2336) imageInfo.SectorSize = 2336; break; case AlcoholTrackMode.Mode2F2: - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc); - if(ImageInfo.SectorSize < 2324) ImageInfo.SectorSize = 2324; + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc); + if(imageInfo.SectorSize < 2324) imageInfo.SectorSize = 2324; break; case AlcoholTrackMode.DVD: - ImageInfo.SectorSize = 2048; + imageInfo.SectorSize = 2048; break; default: - ImageInfo.SectorSize = 2352; + imageInfo.SectorSize = 2352; break; } } @@ -620,7 +623,7 @@ namespace DiscImageChef.DiscImages DicConsole.DebugWriteLine("Alcohol 120% plugin", "\tPartition size in bytes: {0}", partition.Size); } - ImageInfo.Application = "Alcohol 120%"; + imageInfo.Application = "Alcohol 120%"; DicConsole.DebugWriteLine("Alcohol 120% plugin", "Data filename: {0}", alcFile); @@ -629,11 +632,11 @@ namespace DiscImageChef.DiscImages if(alcImage == null) throw new Exception("Cannot open data file"); - ImageInfo.ImageSize = (ulong)alcImage.GetDataForkLength(); - ImageInfo.CreationTime = alcImage.GetCreationTime(); - ImageInfo.LastModificationTime = alcImage.GetLastWriteTime(); - ImageInfo.XmlMediaType = XmlMediaType.OpticalDisc; - ImageInfo.Version = $"{header.version[0]}.{header.version[1]}"; + imageInfo.ImageSize = (ulong)alcImage.GetDataForkLength(); + imageInfo.CreationTime = alcImage.GetCreationTime(); + imageInfo.LastModificationTime = alcImage.GetLastWriteTime(); + imageInfo.XmlMediaType = XmlMediaType.OpticalDisc; + imageInfo.Version = $"{header.version[0]}.{header.version[1]}"; if(!isDvd) { @@ -678,23 +681,23 @@ namespace DiscImageChef.DiscImages DicConsole.DebugWriteLine("Alcohol 120% plugin", "TOC not correctly rebuilt"); fullToc = null; } - else ImageInfo.ReadableMediaTags.Add(MediaTagType.CD_FullTOC); + else imageInfo.ReadableMediaTags.Add(MediaTagType.CD_FullTOC); - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackFlags); + imageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackFlags); } - if(ImageInfo.MediaType == MediaType.XGD2) - if(ImageInfo.Sectors == 25063 || // Locked (or non compatible drive) - ImageInfo.Sectors == 4229664 || // Xtreme unlock - ImageInfo.Sectors == 4246304) // Wxripper unlock - ImageInfo.MediaType = MediaType.XGD3; + if(imageInfo.MediaType == MediaType.XGD2) + if(imageInfo.Sectors == 25063 || // Locked (or non compatible drive) + imageInfo.Sectors == 4229664 || // Xtreme unlock + imageInfo.Sectors == 4246304) // Wxripper unlock + imageInfo.MediaType = MediaType.XGD3; - DicConsole.VerboseWriteLine("Alcohol 120% image describes a disc of type {0}", ImageInfo.MediaType); + DicConsole.VerboseWriteLine("Alcohol 120% image describes a disc of type {0}", imageInfo.MediaType); return true; } - public override byte[] ReadDiskTag(MediaTagType tag) + public virtual byte[] ReadDiskTag(MediaTagType tag) { switch(tag) { @@ -727,27 +730,27 @@ namespace DiscImageChef.DiscImages } } - public override byte[] ReadSector(ulong sectorAddress) + public virtual byte[] ReadSector(ulong sectorAddress) { return ReadSectors(sectorAddress, 1); } - public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag) + public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag) { return ReadSectorsTag(sectorAddress, 1, tag); } - public override byte[] ReadSector(ulong sectorAddress, uint track) + public virtual byte[] ReadSector(ulong sectorAddress, uint track) { return ReadSectors(sectorAddress, 1, track); } - public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag) + public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag) { return ReadSectorsTag(sectorAddress, 1, track, tag); } - public override byte[] ReadSectors(ulong sectorAddress, uint length) + public virtual byte[] ReadSectors(ulong sectorAddress, uint length) { foreach(KeyValuePair kvp in offsetmap) if(sectorAddress >= kvp.Value) @@ -763,7 +766,7 @@ namespace DiscImageChef.DiscImages throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found"); } - public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag) + public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag) { foreach(KeyValuePair kvp in offsetmap) if(sectorAddress >= kvp.Value) @@ -779,7 +782,7 @@ namespace DiscImageChef.DiscImages throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found"); } - public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track) + public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track) { if(!alcTracks.TryGetValue((int)track, out AlcoholTrack alcTrack) || !alcTrackExtras.TryGetValue((int)track, out AlcoholTrackExtra alcExtra)) @@ -872,7 +875,7 @@ namespace DiscImageChef.DiscImages return buffer; } - public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag) + public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag) { if(!alcTracks.TryGetValue((int)track, out AlcoholTrack alcTrack) || !alcTrackExtras.TryGetValue((int)track, out AlcoholTrackExtra alcExtra)) @@ -1195,17 +1198,17 @@ namespace DiscImageChef.DiscImages return buffer; } - public override byte[] ReadSectorLong(ulong sectorAddress) + public virtual byte[] ReadSectorLong(ulong sectorAddress) { return ReadSectorsLong(sectorAddress, 1); } - public override byte[] ReadSectorLong(ulong sectorAddress, uint track) + public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track) { return ReadSectorsLong(sectorAddress, 1, track); } - public override byte[] ReadSectorsLong(ulong sectorAddress, uint length) + public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length) { foreach(KeyValuePair kvp in offsetmap) if(sectorAddress >= kvp.Value) @@ -1221,7 +1224,7 @@ namespace DiscImageChef.DiscImages throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found"); } - public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track) + public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track) { if(!alcTracks.TryGetValue((int)track, out AlcoholTrack alcTrack) || !alcTrackExtras.TryGetValue((int)track, out AlcoholTrackExtra alcExtra)) @@ -1263,14 +1266,14 @@ namespace DiscImageChef.DiscImages return buffer; } - public override List GetSessionTracks(Session session) + public virtual List GetSessionTracks(Session session) { if(sessions.Contains(session)) return GetSessionTracks(session.SessionSequence); throw new ImageNotSupportedException("Session does not exist in disc image"); } - public override List GetSessionTracks(ushort session) + public virtual List GetSessionTracks(ushort session) { List tracks = new List(); @@ -1321,19 +1324,19 @@ namespace DiscImageChef.DiscImages return tracks; } - public override bool? VerifySector(ulong sectorAddress) + public virtual bool? VerifySector(ulong sectorAddress) { byte[] buffer = ReadSectorLong(sectorAddress); return CdChecksums.CheckCdSector(buffer); } - public override bool? VerifySector(ulong sectorAddress, uint track) + public virtual bool? VerifySector(ulong sectorAddress, uint track) { byte[] buffer = ReadSectorLong(sectorAddress, track); return CdChecksums.CheckCdSector(buffer); } - public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas, + public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas, out List unknownLbas) { byte[] buffer = ReadSectorsLong(sectorAddress, length); @@ -1363,7 +1366,7 @@ namespace DiscImageChef.DiscImages return failingLbas.Count <= 0; } - public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas, + public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas, out List unknownLbas) { byte[] buffer = ReadSectorsLong(sectorAddress, length, track); @@ -1393,7 +1396,7 @@ namespace DiscImageChef.DiscImages return failingLbas.Count <= 0; } - public override bool? VerifyMediaImage() + public virtual bool? VerifyMediaImage() { return null; } diff --git a/DiscImageChef.DiscImages/Anex86.cs b/DiscImageChef.DiscImages/Anex86.cs index 4a38f064..956203ab 100644 --- a/DiscImageChef.DiscImages/Anex86.cs +++ b/DiscImageChef.DiscImages/Anex86.cs @@ -40,16 +40,15 @@ using DiscImageChef.Filters; namespace DiscImageChef.DiscImages { - public class Anex86 : ImagePlugin + public class Anex86 : IMediaImage { - Filter anexImageFilter; + IFilter anexImageFilter; Anex86Header fdihdr; + ImageInfo imageInfo; public Anex86() { - Name = "Anex86 Disk Image"; - PluginUuid = new Guid("0410003E-6E7B-40E6-9328-BA5651ADF6B7"); - ImageInfo = new ImageInfo + imageInfo = new ImageInfo { ReadableSectorTags = new List(), ReadableMediaTags = new List(), @@ -74,18 +73,23 @@ namespace DiscImageChef.DiscImages }; } - public override string ImageFormat => "Anex86 disk image"; + public virtual ImageInfo Info => imageInfo; - public override List Partitions => + public virtual string Name => "Anex86 Disk Image"; + public virtual Guid Id => new Guid("0410003E-6E7B-40E6-9328-BA5651ADF6B7"); + + public virtual string ImageFormat => "Anex86 disk image"; + + public virtual List Partitions => throw new FeatureUnsupportedImageException("Feature not supported by image format"); - public override List Tracks => + public virtual List Tracks => throw new FeatureUnsupportedImageException("Feature not supported by image format"); - public override List Sessions => + public virtual List Sessions => throw new FeatureUnsupportedImageException("Feature not supported by image format"); - public override bool IdentifyImage(Filter imageFilter) + public virtual bool IdentifyImage(IFilter imageFilter) { Stream stream = imageFilter.GetDataForkStream(); stream.Seek(0, SeekOrigin.Begin); @@ -114,7 +118,7 @@ namespace DiscImageChef.DiscImages fdihdr.dskSize == fdihdr.bps * fdihdr.spt * fdihdr.heads * fdihdr.cylinders; } - public override bool OpenImage(Filter imageFilter) + public virtual bool OpenImage(IFilter imageFilter) { Stream stream = imageFilter.GetDataForkStream(); stream.Seek(0, SeekOrigin.Begin); @@ -130,7 +134,7 @@ namespace DiscImageChef.DiscImages fdihdr = (Anex86Header)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(Anex86Header)); handle.Free(); - ImageInfo.MediaType = MediaType.GENERIC_HDD; + imageInfo.MediaType = MediaType.GENERIC_HDD; switch(fdihdr.cylinders) { @@ -144,10 +148,10 @@ namespace DiscImageChef.DiscImages switch(fdihdr.heads) { case 1: - ImageInfo.MediaType = MediaType.DOS_525_SS_DD_8; + imageInfo.MediaType = MediaType.DOS_525_SS_DD_8; break; case 2: - ImageInfo.MediaType = MediaType.DOS_525_DS_DD_8; + imageInfo.MediaType = MediaType.DOS_525_DS_DD_8; break; } @@ -156,10 +160,10 @@ namespace DiscImageChef.DiscImages switch(fdihdr.heads) { case 1: - ImageInfo.MediaType = MediaType.DOS_525_SS_DD_9; + imageInfo.MediaType = MediaType.DOS_525_SS_DD_9; break; case 2: - ImageInfo.MediaType = MediaType.DOS_525_DS_DD_9; + imageInfo.MediaType = MediaType.DOS_525_DS_DD_9; break; } @@ -177,7 +181,7 @@ namespace DiscImageChef.DiscImages switch(fdihdr.spt) { case 9: - if(fdihdr.heads == 1) ImageInfo.MediaType = MediaType.Apricot_35; + if(fdihdr.heads == 1) imageInfo.MediaType = MediaType.Apricot_35; break; } @@ -192,7 +196,7 @@ namespace DiscImageChef.DiscImages switch(fdihdr.spt) { case 26: - if(fdihdr.heads == 2) ImageInfo.MediaType = MediaType.NEC_8_SD; + if(fdihdr.heads == 2) imageInfo.MediaType = MediaType.NEC_8_SD; break; } @@ -201,7 +205,7 @@ namespace DiscImageChef.DiscImages switch(fdihdr.spt) { case 26: - if(fdihdr.heads == 2) ImageInfo.MediaType = MediaType.NEC_8_DD; + if(fdihdr.heads == 2) imageInfo.MediaType = MediaType.NEC_8_DD; break; } @@ -210,7 +214,7 @@ namespace DiscImageChef.DiscImages switch(fdihdr.spt) { case 8: - if(fdihdr.heads == 1) ImageInfo.MediaType = MediaType.Apricot_35; + if(fdihdr.heads == 1) imageInfo.MediaType = MediaType.Apricot_35; break; } @@ -219,7 +223,7 @@ namespace DiscImageChef.DiscImages switch(fdihdr.spt) { case 8: - if(fdihdr.heads == 2) ImageInfo.MediaType = MediaType.NEC_525_HD; + if(fdihdr.heads == 2) imageInfo.MediaType = MediaType.NEC_525_HD; break; } @@ -237,10 +241,10 @@ namespace DiscImageChef.DiscImages switch(fdihdr.heads) { case 1: - ImageInfo.MediaType = MediaType.NEC_525_SS; + imageInfo.MediaType = MediaType.NEC_525_SS; break; case 2: - ImageInfo.MediaType = MediaType.NEC_525_DS; + imageInfo.MediaType = MediaType.NEC_525_DS; break; } @@ -255,10 +259,10 @@ namespace DiscImageChef.DiscImages switch(fdihdr.heads) { case 1: - ImageInfo.MediaType = MediaType.DOS_35_SS_DD_8; + imageInfo.MediaType = MediaType.DOS_35_SS_DD_8; break; case 2: - ImageInfo.MediaType = MediaType.DOS_35_DS_DD_8; + imageInfo.MediaType = MediaType.DOS_35_DS_DD_8; break; } @@ -267,22 +271,22 @@ namespace DiscImageChef.DiscImages switch(fdihdr.heads) { case 1: - ImageInfo.MediaType = MediaType.DOS_35_SS_DD_9; + imageInfo.MediaType = MediaType.DOS_35_SS_DD_9; break; case 2: - ImageInfo.MediaType = MediaType.DOS_35_DS_DD_9; + imageInfo.MediaType = MediaType.DOS_35_DS_DD_9; break; } break; case 15: - if(fdihdr.heads == 2) ImageInfo.MediaType = MediaType.NEC_35_HD_15; + if(fdihdr.heads == 2) imageInfo.MediaType = MediaType.NEC_35_HD_15; break; case 18: - if(fdihdr.heads == 2) ImageInfo.MediaType = MediaType.DOS_35_HD; + if(fdihdr.heads == 2) imageInfo.MediaType = MediaType.DOS_35_HD; break; case 36: - if(fdihdr.heads == 2) ImageInfo.MediaType = MediaType.DOS_35_ED; + if(fdihdr.heads == 2) imageInfo.MediaType = MediaType.DOS_35_ED; break; } @@ -297,7 +301,7 @@ namespace DiscImageChef.DiscImages switch(fdihdr.spt) { case 38: - if(fdihdr.heads == 2) ImageInfo.MediaType = MediaType.NEC_35_TD; + if(fdihdr.heads == 2) imageInfo.MediaType = MediaType.NEC_35_TD; break; } @@ -307,140 +311,140 @@ namespace DiscImageChef.DiscImages break; } - DicConsole.DebugWriteLine("Anex86 plugin", "MediaType: {0}", ImageInfo.MediaType); + DicConsole.DebugWriteLine("Anex86 plugin", "MediaType: {0}", imageInfo.MediaType); - ImageInfo.ImageSize = (ulong)fdihdr.dskSize; - ImageInfo.CreationTime = imageFilter.GetCreationTime(); - ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime(); - ImageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename()); - ImageInfo.Sectors = (ulong)(fdihdr.cylinders * fdihdr.heads * fdihdr.spt); - ImageInfo.XmlMediaType = XmlMediaType.BlockMedia; - ImageInfo.SectorSize = (uint)fdihdr.bps; - ImageInfo.Cylinders = (uint)fdihdr.cylinders; - ImageInfo.Heads = (uint)fdihdr.heads; - ImageInfo.SectorsPerTrack = (uint)fdihdr.spt; + imageInfo.ImageSize = (ulong)fdihdr.dskSize; + imageInfo.CreationTime = imageFilter.GetCreationTime(); + imageInfo.LastModificationTime = imageFilter.GetLastWriteTime(); + imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename()); + imageInfo.Sectors = (ulong)(fdihdr.cylinders * fdihdr.heads * fdihdr.spt); + imageInfo.XmlMediaType = XmlMediaType.BlockMedia; + imageInfo.SectorSize = (uint)fdihdr.bps; + imageInfo.Cylinders = (uint)fdihdr.cylinders; + imageInfo.Heads = (uint)fdihdr.heads; + imageInfo.SectorsPerTrack = (uint)fdihdr.spt; anexImageFilter = imageFilter; return true; } - public override byte[] ReadSector(ulong sectorAddress) + public virtual byte[] ReadSector(ulong sectorAddress) { return ReadSectors(sectorAddress, 1); } - public override byte[] ReadSectors(ulong sectorAddress, uint length) + public virtual byte[] ReadSectors(ulong sectorAddress, uint length) { - if(sectorAddress > ImageInfo.Sectors - 1) + if(sectorAddress > imageInfo.Sectors - 1) throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found"); - if(sectorAddress + length > ImageInfo.Sectors) + if(sectorAddress + length > imageInfo.Sectors) throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available"); - byte[] buffer = new byte[length * ImageInfo.SectorSize]; + byte[] buffer = new byte[length * imageInfo.SectorSize]; Stream stream = anexImageFilter.GetDataForkStream(); - stream.Seek((long)((ulong)fdihdr.hdrSize + sectorAddress * ImageInfo.SectorSize), SeekOrigin.Begin); + stream.Seek((long)((ulong)fdihdr.hdrSize + sectorAddress * imageInfo.SectorSize), SeekOrigin.Begin); - stream.Read(buffer, 0, (int)(length * ImageInfo.SectorSize)); + stream.Read(buffer, 0, (int)(length * imageInfo.SectorSize)); return buffer; } - public override byte[] ReadDiskTag(MediaTagType tag) + public virtual byte[] ReadDiskTag(MediaTagType tag) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag) + public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSector(ulong sectorAddress, uint track) + public virtual byte[] ReadSector(ulong sectorAddress, uint track) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag) + public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag) + public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track) + public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag) + public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorLong(ulong sectorAddress) + public virtual byte[] ReadSectorLong(ulong sectorAddress) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorLong(ulong sectorAddress, uint track) + public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorsLong(ulong sectorAddress, uint length) + public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track) + public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override List GetSessionTracks(Session session) + public virtual List GetSessionTracks(Session session) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override List GetSessionTracks(ushort session) + public virtual List GetSessionTracks(ushort session) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override bool? VerifySector(ulong sectorAddress) + public virtual bool? VerifySector(ulong sectorAddress) { return null; } - public override bool? VerifySector(ulong sectorAddress, uint track) + public virtual bool? VerifySector(ulong sectorAddress, uint track) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas, + public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas, out List unknownLbas) { failingLbas = new List(); unknownLbas = new List(); - for(ulong i = 0; i < ImageInfo.Sectors; i++) unknownLbas.Add(i); + for(ulong i = 0; i < imageInfo.Sectors; i++) unknownLbas.Add(i); return null; } - public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas, + public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas, out List unknownLbas) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override bool? VerifyMediaImage() + public virtual bool? VerifyMediaImage() { return null; } diff --git a/DiscImageChef.DiscImages/Apple2MG.cs b/DiscImageChef.DiscImages/Apple2MG.cs index 27984952..89fc6c61 100644 --- a/DiscImageChef.DiscImages/Apple2MG.cs +++ b/DiscImageChef.DiscImages/Apple2MG.cs @@ -41,7 +41,7 @@ using DiscImageChef.Filters; namespace DiscImageChef.DiscImages { - public class Apple2Mg : ImagePlugin + public class Apple2Mg : IMediaImage { /// /// Magic number, "2IMG" @@ -84,14 +84,13 @@ namespace DiscImageChef.DiscImages const uint VALID_VOLUME_NUMBER = 0x00000100; const uint VOLUME_NUMBER_MASK = 0x000000FF; - Filter a2MgImageFilter; + IFilter a2MgImageFilter; A2ImgHeader imageHeader; + ImageInfo imageInfo; public Apple2Mg() { - Name = "Apple 2IMG"; - PluginUuid = new Guid("CBAF8824-BA5F-415F-953A-19A03519B2D1"); - ImageInfo = new ImageInfo + imageInfo = new ImageInfo { ReadableSectorTags = new List(), ReadableMediaTags = new List(), @@ -116,18 +115,23 @@ namespace DiscImageChef.DiscImages }; } - public override string ImageFormat => "Apple 2IMG"; + public virtual ImageInfo Info => imageInfo; - public override List Partitions => + public virtual string Name => "Apple 2IMG"; + public virtual Guid Id => new Guid("CBAF8824-BA5F-415F-953A-19A03519B2D1"); + + public virtual string ImageFormat => "Apple 2IMG"; + + public virtual List Partitions => throw new FeatureUnsupportedImageException("Feature not supported by image format"); - public override List Tracks => + public virtual List Tracks => throw new FeatureUnsupportedImageException("Feature not supported by image format"); - public override List Sessions => + public virtual List Sessions => throw new FeatureUnsupportedImageException("Feature not supported by image format"); - public override bool IdentifyImage(Filter imageFilter) + public virtual bool IdentifyImage(IFilter imageFilter) { Stream stream = imageFilter.GetDataForkStream(); stream.Seek(0, SeekOrigin.Begin); @@ -161,7 +165,7 @@ namespace DiscImageChef.DiscImages return creatoroff + creatorsize <= stream.Length; } - public override bool OpenImage(Filter imageFilter) + public virtual bool OpenImage(IFilter imageFilter) { Stream stream = imageFilter.GetDataForkStream(); stream.Seek(0, SeekOrigin.Begin); @@ -237,40 +241,40 @@ namespace DiscImageChef.DiscImages break; } - ImageInfo.SectorSize = (uint)(imageHeader.ImageFormat == PRODOS_SECTOR_ORDER ? 512 : 256); + imageInfo.SectorSize = (uint)(imageHeader.ImageFormat == PRODOS_SECTOR_ORDER ? 512 : 256); - ImageInfo.Sectors = imageHeader.Blocks; - ImageInfo.ImageSize = imageHeader.DataSize; + imageInfo.Sectors = imageHeader.Blocks; + imageInfo.ImageSize = imageHeader.DataSize; switch(imageHeader.Creator) { case CREATOR_ASIMOV: - ImageInfo.Application = "ASIMOV2"; + imageInfo.Application = "ASIMOV2"; break; case CREATOR_BERNIE: - ImageInfo.Application = "Bernie ][ the Rescue"; + imageInfo.Application = "Bernie ][ the Rescue"; break; case CREATOR_CATAKIG: - ImageInfo.Application = "Catakig"; + imageInfo.Application = "Catakig"; break; case CREATOR_SHEPPY: - ImageInfo.Application = "Sheppy's ImageMaker"; + imageInfo.Application = "Sheppy's ImageMaker"; break; case CREATOR_SWEET: - ImageInfo.Application = "Sweet16"; + imageInfo.Application = "Sweet16"; break; case CREATOR_XGS: - ImageInfo.Application = "XGS"; + imageInfo.Application = "XGS"; break; case CREATOR_CIDER: - ImageInfo.Application = "CiderPress"; + imageInfo.Application = "CiderPress"; break; default: - ImageInfo.Application = $"Unknown creator code \"{Encoding.ASCII.GetString(creator)}\""; + imageInfo.Application = $"Unknown creator code \"{Encoding.ASCII.GetString(creator)}\""; break; } - ImageInfo.Version = imageHeader.Version.ToString(); + imageInfo.Version = imageHeader.Version.ToString(); if(imageHeader.CommentOffset != 0 && imageHeader.CommentSize != 0) { @@ -278,55 +282,55 @@ namespace DiscImageChef.DiscImages byte[] comments = new byte[imageHeader.CommentSize]; stream.Read(comments, 0, (int)imageHeader.CommentSize); - ImageInfo.Comments = Encoding.ASCII.GetString(comments); + imageInfo.Comments = Encoding.ASCII.GetString(comments); } - ImageInfo.CreationTime = imageFilter.GetCreationTime(); - ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime(); - ImageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename()); - ImageInfo.MediaType = GetMediaType(); + imageInfo.CreationTime = imageFilter.GetCreationTime(); + imageInfo.LastModificationTime = imageFilter.GetLastWriteTime(); + imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename()); + imageInfo.MediaType = GetMediaType(); a2MgImageFilter = imageFilter; - ImageInfo.XmlMediaType = XmlMediaType.BlockMedia; + imageInfo.XmlMediaType = XmlMediaType.BlockMedia; - DicConsole.VerboseWriteLine("2MG image contains a disk of type {0}", ImageInfo.MediaType); - if(!string.IsNullOrEmpty(ImageInfo.Comments)) - DicConsole.VerboseWriteLine("2MG comments: {0}", ImageInfo.Comments); + DicConsole.VerboseWriteLine("2MG image contains a disk of type {0}", imageInfo.MediaType); + if(!string.IsNullOrEmpty(imageInfo.Comments)) + DicConsole.VerboseWriteLine("2MG comments: {0}", imageInfo.Comments); - switch(ImageInfo.MediaType) + switch(imageInfo.MediaType) { case MediaType.Apple32SS: - ImageInfo.Cylinders = 35; - ImageInfo.Heads = 1; - ImageInfo.SectorsPerTrack = 13; + imageInfo.Cylinders = 35; + imageInfo.Heads = 1; + imageInfo.SectorsPerTrack = 13; break; case MediaType.Apple32DS: - ImageInfo.Cylinders = 35; - ImageInfo.Heads = 2; - ImageInfo.SectorsPerTrack = 13; + imageInfo.Cylinders = 35; + imageInfo.Heads = 2; + imageInfo.SectorsPerTrack = 13; break; case MediaType.Apple33SS: - ImageInfo.Cylinders = 35; - ImageInfo.Heads = 1; - ImageInfo.SectorsPerTrack = 16; + imageInfo.Cylinders = 35; + imageInfo.Heads = 1; + imageInfo.SectorsPerTrack = 16; break; case MediaType.Apple33DS: - ImageInfo.Cylinders = 35; - ImageInfo.Heads = 2; - ImageInfo.SectorsPerTrack = 16; + imageInfo.Cylinders = 35; + imageInfo.Heads = 2; + imageInfo.SectorsPerTrack = 16; break; case MediaType.AppleSonySS: - ImageInfo.Cylinders = 80; - ImageInfo.Heads = 1; + imageInfo.Cylinders = 80; + imageInfo.Heads = 1; // Variable sectors per track, this suffices - ImageInfo.SectorsPerTrack = 10; + imageInfo.SectorsPerTrack = 10; break; case MediaType.AppleSonyDS: - ImageInfo.Cylinders = 80; - ImageInfo.Heads = 2; + imageInfo.Cylinders = 80; + imageInfo.Heads = 2; // Variable sectors per track, this suffices - ImageInfo.SectorsPerTrack = 10; + imageInfo.SectorsPerTrack = 10; break; } @@ -335,7 +339,7 @@ namespace DiscImageChef.DiscImages MediaType GetMediaType() { - switch(ImageInfo.Sectors) + switch(imageInfo.Sectors) { case 455: return MediaType.Apple32SS; case 910: return MediaType.Apple32DS; @@ -347,122 +351,122 @@ namespace DiscImageChef.DiscImages } } - public override byte[] ReadSector(ulong sectorAddress) + public virtual byte[] ReadSector(ulong sectorAddress) { return ReadSectors(sectorAddress, 1); } - public override byte[] ReadSectors(ulong sectorAddress, uint length) + public virtual byte[] ReadSectors(ulong sectorAddress, uint length) { - if(sectorAddress > ImageInfo.Sectors - 1) + if(sectorAddress > imageInfo.Sectors - 1) throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found"); - if(sectorAddress + length > ImageInfo.Sectors) + if(sectorAddress + length > imageInfo.Sectors) throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available"); - byte[] buffer = new byte[length * ImageInfo.SectorSize]; + byte[] buffer = new byte[length * imageInfo.SectorSize]; Stream stream = a2MgImageFilter.GetDataForkStream(); - stream.Seek((long)(imageHeader.DataOffset + sectorAddress * ImageInfo.SectorSize), SeekOrigin.Begin); + stream.Seek((long)(imageHeader.DataOffset + sectorAddress * imageInfo.SectorSize), SeekOrigin.Begin); - stream.Read(buffer, 0, (int)(length * ImageInfo.SectorSize)); + stream.Read(buffer, 0, (int)(length * imageInfo.SectorSize)); return buffer; } - public override byte[] ReadDiskTag(MediaTagType tag) + public virtual byte[] ReadDiskTag(MediaTagType tag) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag) + public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSector(ulong sectorAddress, uint track) + public virtual byte[] ReadSector(ulong sectorAddress, uint track) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag) + public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag) + public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track) + public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag) + public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorLong(ulong sectorAddress) + public virtual byte[] ReadSectorLong(ulong sectorAddress) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorLong(ulong sectorAddress, uint track) + public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorsLong(ulong sectorAddress, uint length) + public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track) + public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override List GetSessionTracks(Session session) + public virtual List GetSessionTracks(Session session) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override List GetSessionTracks(ushort session) + public virtual List GetSessionTracks(ushort session) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override bool? VerifySector(ulong sectorAddress) + public virtual bool? VerifySector(ulong sectorAddress) { return null; } - public override bool? VerifySector(ulong sectorAddress, uint track) + public virtual bool? VerifySector(ulong sectorAddress, uint track) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas, + public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas, out List unknownLbas) { failingLbas = new List(); unknownLbas = new List(); - for(ulong i = 0; i < ImageInfo.Sectors; i++) unknownLbas.Add(i); + for(ulong i = 0; i < imageInfo.Sectors; i++) unknownLbas.Add(i); return null; } - public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas, + public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas, out List unknownLbas) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override bool? VerifyMediaImage() + public virtual bool? VerifyMediaImage() { return null; } diff --git a/DiscImageChef.DiscImages/AppleDOS.cs b/DiscImageChef.DiscImages/AppleDOS.cs index efc4f8fb..19455724 100644 --- a/DiscImageChef.DiscImages/AppleDOS.cs +++ b/DiscImageChef.DiscImages/AppleDOS.cs @@ -39,16 +39,15 @@ using DiscImageChef.Filters; namespace DiscImageChef.DiscImages { // Checked using several images and strings inside Apple's DiskImages.framework - public class AppleDos : ImagePlugin + public class AppleDos : IMediaImage { readonly int[] dosOffsets = {0, 7, 14, 6, 13, 5, 12, 4, 11, 3, 10, 2, 9, 1, 8, 15}; readonly int[] prodosOffsets = {0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15}; + ImageInfo imageInfo; public AppleDos() { - Name = "Apple ][ Interleaved Disk Image"; - PluginUuid = new Guid("A5828AC0-62C9-4304-81D4-EFD4AAE47360"); - ImageInfo = new ImageInfo + imageInfo = new ImageInfo { ReadableSectorTags = new List(), ReadableMediaTags = new List(), @@ -73,24 +72,29 @@ namespace DiscImageChef.DiscImages }; } - public override string ImageFormat => extension == ".po" + public virtual ImageInfo Info => imageInfo; + + public virtual string Name => "Apple ][ Interleaved Disk Image"; + public virtual Guid Id => new Guid("A5828AC0-62C9-4304-81D4-EFD4AAE47360"); + + public virtual string ImageFormat => extension == ".po" ? "Apple ][ Interleaved Disk Image (ProDOS order)" : "Apple ][ Interleaved Disk Image (DOS order)"; - public override List Tracks => + public virtual List Tracks => throw new FeatureUnsupportedImageException("Feature not supported by image format"); - public override List Sessions => + public virtual List Sessions => throw new FeatureUnsupportedImageException("Feature not supported by image format"); - public override bool IdentifyImage(Filter imageFilter) + public virtual bool IdentifyImage(IFilter imageFilter) { extension = Path.GetExtension(imageFilter.GetFilename())?.ToLower(); return imageFilter.GetDataForkLength() == 143360 && (extension == ".po" || extension == ".do"); } - public override bool OpenImage(Filter imageFilter) + public virtual bool OpenImage(IFilter imageFilter) { Stream stream = imageFilter.GetDataForkStream(); stream.Seek(0, SeekOrigin.Begin); @@ -110,52 +114,52 @@ namespace DiscImageChef.DiscImages Array.Copy(tmp, t * 16 * 256 + s * 256, deinterleaved, t * 16 * 256 + offsets[s] * 256, 256); } - ImageInfo.SectorSize = 256; - ImageInfo.ImageSize = (ulong)imageFilter.GetDataForkLength(); - ImageInfo.CreationTime = imageFilter.GetCreationTime(); - ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime(); - ImageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename()); - ImageInfo.Sectors = 560; - ImageInfo.MediaType = MediaType.Apple33SS; - ImageInfo.XmlMediaType = XmlMediaType.BlockMedia; - ImageInfo.Cylinders = 35; - ImageInfo.Heads = 2; - ImageInfo.SectorsPerTrack = 16; + imageInfo.SectorSize = 256; + imageInfo.ImageSize = (ulong)imageFilter.GetDataForkLength(); + imageInfo.CreationTime = imageFilter.GetCreationTime(); + imageInfo.LastModificationTime = imageFilter.GetLastWriteTime(); + imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename()); + imageInfo.Sectors = 560; + imageInfo.MediaType = MediaType.Apple33SS; + imageInfo.XmlMediaType = XmlMediaType.BlockMedia; + imageInfo.Cylinders = 35; + imageInfo.Heads = 2; + imageInfo.SectorsPerTrack = 16; return true; } - public override byte[] ReadSector(ulong sectorAddress) + public virtual byte[] ReadSector(ulong sectorAddress) { return ReadSectors(sectorAddress, 1); } - public override byte[] ReadSectors(ulong sectorAddress, uint length) + public virtual byte[] ReadSectors(ulong sectorAddress, uint length) { - if(sectorAddress > ImageInfo.Sectors - 1) + if(sectorAddress > imageInfo.Sectors - 1) throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found"); - if(sectorAddress + length > ImageInfo.Sectors) + if(sectorAddress + length > imageInfo.Sectors) throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available"); - byte[] buffer = new byte[length * ImageInfo.SectorSize]; + byte[] buffer = new byte[length * imageInfo.SectorSize]; - Array.Copy(deinterleaved, (int)(sectorAddress * ImageInfo.SectorSize), buffer, 0, buffer.Length); + Array.Copy(deinterleaved, (int)(sectorAddress * imageInfo.SectorSize), buffer, 0, buffer.Length); return buffer; } - public override bool? VerifySector(ulong sectorAddress) + public virtual bool? VerifySector(ulong sectorAddress) { return null; } - public override bool? VerifySector(ulong sectorAddress, uint track) + public virtual bool? VerifySector(ulong sectorAddress, uint track) { return null; } - public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas, + public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas, out List unknownLbas) { failingLbas = new List(); @@ -166,7 +170,7 @@ namespace DiscImageChef.DiscImages return null; } - public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas, + public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas, out List unknownLbas) { failingLbas = new List(); @@ -177,37 +181,37 @@ namespace DiscImageChef.DiscImages return null; } - public override bool? VerifyMediaImage() + public virtual bool? VerifyMediaImage() { return null; } - public override List GetSessionTracks(Session session) + public virtual List GetSessionTracks(Session session) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override List GetSessionTracks(ushort session) + public virtual List GetSessionTracks(ushort session) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSector(ulong sectorAddress, uint track) + public virtual byte[] ReadSector(ulong sectorAddress, uint track) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track) + public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorLong(ulong sectorAddress, uint track) + public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track) + public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } @@ -218,40 +222,40 @@ namespace DiscImageChef.DiscImages #endregion #region Unsupported features - public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag) + public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag) + public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorLong(ulong sectorAddress) + public virtual byte[] ReadSectorLong(ulong sectorAddress) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorsLong(ulong sectorAddress, uint length) + public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadDiskTag(MediaTagType tag) + public virtual byte[] ReadDiskTag(MediaTagType tag) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override List Partitions => + public virtual List Partitions => throw new FeatureUnsupportedImageException("Feature not supported by image format"); - public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag) + public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag) + public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } diff --git a/DiscImageChef.DiscImages/AppleNIB.cs b/DiscImageChef.DiscImages/AppleNIB.cs index 6a68ac94..f6c8412a 100644 --- a/DiscImageChef.DiscImages/AppleNIB.cs +++ b/DiscImageChef.DiscImages/AppleNIB.cs @@ -42,7 +42,7 @@ using DiscImageChef.Filters; namespace DiscImageChef.DiscImages { // TODO: Checksum sectors - public class AppleNib : ImagePlugin + public class AppleNib : IMediaImage { readonly byte[] apple3_sign = {0x8D, 0xD0, 0x03, 0x4C, 0xC7, 0xA4}; readonly byte[] cpm_sign = {0xA2, 0x55, 0xA9, 0x00, 0x9D, 0x00, 0x0D, 0xCA}; @@ -61,13 +61,12 @@ namespace DiscImageChef.DiscImages readonly byte[] sos_sign = {0xC9, 0x20, 0xF0, 0x3E}; Dictionary addressFields; Dictionary cookedSectors; + ImageInfo imageInfo; Dictionary longSectors; public AppleNib() { - Name = "Apple NIB"; - PluginUuid = new Guid("AE171AE8-6747-49CC-B861-9D450B7CD42E"); - ImageInfo = new ImageInfo + imageInfo = new ImageInfo { ReadableSectorTags = new List(), ReadableMediaTags = new List(), @@ -92,18 +91,23 @@ namespace DiscImageChef.DiscImages }; } - public override string ImageFormat => "Apple nibbles"; + public virtual ImageInfo Info => imageInfo; - public override List Partitions => + public virtual string Name => "Apple NIB"; + public virtual Guid Id => new Guid("AE171AE8-6747-49CC-B861-9D450B7CD42E"); + + public virtual string ImageFormat => "Apple nibbles"; + + public virtual List Partitions => throw new FeatureUnsupportedImageException("Feature not supported by image format"); - public override List Tracks => + public virtual List Tracks => throw new FeatureUnsupportedImageException("Feature not supported by image format"); - public override List Sessions => + public virtual List Sessions => throw new FeatureUnsupportedImageException("Feature not supported by image format"); - public override bool IdentifyImage(Filter imageFilter) + public virtual bool IdentifyImage(IFilter imageFilter) { Stream stream = imageFilter.GetDataForkStream(); stream.Seek(0, SeekOrigin.Begin); @@ -116,7 +120,7 @@ namespace DiscImageChef.DiscImages return Apple2.IsApple2GCR(test); } - public override bool OpenImage(Filter imageFilter) + public virtual bool OpenImage(IFilter imageFilter) { Stream stream = imageFilter.GetDataForkStream(); stream.Seek(0, SeekOrigin.Begin); @@ -203,15 +207,15 @@ namespace DiscImageChef.DiscImages "Hardware sector {0} of track {1} goes to logical sector {2}", sectorNo, i, skewing[sectorNo] + (ulong)(i * spt)); rawSectors.Add(skewing[sectorNo] + (ulong)(i * spt), sector); - ImageInfo.Sectors++; + imageInfo.Sectors++; } else { - rawSectors.Add(ImageInfo.Sectors, sector); - ImageInfo.Sectors++; + rawSectors.Add(imageInfo.Sectors, sector); + imageInfo.Sectors++; } - DicConsole.DebugWriteLine("Apple NIB Plugin", "Got {0} sectors", ImageInfo.Sectors); + DicConsole.DebugWriteLine("Apple NIB Plugin", "Got {0} sectors", imageInfo.Sectors); DicConsole.DebugWriteLine("Apple NIB Plugin", "Cooking sectors"); @@ -229,27 +233,27 @@ namespace DiscImageChef.DiscImages addressFields.Add(kvp.Key, addr); } - ImageInfo.ImageSize = (ulong)imageFilter.GetDataForkLength(); - ImageInfo.CreationTime = imageFilter.GetCreationTime(); - ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime(); - ImageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename()); - if(ImageInfo.Sectors == 455) ImageInfo.MediaType = MediaType.Apple32SS; - else if(ImageInfo.Sectors == 560) ImageInfo.MediaType = MediaType.Apple33SS; - else ImageInfo.MediaType = MediaType.Unknown; - ImageInfo.SectorSize = 256; - ImageInfo.XmlMediaType = XmlMediaType.BlockMedia; - ImageInfo.ReadableSectorTags.Add(SectorTagType.FloppyAddressMark); - switch(ImageInfo.MediaType) + imageInfo.ImageSize = (ulong)imageFilter.GetDataForkLength(); + imageInfo.CreationTime = imageFilter.GetCreationTime(); + imageInfo.LastModificationTime = imageFilter.GetLastWriteTime(); + imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename()); + if(imageInfo.Sectors == 455) imageInfo.MediaType = MediaType.Apple32SS; + else if(imageInfo.Sectors == 560) imageInfo.MediaType = MediaType.Apple33SS; + else imageInfo.MediaType = MediaType.Unknown; + imageInfo.SectorSize = 256; + imageInfo.XmlMediaType = XmlMediaType.BlockMedia; + imageInfo.ReadableSectorTags.Add(SectorTagType.FloppyAddressMark); + switch(imageInfo.MediaType) { case MediaType.Apple32SS: - ImageInfo.Cylinders = 35; - ImageInfo.Heads = 1; - ImageInfo.SectorsPerTrack = 13; + imageInfo.Cylinders = 35; + imageInfo.Heads = 1; + imageInfo.SectorsPerTrack = 13; break; case MediaType.Apple33SS: - ImageInfo.Cylinders = 35; - ImageInfo.Heads = 1; - ImageInfo.SectorsPerTrack = 16; + imageInfo.Cylinders = 35; + imageInfo.Heads = 1; + imageInfo.SectorsPerTrack = 16; break; } @@ -258,7 +262,7 @@ namespace DiscImageChef.DiscImages MediaType GetMediaType() { - switch(ImageInfo.Sectors) + switch(imageInfo.Sectors) { case 455: return MediaType.Apple32SS; case 560: return MediaType.Apple33SS; @@ -266,9 +270,9 @@ namespace DiscImageChef.DiscImages } } - public override byte[] ReadSector(ulong sectorAddress) + public virtual byte[] ReadSector(ulong sectorAddress) { - if(sectorAddress > ImageInfo.Sectors - 1) + if(sectorAddress > imageInfo.Sectors - 1) throw new ArgumentOutOfRangeException(nameof(sectorAddress), $"Sector address {sectorAddress} not found"); @@ -276,13 +280,13 @@ namespace DiscImageChef.DiscImages return temp; } - public override byte[] ReadSectors(ulong sectorAddress, uint length) + public virtual byte[] ReadSectors(ulong sectorAddress, uint length) { - if(sectorAddress > ImageInfo.Sectors - 1) + if(sectorAddress > imageInfo.Sectors - 1) throw new ArgumentOutOfRangeException(nameof(sectorAddress), $"Sector address {sectorAddress} not found"); - if(sectorAddress + length > ImageInfo.Sectors) + if(sectorAddress + length > imageInfo.Sectors) throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available"); MemoryStream ms = new MemoryStream(); @@ -296,9 +300,9 @@ namespace DiscImageChef.DiscImages return ms.ToArray(); } - public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag) + public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag) { - if(sectorAddress > ImageInfo.Sectors - 1) + if(sectorAddress > imageInfo.Sectors - 1) throw new ArgumentOutOfRangeException(nameof(sectorAddress), $"Sector address {sectorAddress} not found"); @@ -309,13 +313,13 @@ namespace DiscImageChef.DiscImages return temp; } - public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag) + public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag) { - if(sectorAddress > ImageInfo.Sectors - 1) + if(sectorAddress > imageInfo.Sectors - 1) throw new ArgumentOutOfRangeException(nameof(sectorAddress), $"Sector address {sectorAddress} not found"); - if(sectorAddress + length > ImageInfo.Sectors) + if(sectorAddress + length > imageInfo.Sectors) throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available"); if(tag != SectorTagType.FloppyAddressMark) @@ -332,9 +336,9 @@ namespace DiscImageChef.DiscImages return ms.ToArray(); } - public override byte[] ReadSectorLong(ulong sectorAddress) + public virtual byte[] ReadSectorLong(ulong sectorAddress) { - if(sectorAddress > ImageInfo.Sectors - 1) + if(sectorAddress > imageInfo.Sectors - 1) throw new ArgumentOutOfRangeException(nameof(sectorAddress), $"Sector address {sectorAddress} not found"); @@ -342,13 +346,13 @@ namespace DiscImageChef.DiscImages return temp; } - public override byte[] ReadSectorsLong(ulong sectorAddress, uint length) + public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length) { - if(sectorAddress > ImageInfo.Sectors - 1) + if(sectorAddress > imageInfo.Sectors - 1) throw new ArgumentOutOfRangeException(nameof(sectorAddress), $"Sector address {sectorAddress} not found"); - if(sectorAddress + length > ImageInfo.Sectors) + if(sectorAddress + length > imageInfo.Sectors) throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available"); MemoryStream ms = new MemoryStream(); @@ -362,78 +366,78 @@ namespace DiscImageChef.DiscImages return ms.ToArray(); } - public override byte[] ReadDiskTag(MediaTagType tag) + public virtual byte[] ReadDiskTag(MediaTagType tag) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSector(ulong sectorAddress, uint track) + public virtual byte[] ReadSector(ulong sectorAddress, uint track) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag) + public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track) + public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag) + public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorLong(ulong sectorAddress, uint track) + public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track) + public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override List GetSessionTracks(Session session) + public virtual List GetSessionTracks(Session session) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override List GetSessionTracks(ushort session) + public virtual List GetSessionTracks(ushort session) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override bool? VerifySector(ulong sectorAddress) + public virtual bool? VerifySector(ulong sectorAddress) { return null; } - public override bool? VerifySector(ulong sectorAddress, uint track) + public virtual bool? VerifySector(ulong sectorAddress, uint track) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas, + public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas, out List unknownLbas) { failingLbas = new List(); unknownLbas = new List(); - for(ulong i = 0; i < ImageInfo.Sectors; i++) unknownLbas.Add(i); + for(ulong i = 0; i < imageInfo.Sectors; i++) unknownLbas.Add(i); return null; } - public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas, + public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas, out List unknownLbas) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override bool? VerifyMediaImage() + public virtual bool? VerifyMediaImage() { return null; } diff --git a/DiscImageChef.DiscImages/Apridisk.cs b/DiscImageChef.DiscImages/Apridisk.cs index 7463475e..d86be782 100644 --- a/DiscImageChef.DiscImages/Apridisk.cs +++ b/DiscImageChef.DiscImages/Apridisk.cs @@ -41,7 +41,7 @@ using DiscImageChef.Filters; namespace DiscImageChef.DiscImages { - public class Apridisk : ImagePlugin + public class Apridisk : IMediaImage { readonly byte[] signature = { @@ -54,15 +54,14 @@ namespace DiscImageChef.DiscImages 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + ImageInfo imageInfo; // Cylinder by head, sector data matrix byte[][][][] sectorsData; public Apridisk() { - Name = "ACT Apricot Disk Image"; - PluginUuid = new Guid("43408CF3-6DB3-449F-A779-2B0E497C5B14"); - ImageInfo = new ImageInfo + imageInfo = new ImageInfo { ReadableSectorTags = new List(), ReadableMediaTags = new List(), @@ -87,18 +86,23 @@ namespace DiscImageChef.DiscImages }; } - public override string ImageFormat => "ACT Apricot disk image"; + public virtual ImageInfo Info => imageInfo; - public override List Partitions => + public virtual string Name => "ACT Apricot Disk Image"; + public virtual Guid Id => new Guid("43408CF3-6DB3-449F-A779-2B0E497C5B14"); + + public virtual string ImageFormat => "ACT Apricot disk image"; + + public virtual List Partitions => throw new FeatureUnsupportedImageException("Feature not supported by image format"); - public override List Tracks => + public virtual List Tracks => throw new FeatureUnsupportedImageException("Feature not supported by image format"); - public override List Sessions => + public virtual List Sessions => throw new FeatureUnsupportedImageException("Feature not supported by image format"); - public override bool IdentifyImage(Filter imageFilter) + public virtual bool IdentifyImage(IFilter imageFilter) { Stream stream = imageFilter.GetDataForkStream(); stream.Seek(0, SeekOrigin.Begin); @@ -111,7 +115,7 @@ namespace DiscImageChef.DiscImages return sigB.SequenceEqual(signature); } - public override bool OpenImage(Filter imageFilter) + public virtual bool OpenImage(IFilter imageFilter) { Stream stream = imageFilter.GetDataForkStream(); stream.Seek(0, SeekOrigin.Begin); @@ -147,16 +151,16 @@ namespace DiscImageChef.DiscImages stream.Seek(record.headerSize - recordSize, SeekOrigin.Current); byte[] commentB = new byte[record.dataSize]; stream.Read(commentB, 0, commentB.Length); - ImageInfo.Comments = StringHandlers.CToString(commentB); - DicConsole.DebugWriteLine("Apridisk plugin", "Comment: \"{0}\"", ImageInfo.Comments); + imageInfo.Comments = StringHandlers.CToString(commentB); + DicConsole.DebugWriteLine("Apridisk plugin", "Comment: \"{0}\"", imageInfo.Comments); break; case RecordType.Creator: DicConsole.DebugWriteLine("Apridisk plugin", "Found creator record at {0}", stream.Position); stream.Seek(record.headerSize - recordSize, SeekOrigin.Current); byte[] creatorB = new byte[record.dataSize]; stream.Read(creatorB, 0, creatorB.Length); - ImageInfo.Creator = StringHandlers.CToString(creatorB); - DicConsole.DebugWriteLine("Apridisk plugin", "Creator: \"{0}\"", ImageInfo.Creator); + imageInfo.Creator = StringHandlers.CToString(creatorB); + DicConsole.DebugWriteLine("Apridisk plugin", "Creator: \"{0}\"", imageInfo.Creator); break; case RecordType.Sector: if(record.compression != CompressType.Compressed && @@ -193,8 +197,8 @@ namespace DiscImageChef.DiscImages // Total sectors per track uint[][] spts = new uint[totalCylinders][]; - ImageInfo.Cylinders = (ushort)totalCylinders; - ImageInfo.Heads = (byte)totalHeads; + imageInfo.Cylinders = (ushort)totalCylinders; + imageInfo.Heads = (byte)totalHeads; DicConsole.DebugWriteLine("Apridisk plugin", "Found {0} cylinders and {1} heads with a maximum sector number of {2}", @@ -209,7 +213,7 @@ namespace DiscImageChef.DiscImages for(int j = 0; j < totalHeads; j++) sectorsData[i][j] = new byte[maxSector + 1][]; } - ImageInfo.SectorSize = uint.MaxValue; + imageInfo.SectorSize = uint.MaxValue; ulong headersizes = 0; @@ -247,7 +251,7 @@ namespace DiscImageChef.DiscImages realLength = Decompress(data, out sectorsData[record.cylinder][record.head][record.sector]); else sectorsData[record.cylinder][record.head][record.sector] = data; - if(realLength < ImageInfo.SectorSize) ImageInfo.SectorSize = realLength; + if(realLength < imageInfo.SectorSize) imageInfo.SectorSize = realLength; headersizes += record.headerSize + record.dataSize; @@ -256,33 +260,33 @@ namespace DiscImageChef.DiscImages } DicConsole.DebugWriteLine("Apridisk plugin", "Found a minimum of {0} bytes per sector", - ImageInfo.SectorSize); + imageInfo.SectorSize); // Count sectors per track uint spt = uint.MaxValue; - for(ushort cyl = 0; cyl < ImageInfo.Cylinders; cyl++) + for(ushort cyl = 0; cyl < imageInfo.Cylinders; cyl++) { - for(ushort head = 0; head < ImageInfo.Heads; head++) if(spts[cyl][head] < spt) spt = spts[cyl][head]; + for(ushort head = 0; head < imageInfo.Heads; head++) if(spts[cyl][head] < spt) spt = spts[cyl][head]; } - ImageInfo.SectorsPerTrack = spt; + imageInfo.SectorsPerTrack = spt; DicConsole.DebugWriteLine("Apridisk plugin", "Found a minimum of {0} sectors per track", - ImageInfo.SectorsPerTrack); + imageInfo.SectorsPerTrack); - if(ImageInfo.Cylinders == 70 && ImageInfo.Heads == 1 && ImageInfo.SectorsPerTrack == 9) - ImageInfo.MediaType = MediaType.Apricot_35; - else if(ImageInfo.Cylinders == 80 && ImageInfo.Heads == 1 && ImageInfo.SectorsPerTrack == 9) - ImageInfo.MediaType = MediaType.DOS_35_SS_DD_9; - else if(ImageInfo.Cylinders == 80 && ImageInfo.Heads == 2 && ImageInfo.SectorsPerTrack == 9) - ImageInfo.MediaType = MediaType.DOS_35_DS_DD_9; + if(imageInfo.Cylinders == 70 && imageInfo.Heads == 1 && imageInfo.SectorsPerTrack == 9) + imageInfo.MediaType = MediaType.Apricot_35; + else if(imageInfo.Cylinders == 80 && imageInfo.Heads == 1 && imageInfo.SectorsPerTrack == 9) + imageInfo.MediaType = MediaType.DOS_35_SS_DD_9; + else if(imageInfo.Cylinders == 80 && imageInfo.Heads == 2 && imageInfo.SectorsPerTrack == 9) + imageInfo.MediaType = MediaType.DOS_35_DS_DD_9; - ImageInfo.ImageSize = (ulong)stream.Length - headersizes; - ImageInfo.CreationTime = imageFilter.GetCreationTime(); - ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime(); - ImageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename()); - ImageInfo.Sectors = ImageInfo.Cylinders * ImageInfo.Heads * ImageInfo.SectorsPerTrack; - ImageInfo.XmlMediaType = XmlMediaType.BlockMedia; + imageInfo.ImageSize = (ulong)stream.Length - headersizes; + imageInfo.CreationTime = imageFilter.GetCreationTime(); + imageInfo.LastModificationTime = imageFilter.GetLastWriteTime(); + imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename()); + imageInfo.Sectors = imageInfo.Cylinders * imageInfo.Heads * imageInfo.SectorsPerTrack; + imageInfo.XmlMediaType = XmlMediaType.BlockMedia; /* FileStream debugFs = new FileStream("debug.img", FileMode.CreateNew, FileAccess.Write); @@ -318,7 +322,7 @@ namespace DiscImageChef.DiscImages return uLen; } - public override byte[] ReadSector(ulong sectorAddress) + public virtual byte[] ReadSector(ulong sectorAddress) { (ushort cylinder, byte head, byte sector) = LbaToChs(sectorAddress); @@ -334,12 +338,12 @@ namespace DiscImageChef.DiscImages return sectorsData[cylinder][head][sector]; } - public override byte[] ReadSectors(ulong sectorAddress, uint length) + public virtual byte[] ReadSectors(ulong sectorAddress, uint length) { - if(sectorAddress > ImageInfo.Sectors - 1) + if(sectorAddress > imageInfo.Sectors - 1) throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found"); - if(sectorAddress + length > ImageInfo.Sectors) + if(sectorAddress + length > imageInfo.Sectors) throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available"); MemoryStream buffer = new MemoryStream(); @@ -354,105 +358,105 @@ namespace DiscImageChef.DiscImages (ushort cylinder, byte head, byte sector) LbaToChs(ulong lba) { - ushort cylinder = (ushort)(lba / (ImageInfo.Heads * ImageInfo.SectorsPerTrack)); - byte head = (byte)(lba / ImageInfo.SectorsPerTrack % ImageInfo.Heads); - byte sector = (byte)(lba % ImageInfo.SectorsPerTrack + 1); + ushort cylinder = (ushort)(lba / (imageInfo.Heads * imageInfo.SectorsPerTrack)); + byte head = (byte)(lba / imageInfo.SectorsPerTrack % imageInfo.Heads); + byte sector = (byte)(lba % imageInfo.SectorsPerTrack + 1); return (cylinder, head, sector); } - public override byte[] ReadDiskTag(MediaTagType tag) + public virtual byte[] ReadDiskTag(MediaTagType tag) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag) + public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSector(ulong sectorAddress, uint track) + public virtual byte[] ReadSector(ulong sectorAddress, uint track) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag) + public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag) + public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track) + public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag) + public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorLong(ulong sectorAddress) + public virtual byte[] ReadSectorLong(ulong sectorAddress) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorLong(ulong sectorAddress, uint track) + public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorsLong(ulong sectorAddress, uint length) + public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track) + public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override List GetSessionTracks(Session session) + public virtual List GetSessionTracks(Session session) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override List GetSessionTracks(ushort session) + public virtual List GetSessionTracks(ushort session) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override bool? VerifySector(ulong sectorAddress) + public virtual bool? VerifySector(ulong sectorAddress) { return null; } - public override bool? VerifySector(ulong sectorAddress, uint track) + public virtual bool? VerifySector(ulong sectorAddress, uint track) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas, + public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas, out List unknownLbas) { failingLbas = new List(); unknownLbas = new List(); - for(ulong i = 0; i < ImageInfo.Sectors; i++) unknownLbas.Add(i); + for(ulong i = 0; i < imageInfo.Sectors; i++) unknownLbas.Add(i); return null; } - public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas, + public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas, out List unknownLbas) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override bool? VerifyMediaImage() + public virtual bool? VerifyMediaImage() { return null; } diff --git a/DiscImageChef.DiscImages/BLU.cs b/DiscImageChef.DiscImages/BLU.cs index f12798a2..385df80a 100644 --- a/DiscImageChef.DiscImages/BLU.cs +++ b/DiscImageChef.DiscImages/BLU.cs @@ -39,22 +39,21 @@ using DiscImageChef.Filters; namespace DiscImageChef.DiscImages { - public class Blu : ImagePlugin + public class Blu : IMediaImage { const string PROFILE_NAME = "PROFILE "; const string PROFILE10_NAME = "PROFILE 10 "; const string WIDGET_NAME = "WIDGET-10 "; const string PRIAM_NAME = "PRIAMDTATOWER"; - Filter bluImageFilter; + IFilter bluImageFilter; int bptag; BluHeader imageHeader; + ImageInfo imageInfo; public Blu() { - Name = "Basic Lisa Utility"; - PluginUuid = new Guid("A153E2F8-4235-432D-9A7F-20807B0BCD74"); - ImageInfo = new ImageInfo + imageInfo = new ImageInfo { ReadableSectorTags = new List(), ReadableMediaTags = new List(), @@ -79,18 +78,23 @@ namespace DiscImageChef.DiscImages }; } - public override string ImageFormat => "Basic Lisa Utility"; + public virtual ImageInfo Info => imageInfo; - public override List Partitions => + public virtual string Name => "Basic Lisa Utility"; + public virtual Guid Id => new Guid("A153E2F8-4235-432D-9A7F-20807B0BCD74"); + + public virtual string ImageFormat => "Basic Lisa Utility"; + + public virtual List Partitions => throw new FeatureUnsupportedImageException("Feature not supported by image format"); - public override List Tracks => + public virtual List Tracks => throw new FeatureUnsupportedImageException("Feature not supported by image format"); - public override List Sessions => + public virtual List Sessions => throw new FeatureUnsupportedImageException("Feature not supported by image format"); - public override bool IdentifyImage(Filter imageFilter) + public virtual bool IdentifyImage(IFilter imageFilter) { Stream stream = imageFilter.GetDataForkStream(); stream.Seek(0, SeekOrigin.Begin); @@ -113,7 +117,7 @@ namespace DiscImageChef.DiscImages return (tmpHdr.BytesPerBlock & 0xFE00) == 0x200; } - public override bool OpenImage(Filter imageFilter) + public virtual bool OpenImage(IFilter imageFilter) { Stream stream = imageFilter.GetDataForkStream(); stream.Seek(0, SeekOrigin.Begin); @@ -142,10 +146,10 @@ namespace DiscImageChef.DiscImages header = new byte[imageHeader.BytesPerBlock]; stream.Read(header, 0, imageHeader.BytesPerBlock); - ImageInfo.SectorSize = 0x200; + imageInfo.SectorSize = 0x200; - ImageInfo.Sectors = imageHeader.DeviceBlocks; - ImageInfo.ImageSize = imageHeader.DeviceBlocks * imageHeader.BytesPerBlock; + imageInfo.Sectors = imageHeader.DeviceBlocks; + imageInfo.ImageSize = imageHeader.DeviceBlocks * imageHeader.BytesPerBlock; bptag = imageHeader.BytesPerBlock - 0x200; byte[] hdrTag = new byte[bptag]; Array.Copy(header, 0x200, hdrTag, 0, bptag); @@ -153,72 +157,72 @@ namespace DiscImageChef.DiscImages switch(StringHandlers.CToString(imageHeader.DeviceName)) { case PROFILE_NAME: - ImageInfo.MediaType = ImageInfo.Sectors == 0x2600 ? MediaType.AppleProfile : MediaType.GENERIC_HDD; - ImageInfo.Cylinders = 152; - ImageInfo.Heads = 4; - ImageInfo.SectorsPerTrack = 16; + imageInfo.MediaType = imageInfo.Sectors == 0x2600 ? MediaType.AppleProfile : MediaType.GENERIC_HDD; + imageInfo.Cylinders = 152; + imageInfo.Heads = 4; + imageInfo.SectorsPerTrack = 16; break; case PROFILE10_NAME: - ImageInfo.MediaType = ImageInfo.Sectors == 0x4C00 ? MediaType.AppleProfile : MediaType.GENERIC_HDD; - ImageInfo.Cylinders = 304; - ImageInfo.Heads = 4; - ImageInfo.SectorsPerTrack = 16; + imageInfo.MediaType = imageInfo.Sectors == 0x4C00 ? MediaType.AppleProfile : MediaType.GENERIC_HDD; + imageInfo.Cylinders = 304; + imageInfo.Heads = 4; + imageInfo.SectorsPerTrack = 16; break; case WIDGET_NAME: - ImageInfo.MediaType = ImageInfo.Sectors == 0x4C00 ? MediaType.AppleWidget : MediaType.GENERIC_HDD; - ImageInfo.Cylinders = 304; - ImageInfo.Heads = 4; - ImageInfo.SectorsPerTrack = 16; + imageInfo.MediaType = imageInfo.Sectors == 0x4C00 ? MediaType.AppleWidget : MediaType.GENERIC_HDD; + imageInfo.Cylinders = 304; + imageInfo.Heads = 4; + imageInfo.SectorsPerTrack = 16; break; case PRIAM_NAME: - ImageInfo.MediaType = - ImageInfo.Sectors == 0x022C7C ? MediaType.PriamDataTower : MediaType.GENERIC_HDD; + imageInfo.MediaType = + imageInfo.Sectors == 0x022C7C ? MediaType.PriamDataTower : MediaType.GENERIC_HDD; // This values are invented... - ImageInfo.Cylinders = 419; - ImageInfo.Heads = 4; - ImageInfo.SectorsPerTrack = 85; + imageInfo.Cylinders = 419; + imageInfo.Heads = 4; + imageInfo.SectorsPerTrack = 85; break; default: - ImageInfo.MediaType = MediaType.GENERIC_HDD; - ImageInfo.Cylinders = (uint)(ImageInfo.Sectors / 16 / 63); - ImageInfo.Heads = 16; - ImageInfo.SectorsPerTrack = 63; + imageInfo.MediaType = MediaType.GENERIC_HDD; + imageInfo.Cylinders = (uint)(imageInfo.Sectors / 16 / 63); + imageInfo.Heads = 16; + imageInfo.SectorsPerTrack = 63; break; } - ImageInfo.Application = StringHandlers.CToString(hdrTag); + imageInfo.Application = StringHandlers.CToString(hdrTag); - ImageInfo.CreationTime = imageFilter.GetCreationTime(); - ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime(); - ImageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename()); + imageInfo.CreationTime = imageFilter.GetCreationTime(); + imageInfo.LastModificationTime = imageFilter.GetLastWriteTime(); + imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename()); bluImageFilter = imageFilter; - ImageInfo.XmlMediaType = XmlMediaType.BlockMedia; + imageInfo.XmlMediaType = XmlMediaType.BlockMedia; - if(bptag > 0) ImageInfo.ReadableSectorTags.Add(SectorTagType.AppleSectorTag); + if(bptag > 0) imageInfo.ReadableSectorTags.Add(SectorTagType.AppleSectorTag); - DicConsole.VerboseWriteLine("BLU image contains a disk of type {0}", ImageInfo.MediaType); + DicConsole.VerboseWriteLine("BLU image contains a disk of type {0}", imageInfo.MediaType); return true; } - public override byte[] ReadSector(ulong sectorAddress) + public virtual byte[] ReadSector(ulong sectorAddress) { return ReadSectors(sectorAddress, 1); } - public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag) + public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag) { return ReadSectorsTag(sectorAddress, 1, tag); } - public override byte[] ReadSectors(ulong sectorAddress, uint length) + public virtual byte[] ReadSectors(ulong sectorAddress, uint length) { - if(sectorAddress > ImageInfo.Sectors - 1) + if(sectorAddress > imageInfo.Sectors - 1) throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found"); - if(sectorAddress + length > ImageInfo.Sectors) + if(sectorAddress + length > imageInfo.Sectors) throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available"); MemoryStream buffer = new MemoryStream(); @@ -241,17 +245,17 @@ namespace DiscImageChef.DiscImages return buffer.ToArray(); } - public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag) + public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag) { if(tag != SectorTagType.AppleSectorTag) throw new FeatureUnsupportedImageException($"Tag {tag} not supported by image format"); if(bptag == 0) throw new FeatureNotPresentImageException("Disk image does not have tags"); - if(sectorAddress > ImageInfo.Sectors - 1) + if(sectorAddress > imageInfo.Sectors - 1) throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found"); - if(sectorAddress + length > ImageInfo.Sectors) + if(sectorAddress + length > imageInfo.Sectors) throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available"); MemoryStream buffer = new MemoryStream(); @@ -274,17 +278,17 @@ namespace DiscImageChef.DiscImages return buffer.ToArray(); } - public override byte[] ReadSectorLong(ulong sectorAddress) + public virtual byte[] ReadSectorLong(ulong sectorAddress) { return ReadSectorsLong(sectorAddress, 1); } - public override byte[] ReadSectorsLong(ulong sectorAddress, uint length) + public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length) { - if(sectorAddress > ImageInfo.Sectors - 1) + if(sectorAddress > imageInfo.Sectors - 1) throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found"); - if(sectorAddress + length > ImageInfo.Sectors) + if(sectorAddress + length > imageInfo.Sectors) throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available"); byte[] buffer = new byte[length * imageHeader.BytesPerBlock]; @@ -295,47 +299,47 @@ namespace DiscImageChef.DiscImages return buffer; } - public override byte[] ReadDiskTag(MediaTagType tag) + public virtual byte[] ReadDiskTag(MediaTagType tag) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override List GetSessionTracks(Session session) + public virtual List GetSessionTracks(Session session) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override List GetSessionTracks(ushort session) + public virtual List GetSessionTracks(ushort session) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSector(ulong sectorAddress, uint track) + public virtual byte[] ReadSector(ulong sectorAddress, uint track) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag) + public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track) + public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag) + public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorLong(ulong sectorAddress, uint track) + public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } - public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track) + public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track) { throw new FeatureUnsupportedImageException("Feature not supported by image format"); } @@ -349,17 +353,17 @@ namespace DiscImageChef.DiscImages } #region Verification, should add tag checksum checks - public override bool? VerifySector(ulong sectorAddress) + public virtual bool? VerifySector(ulong sectorAddress) { return null; } - public override bool? VerifySector(ulong sectorAddress, uint track) + public virtual bool? VerifySector(ulong sectorAddress, uint track) { return null; } - public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas, + public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas, out List unknownLbas) { failingLbas = new List(); @@ -370,7 +374,7 @@ namespace DiscImageChef.DiscImages return null; } - public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas, + public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas, out List unknownLbas) { failingLbas = new List(); @@ -381,7 +385,7 @@ namespace DiscImageChef.DiscImages return null; } - public override bool? VerifyMediaImage() + public virtual bool? VerifyMediaImage() { return null; } diff --git a/DiscImageChef.DiscImages/BlindWrite4.cs b/DiscImageChef.DiscImages/BlindWrite4.cs index 2e32a44a..6e4e2953 100644 --- a/DiscImageChef.DiscImages/BlindWrite4.cs +++ b/DiscImageChef.DiscImages/BlindWrite4.cs @@ -44,7 +44,7 @@ using DiscImageChef.Filters; namespace DiscImageChef.DiscImages { - public class BlindWrite4 : ImagePlugin + public class BlindWrite4 : IMediaImage { /// "BLINDWRITE TOC FILE" readonly byte[] bw4Signature = @@ -53,9 +53,10 @@ namespace DiscImageChef.DiscImages 0x45 }; List bwTracks; - Filter dataFilter, subFilter; + IFilter dataFilter, subFilter; Bw4Header header; + ImageInfo imageInfo; Stream imageStream; Dictionary offsetmap; List partitions; @@ -65,9 +66,7 @@ namespace DiscImageChef.DiscImages public BlindWrite4() { - Name = "BlindWrite 4"; - PluginUuid = new Guid("664568B2-15D4-4E64-8A7A-20BDA8B8386F"); - ImageInfo = new ImageInfo + imageInfo = new ImageInfo { ReadableSectorTags = new List(), ReadableMediaTags = new List(), @@ -89,15 +88,20 @@ namespace DiscImageChef.DiscImages }; } - public override string ImageFormat => "BlindWrite 4 TOC file"; + public virtual ImageInfo Info => imageInfo; - public override List Partitions => partitions; + public virtual string Name => "BlindWrite 4"; + public virtual Guid Id => new Guid("664568B2-15D4-4E64-8A7A-20BDA8B8386F"); - public override List Tracks => tracks; + public virtual string ImageFormat => "BlindWrite 4 TOC file"; - public override List Sessions => sessions; + public virtual List Partitions => partitions; - public override bool IdentifyImage(Filter imageFilter) + public virtual List Tracks => tracks; + + public virtual List Sessions => sessions; + + public virtual bool IdentifyImage(IFilter imageFilter) { Stream stream = imageFilter.GetDataForkStream(); stream.Seek(0, SeekOrigin.Begin); @@ -109,7 +113,7 @@ namespace DiscImageChef.DiscImages return bw4Signature.SequenceEqual(signature); } - public override bool OpenImage(Filter imageFilter) + public virtual bool OpenImage(IFilter imageFilter) { Stream stream = imageFilter.GetDataForkStream(); stream.Seek(0, SeekOrigin.Begin); @@ -580,8 +584,8 @@ namespace DiscImageChef.DiscImages if(subFilter != null && bwTrack.subchannel > 0) { track.TrackSubchannelType = TrackSubchannelType.Packed; - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubchannel)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubchannel); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubchannel)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubchannel); } else track.TrackSubchannelType = TrackSubchannelType.None; @@ -589,41 +593,41 @@ namespace DiscImageChef.DiscImages { case Bw4TrackType.Audio: track.TrackType = TrackType.Audio; - ImageInfo.SectorSize = 2352; + imageInfo.SectorSize = 2352; track.TrackBytesPerSector = 2352; break; case Bw4TrackType.Mode1: track.TrackType = TrackType.CdMode1; - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEcc)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccP)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccQ)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc); - if(ImageInfo.SectorSize < 2048) ImageInfo.SectorSize = 2048; + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEcc)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccP)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccQ)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc); + if(imageInfo.SectorSize < 2048) imageInfo.SectorSize = 2048; track.TrackBytesPerSector = 2048; break; case Bw4TrackType.Mode2: track.TrackType = TrackType.CdMode2Formless; - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); - if(ImageInfo.SectorSize < 2336) ImageInfo.SectorSize = 2336; + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); + if(imageInfo.SectorSize < 2336) imageInfo.SectorSize = 2336; track.TrackBytesPerSector = 2336; break; default: track.TrackType = TrackType.Data; track.TrackRawBytesPerSector = 2048; - ImageInfo.SectorSize = 2048; + imageInfo.SectorSize = 2048; track.TrackBytesPerSector = 2048; break; } @@ -652,17 +656,17 @@ namespace DiscImageChef.DiscImages if(!trackFlags.ContainsKey(track.TrackSequence)) trackFlags.Add(track.TrackSequence, (byte)(bwTrack.adrCtl & 0x0F)); - ImageInfo.Sectors += (ulong)(bwTrack.lastSector - bwTrack.startSector + 1); + imageInfo.Sectors += (ulong)(bwTrack.lastSector - bwTrack.startSector + 1); } else { - ImageInfo.MediaBarcode = bwTrack.isrcUpc; - ImageInfo.MediaSerialNumber = bwTrack.discId; - ImageInfo.MediaTitle = bwTrack.title; + imageInfo.MediaBarcode = bwTrack.isrcUpc; + imageInfo.MediaSerialNumber = bwTrack.discId; + imageInfo.MediaTitle = bwTrack.title; if(!string.IsNullOrEmpty(bwTrack.isrcUpc) && - !ImageInfo.ReadableMediaTags.Contains(MediaTagType.CD_MCN)) - ImageInfo.ReadableMediaTags.Add(MediaTagType.CD_MCN); + !imageInfo.ReadableMediaTags.Contains(MediaTagType.CD_MCN)) + imageInfo.ReadableMediaTags.Add(MediaTagType.CD_MCN); } sessions = new List(); @@ -686,16 +690,16 @@ namespace DiscImageChef.DiscImages sessions.Add(session); } - ImageInfo.MediaType = MediaType.CD; + imageInfo.MediaType = MediaType.CD; - ImageInfo.Application = "BlindWrite"; - ImageInfo.ApplicationVersion = "4"; - ImageInfo.Version = "4"; + imageInfo.Application = "BlindWrite"; + imageInfo.ApplicationVersion = "4"; + imageInfo.Version = "4"; - ImageInfo.ImageSize = (ulong)dataFilter.GetDataForkLength(); - ImageInfo.CreationTime = dataFilter.GetCreationTime(); - ImageInfo.LastModificationTime = dataFilter.GetLastWriteTime(); - ImageInfo.XmlMediaType = XmlMediaType.OpticalDisc; + imageInfo.ImageSize = (ulong)dataFilter.GetDataForkLength(); + imageInfo.CreationTime = dataFilter.GetCreationTime(); + imageInfo.LastModificationTime = dataFilter.GetLastWriteTime(); + imageInfo.XmlMediaType = XmlMediaType.OpticalDisc; bool data = false; bool mode2 = false; @@ -725,28 +729,28 @@ namespace DiscImageChef.DiscImages } } - if(!data && !firstdata) ImageInfo.MediaType = MediaType.CDDA; - else if(firstaudio && data && sessions.Count > 1 && mode2) ImageInfo.MediaType = MediaType.CDPLUS; - else if(firstdata && audio || mode2) ImageInfo.MediaType = MediaType.CDROMXA; - else if(!audio) ImageInfo.MediaType = MediaType.CDROM; - else ImageInfo.MediaType = MediaType.CD; + if(!data && !firstdata) imageInfo.MediaType = MediaType.CDDA; + else if(firstaudio && data && sessions.Count > 1 && mode2) imageInfo.MediaType = MediaType.CDPLUS; + else if(firstdata && audio || mode2) imageInfo.MediaType = MediaType.CDROMXA; + else if(!audio) imageInfo.MediaType = MediaType.CDROM; + else imageInfo.MediaType = MediaType.CD; - ImageInfo.Comments = header.Comments; + imageInfo.Comments = header.Comments; - DicConsole.VerboseWriteLine("BlindWrite image describes a disc of type {0}", ImageInfo.MediaType); - if(!string.IsNullOrEmpty(ImageInfo.Comments)) - DicConsole.VerboseWriteLine("BlindrWrite comments: {0}", ImageInfo.Comments); + DicConsole.VerboseWriteLine("BlindWrite image describes a disc of type {0}", imageInfo.MediaType); + if(!string.IsNullOrEmpty(imageInfo.Comments)) + DicConsole.VerboseWriteLine("BlindrWrite comments: {0}", imageInfo.Comments); return true; } - public override byte[] ReadDiskTag(MediaTagType tag) + public virtual byte[] ReadDiskTag(MediaTagType tag) { switch(tag) { case MediaTagType.CD_MCN: { - if(ImageInfo.MediaSerialNumber != null) return Encoding.ASCII.GetBytes(ImageInfo.MediaSerialNumber); + if(imageInfo.MediaSerialNumber != null) return Encoding.ASCII.GetBytes(imageInfo.MediaSerialNumber); throw new FeatureNotPresentImageException("Image does not contain MCN information."); } @@ -755,27 +759,27 @@ namespace DiscImageChef.DiscImages } } - public override byte[] ReadSector(ulong sectorAddress) + public virtual byte[] ReadSector(ulong sectorAddress) { return ReadSectors(sectorAddress, 1); } - public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag) + public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag) { return ReadSectorsTag(sectorAddress, 1, tag); } - public override byte[] ReadSector(ulong sectorAddress, uint track) + public virtual byte[] ReadSector(ulong sectorAddress, uint track) { return ReadSectors(sectorAddress, 1, track); } - public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag) + public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag) { return ReadSectorsTag(sectorAddress, 1, track, tag); } - public override byte[] ReadSectors(ulong sectorAddress, uint length) + public virtual byte[] ReadSectors(ulong sectorAddress, uint length) { foreach(KeyValuePair kvp in from kvp in offsetmap where sectorAddress >= kvp.Value @@ -789,7 +793,7 @@ namespace DiscImageChef.DiscImages throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found"); } - public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag) + public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag) { foreach(KeyValuePair kvp in from kvp in offsetmap where sectorAddress >= kvp.Value @@ -803,7 +807,7 @@ namespace DiscImageChef.DiscImages throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found"); } - public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track) + public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track) { Track dicTrack = new Track {TrackSequence = 0}; @@ -877,7 +881,7 @@ namespace DiscImageChef.DiscImages return buffer; } - public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag) + public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag) { Track dicTrack = new Track {TrackSequence = 0}; @@ -1036,17 +1040,17 @@ namespace DiscImageChef.DiscImages return buffer; } - public override byte[] ReadSectorLong(ulong sectorAddress) + public virtual byte[] ReadSectorLong(ulong sectorAddress) { return ReadSectorsLong(sectorAddress, 1); } - public override byte[] ReadSectorLong(ulong sectorAddress, uint track) + public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track) { return ReadSectorsLong(sectorAddress, 1, track); } - public override byte[] ReadSectorsLong(ulong sectorAddress, uint length) + public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length) { foreach(KeyValuePair kvp in from kvp in offsetmap where sectorAddress >= kvp.Value @@ -1060,7 +1064,7 @@ namespace DiscImageChef.DiscImages throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found"); } - public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track) + public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track) { Track dicTrack = new Track {TrackSequence = 0}; @@ -1106,31 +1110,31 @@ namespace DiscImageChef.DiscImages return buffer; } - public override List GetSessionTracks(Session session) + public virtual List GetSessionTracks(Session session) { if(sessions.Contains(session)) return GetSessionTracks(session.SessionSequence); throw new ImageNotSupportedException("Session does not exist in disc image"); } - public override List GetSessionTracks(ushort session) + public virtual List GetSessionTracks(ushort session) { return tracks.Where(track => track.TrackSession == session).ToList(); } - public override bool? VerifySector(ulong sectorAddress) + public virtual bool? VerifySector(ulong sectorAddress) { byte[] buffer = ReadSectorLong(sectorAddress); return CdChecksums.CheckCdSector(buffer); } - public override bool? VerifySector(ulong sectorAddress, uint track) + public virtual bool? VerifySector(ulong sectorAddress, uint track) { byte[] buffer = ReadSectorLong(sectorAddress, track); return CdChecksums.CheckCdSector(buffer); } - public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas, + public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas, out List unknownLbas) { byte[] buffer = ReadSectorsLong(sectorAddress, length); @@ -1160,7 +1164,7 @@ namespace DiscImageChef.DiscImages return failingLbas.Count <= 0; } - public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas, + public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas, out List unknownLbas) { byte[] buffer = ReadSectorsLong(sectorAddress, length, track); @@ -1190,7 +1194,7 @@ namespace DiscImageChef.DiscImages return failingLbas.Count <= 0; } - public override bool? VerifyMediaImage() + public virtual bool? VerifyMediaImage() { return null; } @@ -1220,8 +1224,8 @@ namespace DiscImageChef.DiscImages public string VolumeIdentifier; public string SystemIdentifier; public string Comments; - public Filter DataFilter; - public Filter SubchannelFilter; + public IFilter DataFilter; + public IFilter SubchannelFilter; public string DataFile; public string SubchannelFile; #pragma warning restore 649 diff --git a/DiscImageChef.DiscImages/BlindWrite5.cs b/DiscImageChef.DiscImages/BlindWrite5.cs index d9a50564..2f467090 100644 --- a/DiscImageChef.DiscImages/BlindWrite5.cs +++ b/DiscImageChef.DiscImages/BlindWrite5.cs @@ -49,7 +49,7 @@ using DMI = DiscImageChef.Decoders.Xbox.DMI; namespace DiscImageChef.DiscImages { - public class BlindWrite5 : ImagePlugin + public class BlindWrite5 : IMediaImage { /// "BWT5 STREAM FOOT" readonly byte[] bw5Footer = @@ -70,6 +70,7 @@ namespace DiscImageChef.DiscImages byte[] fullToc; Bw5Header header; + ImageInfo imageInfo; Stream imageStream; byte[] mode2A; Dictionary offsetmap; @@ -83,9 +84,7 @@ namespace DiscImageChef.DiscImages public BlindWrite5() { - Name = "BlindWrite 5"; - PluginUuid = new Guid("9CB7A381-0509-4F9F-B801-3F65434BC3EE"); - ImageInfo = new ImageInfo + imageInfo = new ImageInfo { ReadableSectorTags = new List(), ReadableMediaTags = new List(), @@ -107,15 +106,20 @@ namespace DiscImageChef.DiscImages }; } - public override string ImageFormat => "BlindWrite 5 TOC file"; + public virtual ImageInfo Info => imageInfo; - public override List Partitions => partitions; + public virtual string Name => "BlindWrite 5"; + public virtual Guid Id => new Guid("9CB7A381-0509-4F9F-B801-3F65434BC3EE"); - public override List Tracks => tracks; + public virtual string ImageFormat => "BlindWrite 5 TOC file"; - public override List Sessions => sessions; + public virtual List Partitions => partitions; - public override bool IdentifyImage(Filter imageFilter) + public virtual List Tracks => tracks; + + public virtual List Sessions => sessions; + + public virtual bool IdentifyImage(IFilter imageFilter) { Stream stream = imageFilter.GetDataForkStream(); stream.Seek(0, SeekOrigin.Begin); @@ -131,7 +135,7 @@ namespace DiscImageChef.DiscImages return bw5Signature.SequenceEqual(signature) && bw5Footer.SequenceEqual(footer); } - public override bool OpenImage(Filter imageFilter) + public virtual bool OpenImage(IFilter imageFilter) { Stream stream = imageFilter.GetDataForkStream(); stream.Seek(0, SeekOrigin.Begin); @@ -652,7 +656,7 @@ namespace DiscImageChef.DiscImages byte firstSession = byte.MaxValue; byte lastSession = 0; trackFlags = new Dictionary(); - ImageInfo.Sectors = 0; + imageInfo.Sectors = 0; DicConsole.DebugWriteLine("BlindWrite5 plugin", "Building maps"); foreach(Bw5SessionDescriptor ses in bwSessions) @@ -697,54 +701,54 @@ namespace DiscImageChef.DiscImages case Bw5TrackType.Audio: track.TrackBytesPerSector = 2352; track.TrackRawBytesPerSector = 2352; - if(ImageInfo.SectorSize < 2352) ImageInfo.SectorSize = 2352; + if(imageInfo.SectorSize < 2352) imageInfo.SectorSize = 2352; break; case Bw5TrackType.Mode1: case Bw5TrackType.Mode2F1: - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEcc)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccP)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccQ)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEcc)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccP)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccQ)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc); track.TrackBytesPerSector = 2048; track.TrackRawBytesPerSector = 2352; - if(ImageInfo.SectorSize < 2048) ImageInfo.SectorSize = 2048; + if(imageInfo.SectorSize < 2048) imageInfo.SectorSize = 2048; break; case Bw5TrackType.Mode2: - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); track.TrackBytesPerSector = 2336; track.TrackRawBytesPerSector = 2352; - if(ImageInfo.SectorSize < 2336) ImageInfo.SectorSize = 2336; + if(imageInfo.SectorSize < 2336) imageInfo.SectorSize = 2336; break; case Bw5TrackType.Mode2F2: - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc); track.TrackBytesPerSector = 2336; track.TrackRawBytesPerSector = 2352; - if(ImageInfo.SectorSize < 2324) ImageInfo.SectorSize = 2324; + if(imageInfo.SectorSize < 2324) imageInfo.SectorSize = 2324; break; case Bw5TrackType.Dvd: track.TrackBytesPerSector = 2048; track.TrackRawBytesPerSector = 2048; - if(ImageInfo.SectorSize < 2048) ImageInfo.SectorSize = 2048; + if(imageInfo.SectorSize < 2048) imageInfo.SectorSize = 2048; isDvd = true; break; } @@ -771,8 +775,8 @@ namespace DiscImageChef.DiscImages track.TrackSubchannelOffset = track.TrackFileOffset; if(chars.Subchannel == TrackSubchannelType.PackedInterleaved) - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubchannel)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubchannel); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubchannel)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubchannel); } break; @@ -797,7 +801,7 @@ namespace DiscImageChef.DiscImages tracks.Add(track); partitions.Add(partition); offsetmap.Add(track.TrackSequence, track.TrackStartSector); - ImageInfo.Sectors += partition.Length; + imageInfo.Sectors += partition.Length; } } @@ -847,10 +851,10 @@ namespace DiscImageChef.DiscImages } else DicConsole.DebugWriteLine("BlindWrite5 plugin", "TOC correctly rebuilt"); - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackFlags); + imageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackFlags); } - ImageInfo.MediaType = BlindWriteProfileToMediaType(header.profile); + imageInfo.MediaType = BlindWriteProfileToMediaType(header.profile); if(dmi != null && pfi != null) { @@ -863,54 +867,54 @@ namespace DiscImageChef.DiscImages switch(pfi0.Value.DiskCategory) { case DiskCategory.DVDPR: - ImageInfo.MediaType = MediaType.DVDPR; + imageInfo.MediaType = MediaType.DVDPR; break; case DiskCategory.DVDPRDL: - ImageInfo.MediaType = MediaType.DVDPRDL; + imageInfo.MediaType = MediaType.DVDPRDL; break; case DiskCategory.DVDPRW: - ImageInfo.MediaType = MediaType.DVDPRW; + imageInfo.MediaType = MediaType.DVDPRW; break; case DiskCategory.DVDPRWDL: - ImageInfo.MediaType = MediaType.DVDPRWDL; + imageInfo.MediaType = MediaType.DVDPRWDL; break; case DiskCategory.DVDR: - ImageInfo.MediaType = pfi0.Value.PartVersion == 6 ? MediaType.DVDRDL : MediaType.DVDR; + imageInfo.MediaType = pfi0.Value.PartVersion == 6 ? MediaType.DVDRDL : MediaType.DVDR; break; case DiskCategory.DVDRAM: - ImageInfo.MediaType = MediaType.DVDRAM; + imageInfo.MediaType = MediaType.DVDRAM; break; default: - ImageInfo.MediaType = MediaType.DVDROM; + imageInfo.MediaType = MediaType.DVDROM; break; case DiskCategory.DVDRW: - ImageInfo.MediaType = pfi0.Value.PartVersion == 3 ? MediaType.DVDRWDL : MediaType.DVDRW; + imageInfo.MediaType = pfi0.Value.PartVersion == 3 ? MediaType.DVDRWDL : MediaType.DVDRW; break; case DiskCategory.HDDVDR: - ImageInfo.MediaType = MediaType.HDDVDR; + imageInfo.MediaType = MediaType.HDDVDR; break; case DiskCategory.HDDVDRAM: - ImageInfo.MediaType = MediaType.HDDVDRAM; + imageInfo.MediaType = MediaType.HDDVDRAM; break; case DiskCategory.HDDVDROM: - ImageInfo.MediaType = MediaType.HDDVDROM; + imageInfo.MediaType = MediaType.HDDVDROM; break; case DiskCategory.HDDVDRW: - ImageInfo.MediaType = MediaType.HDDVDRW; + imageInfo.MediaType = MediaType.HDDVDRW; break; case DiskCategory.Nintendo: - ImageInfo.MediaType = pfi0.Value.DiscSize == DVDSize.Eighty ? MediaType.GOD : MediaType.WOD; + imageInfo.MediaType = pfi0.Value.DiscSize == DVDSize.Eighty ? MediaType.GOD : MediaType.WOD; break; case DiskCategory.UMD: - ImageInfo.MediaType = MediaType.UMD; + imageInfo.MediaType = MediaType.UMD; break; } - if(DMI.IsXbox(dmi)) ImageInfo.MediaType = MediaType.XGD; - else if(DMI.IsXbox360(dmi)) ImageInfo.MediaType = MediaType.XGD2; + if(DMI.IsXbox(dmi)) imageInfo.MediaType = MediaType.XGD; + else if(DMI.IsXbox360(dmi)) imageInfo.MediaType = MediaType.XGD2; } } - else if(ImageInfo.MediaType == MediaType.CD || ImageInfo.MediaType == MediaType.CDROM) + else if(imageInfo.MediaType == MediaType.CD || imageInfo.MediaType == MediaType.CDROM) { bool data = false; bool mode2 = false; @@ -942,27 +946,27 @@ namespace DiscImageChef.DiscImages } } - if(!data && !firstdata) ImageInfo.MediaType = MediaType.CDDA; - else if(firstaudio && data && sessions.Count > 1 && mode2) ImageInfo.MediaType = MediaType.CDPLUS; - else if(firstdata && audio || mode2) ImageInfo.MediaType = MediaType.CDROMXA; - else if(!audio) ImageInfo.MediaType = MediaType.CDROM; - else ImageInfo.MediaType = MediaType.CD; + if(!data && !firstdata) imageInfo.MediaType = MediaType.CDDA; + else if(firstaudio && data && sessions.Count > 1 && mode2) imageInfo.MediaType = MediaType.CDPLUS; + else if(firstdata && audio || mode2) imageInfo.MediaType = MediaType.CDROMXA; + else if(!audio) imageInfo.MediaType = MediaType.CDROM; + else imageInfo.MediaType = MediaType.CD; } - ImageInfo.DriveManufacturer = StringHandlers.CToString(header.manufacturer); - ImageInfo.DriveModel = StringHandlers.CToString(header.product); - ImageInfo.DriveFirmwareRevision = StringHandlers.CToString(header.revision); - ImageInfo.Application = "BlindWrite"; + imageInfo.DriveManufacturer = StringHandlers.CToString(header.manufacturer); + imageInfo.DriveModel = StringHandlers.CToString(header.product); + imageInfo.DriveFirmwareRevision = StringHandlers.CToString(header.revision); + imageInfo.Application = "BlindWrite"; if(string.Compare(Path.GetExtension(imageFilter.GetFilename()), "B5T", - StringComparison.OrdinalIgnoreCase) == 0) ImageInfo.ApplicationVersion = "5"; + StringComparison.OrdinalIgnoreCase) == 0) imageInfo.ApplicationVersion = "5"; else if(string.Compare(Path.GetExtension(imageFilter.GetFilename()), "B6T", - StringComparison.OrdinalIgnoreCase) == 0) ImageInfo.ApplicationVersion = "6"; - ImageInfo.Version = "5"; + StringComparison.OrdinalIgnoreCase) == 0) imageInfo.ApplicationVersion = "6"; + imageInfo.Version = "5"; - ImageInfo.ImageSize = (ulong)imageFilter.GetDataForkLength(); - ImageInfo.CreationTime = imageFilter.GetCreationTime(); - ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime(); - ImageInfo.XmlMediaType = XmlMediaType.OpticalDisc; + imageInfo.ImageSize = (ulong)imageFilter.GetDataForkLength(); + imageInfo.CreationTime = imageFilter.GetCreationTime(); + imageInfo.LastModificationTime = imageFilter.GetLastWriteTime(); + imageInfo.XmlMediaType = XmlMediaType.OpticalDisc; if(pma != null) { @@ -971,67 +975,67 @@ namespace DiscImageChef.DiscImages foreach(uint id in from descriptor in pma0.PMADescriptors where descriptor.ADR == 2 select (uint)((descriptor.Min << 16) + (descriptor.Sec << 8) + descriptor.Frame)) - ImageInfo.MediaSerialNumber = $"{id & 0x00FFFFFF:X6}"; + imageInfo.MediaSerialNumber = $"{id & 0x00FFFFFF:X6}"; } if(atip != null) { ATIP.CDATIP atip0 = ATIP.Decode(atip).Value; - ImageInfo.MediaType = atip0.DiscType ? MediaType.CDRW : MediaType.CDR; + imageInfo.MediaType = atip0.DiscType ? MediaType.CDRW : MediaType.CDR; if(atip0.LeadInStartMin == 97) { int type = atip0.LeadInStartFrame % 10; int frm = atip0.LeadInStartFrame - type; - ImageInfo.MediaManufacturer = ATIP.ManufacturerFromATIP(atip0.LeadInStartSec, frm); + imageInfo.MediaManufacturer = ATIP.ManufacturerFromATIP(atip0.LeadInStartSec, frm); } } bool isBd = false; - if(ImageInfo.MediaType == MediaType.BDR || ImageInfo.MediaType == MediaType.BDRE || - ImageInfo.MediaType == MediaType.BDROM) + if(imageInfo.MediaType == MediaType.BDR || imageInfo.MediaType == MediaType.BDRE || + imageInfo.MediaType == MediaType.BDROM) { isDvd = false; isBd = true; } - if(isBd && ImageInfo.Sectors > 24438784) - switch(ImageInfo.MediaType) + if(isBd && imageInfo.Sectors > 24438784) + switch(imageInfo.MediaType) { case MediaType.BDR: - ImageInfo.MediaType = MediaType.BDRXL; + imageInfo.MediaType = MediaType.BDRXL; break; case MediaType.BDRE: - ImageInfo.MediaType = MediaType.BDREXL; + imageInfo.MediaType = MediaType.BDREXL; break; } - DicConsole.DebugWriteLine("BlindWrite5 plugin", "ImageInfo.mediaType = {0}", ImageInfo.MediaType); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "ImageInfo.mediaType = {0}", imageInfo.MediaType); - if(mode2A != null) ImageInfo.ReadableMediaTags.Add(MediaTagType.SCSI_MODEPAGE_2A); - if(pma != null) ImageInfo.ReadableMediaTags.Add(MediaTagType.CD_PMA); - if(atip != null) ImageInfo.ReadableMediaTags.Add(MediaTagType.CD_ATIP); - if(cdtext != null) ImageInfo.ReadableMediaTags.Add(MediaTagType.CD_TEXT); + if(mode2A != null) imageInfo.ReadableMediaTags.Add(MediaTagType.SCSI_MODEPAGE_2A); + if(pma != null) imageInfo.ReadableMediaTags.Add(MediaTagType.CD_PMA); + if(atip != null) imageInfo.ReadableMediaTags.Add(MediaTagType.CD_ATIP); + if(cdtext != null) imageInfo.ReadableMediaTags.Add(MediaTagType.CD_TEXT); if(bca != null) - if(isDvd) ImageInfo.ReadableMediaTags.Add(MediaTagType.DVD_BCA); - else if(isBd) ImageInfo.ReadableMediaTags.Add(MediaTagType.BD_BCA); - if(dmi != null) ImageInfo.ReadableMediaTags.Add(MediaTagType.DVD_DMI); - if(pfi != null) ImageInfo.ReadableMediaTags.Add(MediaTagType.DVD_PFI); - if(fullToc != null) ImageInfo.ReadableMediaTags.Add(MediaTagType.CD_FullTOC); + if(isDvd) imageInfo.ReadableMediaTags.Add(MediaTagType.DVD_BCA); + else if(isBd) imageInfo.ReadableMediaTags.Add(MediaTagType.BD_BCA); + if(dmi != null) imageInfo.ReadableMediaTags.Add(MediaTagType.DVD_DMI); + if(pfi != null) imageInfo.ReadableMediaTags.Add(MediaTagType.DVD_PFI); + if(fullToc != null) imageInfo.ReadableMediaTags.Add(MediaTagType.CD_FullTOC); - if(ImageInfo.MediaType == MediaType.XGD2) - if(ImageInfo.Sectors == 25063 || // Locked (or non compatible drive) - ImageInfo.Sectors == 4229664 || // Xtreme unlock - ImageInfo.Sectors == 4246304) // Wxripper unlock - ImageInfo.MediaType = MediaType.XGD3; + if(imageInfo.MediaType == MediaType.XGD2) + if(imageInfo.Sectors == 25063 || // Locked (or non compatible drive) + imageInfo.Sectors == 4229664 || // Xtreme unlock + imageInfo.Sectors == 4246304) // Wxripper unlock + imageInfo.MediaType = MediaType.XGD3; - DicConsole.VerboseWriteLine("BlindWrite image describes a disc of type {0}", ImageInfo.MediaType); + DicConsole.VerboseWriteLine("BlindWrite image describes a disc of type {0}", imageInfo.MediaType); return true; } - public override byte[] ReadDiskTag(MediaTagType tag) + public virtual byte[] ReadDiskTag(MediaTagType tag) { switch(tag) { @@ -1089,27 +1093,27 @@ namespace DiscImageChef.DiscImages } } - public override byte[] ReadSector(ulong sectorAddress) + public virtual byte[] ReadSector(ulong sectorAddress) { return ReadSectors(sectorAddress, 1); } - public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag) + public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag) { return ReadSectorsTag(sectorAddress, 1, tag); } - public override byte[] ReadSector(ulong sectorAddress, uint track) + public virtual byte[] ReadSector(ulong sectorAddress, uint track) { return ReadSectors(sectorAddress, 1, track); } - public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag) + public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag) { return ReadSectorsTag(sectorAddress, 1, track, tag); } - public override byte[] ReadSectors(ulong sectorAddress, uint length) + public virtual byte[] ReadSectors(ulong sectorAddress, uint length) { foreach(KeyValuePair kvp in from kvp in offsetmap where sectorAddress >= kvp.Value @@ -1123,7 +1127,7 @@ namespace DiscImageChef.DiscImages throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found"); } - public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag) + public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag) { foreach(KeyValuePair kvp in from kvp in offsetmap where sectorAddress >= kvp.Value @@ -1137,7 +1141,7 @@ namespace DiscImageChef.DiscImages throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found"); } - public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track) + public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track) { // TODO: Cross data files Track dicTrack = new Track(); @@ -1256,7 +1260,7 @@ namespace DiscImageChef.DiscImages return buffer; } - public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag) + public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag) { // TODO: Cross data files Track dicTrack = new Track(); @@ -1540,17 +1544,17 @@ namespace DiscImageChef.DiscImages return buffer; } - public override byte[] ReadSectorLong(ulong sectorAddress) + public virtual byte[] ReadSectorLong(ulong sectorAddress) { return ReadSectorsLong(sectorAddress, 1); } - public override byte[] ReadSectorLong(ulong sectorAddress, uint track) + public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track) { return ReadSectorsLong(sectorAddress, 1, track); } - public override byte[] ReadSectorsLong(ulong sectorAddress, uint length) + public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length) { foreach(KeyValuePair kvp in from kvp in offsetmap where sectorAddress >= kvp.Value @@ -1564,7 +1568,7 @@ namespace DiscImageChef.DiscImages throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found"); } - public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track) + public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track) { // TODO: Cross data files Track dicTrack = new Track(); @@ -1658,31 +1662,31 @@ namespace DiscImageChef.DiscImages return buffer; } - public override List GetSessionTracks(Session session) + public virtual List GetSessionTracks(Session session) { if(sessions.Contains(session)) return GetSessionTracks(session.SessionSequence); throw new ImageNotSupportedException("Session does not exist in disc image"); } - public override List GetSessionTracks(ushort session) + public virtual List GetSessionTracks(ushort session) { return tracks.Where(dicTrack => dicTrack.TrackSession == session).ToList(); } - public override bool? VerifySector(ulong sectorAddress) + public virtual bool? VerifySector(ulong sectorAddress) { byte[] buffer = ReadSectorLong(sectorAddress); return CdChecksums.CheckCdSector(buffer); } - public override bool? VerifySector(ulong sectorAddress, uint track) + public virtual bool? VerifySector(ulong sectorAddress, uint track) { byte[] buffer = ReadSectorLong(sectorAddress, track); return CdChecksums.CheckCdSector(buffer); } - public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas, + public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas, out List unknownLbas) { byte[] buffer = ReadSectorsLong(sectorAddress, length); @@ -1712,7 +1716,7 @@ namespace DiscImageChef.DiscImages return failingLbas.Count <= 0; } - public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas, + public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas, out List unknownLbas) { byte[] buffer = ReadSectorsLong(sectorAddress, length, track); @@ -1742,7 +1746,7 @@ namespace DiscImageChef.DiscImages return failingLbas.Count <= 0; } - public override bool? VerifyMediaImage() + public virtual bool? VerifyMediaImage() { return null; } @@ -1915,7 +1919,7 @@ namespace DiscImageChef.DiscImages struct DataFileCharacteristics { - public Filter FileFilter; + public IFilter FileFilter; public string FilePath; public TrackSubchannelType Subchannel; public long SectorSize; diff --git a/DiscImageChef.DiscImages/CDRDAO.cs b/DiscImageChef.DiscImages/CDRDAO.cs index eae35622..e9244f5a 100644 --- a/DiscImageChef.DiscImages/CDRDAO.cs +++ b/DiscImageChef.DiscImages/CDRDAO.cs @@ -46,7 +46,7 @@ namespace DiscImageChef.DiscImages { // TODO: Doesn't support compositing from several files // TODO: Doesn't support silences that are not in files - public class Cdrdao : ImagePlugin + public class Cdrdao : IMediaImage { /// Audio track, 2352 bytes/sector const string CDRDAO_TRACK_TYPE_AUDIO = "AUDIO"; @@ -103,8 +103,9 @@ namespace DiscImageChef.DiscImages const string REGEX_LANGUAGE_MAP = @"^\s*LANGUAGE_MAP\s*\{"; const string REGEX_LANGUAGE_MAPPING = @"^\s*(?\d+)\s?\:\s?(?\d+|\w+)"; - Filter cdrdaoFilter; + IFilter cdrdaoFilter; CdrdaoDisc discimage; + ImageInfo imageInfo; Stream imageStream; /// Dictionary, index is track #, value is TrackFile Dictionary offsetmap; @@ -113,9 +114,7 @@ namespace DiscImageChef.DiscImages public Cdrdao() { - Name = "CDRDAO tocfile"; - PluginUuid = new Guid("04D7BA12-1BE8-44D4-97A4-1B48A505463E"); - ImageInfo = new ImageInfo + imageInfo = new ImageInfo { ReadableSectorTags = new List(), ReadableMediaTags = new List(), @@ -137,11 +136,16 @@ namespace DiscImageChef.DiscImages }; } - public override string ImageFormat => "CDRDAO tocfile"; + public virtual ImageInfo Info => imageInfo; - public override List Partitions => partitions; + public virtual string Name => "CDRDAO tocfile"; + public virtual Guid Id => new Guid("04D7BA12-1BE8-44D4-97A4-1B48A505463E"); - public override List Tracks + public virtual string ImageFormat => "CDRDAO tocfile"; + + public virtual List Partitions => partitions; + + public virtual List Tracks { get { @@ -187,9 +191,9 @@ namespace DiscImageChef.DiscImages } } - public override List Sessions => throw new NotImplementedException(); + public virtual List Sessions => throw new NotImplementedException(); - public override bool IdentifyImage(Filter imageFilter) + public virtual bool IdentifyImage(IFilter imageFilter) { try { @@ -244,7 +248,7 @@ namespace DiscImageChef.DiscImages } } - public override bool OpenImage(Filter imageFilter) + public virtual bool OpenImage(IFilter imageFilter) { if(imageFilter == null) return false; @@ -830,93 +834,93 @@ namespace DiscImageChef.DiscImages foreach(CdrdaoTrack track in discimage.Tracks) { - ImageInfo.ImageSize += track.Bps * track.Sectors; - ImageInfo.Sectors += track.Sectors; + imageInfo.ImageSize += track.Bps * track.Sectors; + imageInfo.Sectors += track.Sectors; } if(discimage.Disktype == MediaType.CDG || discimage.Disktype == MediaType.CDEG || discimage.Disktype == MediaType.CDMIDI) - ImageInfo.SectorSize = 2448; // CD+G subchannels ARE user data, as CD+G are useless without them + imageInfo.SectorSize = 2448; // CD+G subchannels ARE user data, as CD+G are useless without them else if(discimage.Disktype != MediaType.CDROMXA && discimage.Disktype != MediaType.CDDA && discimage.Disktype != MediaType.CDI && - discimage.Disktype != MediaType.CDPLUS) ImageInfo.SectorSize = 2048; // Only data tracks - else ImageInfo.SectorSize = 2352; // All others + discimage.Disktype != MediaType.CDPLUS) imageInfo.SectorSize = 2048; // Only data tracks + else imageInfo.SectorSize = 2352; // All others - if(discimage.Mcn != null) ImageInfo.ReadableMediaTags.Add(MediaTagType.CD_MCN); + if(discimage.Mcn != null) imageInfo.ReadableMediaTags.Add(MediaTagType.CD_MCN); - ImageInfo.Application = "CDRDAO"; + imageInfo.Application = "CDRDAO"; - ImageInfo.CreationTime = imageFilter.GetCreationTime(); - ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime(); + imageInfo.CreationTime = imageFilter.GetCreationTime(); + imageInfo.LastModificationTime = imageFilter.GetLastWriteTime(); - ImageInfo.Comments = discimage.Comment; - ImageInfo.MediaSerialNumber = discimage.Mcn; - ImageInfo.MediaBarcode = discimage.Barcode; - ImageInfo.MediaType = discimage.Disktype; + imageInfo.Comments = discimage.Comment; + imageInfo.MediaSerialNumber = discimage.Mcn; + imageInfo.MediaBarcode = discimage.Barcode; + imageInfo.MediaType = discimage.Disktype; - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackFlags); + imageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackFlags); foreach(CdrdaoTrack track in discimage.Tracks) { if(track.Subchannel) - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubchannel)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubchannel); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubchannel)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubchannel); switch(track.Tracktype) { case CDRDAO_TRACK_TYPE_AUDIO: { - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdTrackIsrc)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackIsrc); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdTrackIsrc)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackIsrc); break; } case CDRDAO_TRACK_TYPE_MODE2: case CDRDAO_TRACK_TYPE_MODE2_MIX: { - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc); break; } case CDRDAO_TRACK_TYPE_MODE2_RAW: { - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc); break; } case CDRDAO_TRACK_TYPE_MODE1_RAW: { - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEcc)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccP)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccQ)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ); - if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)) - ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEcc)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccP)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccQ)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc); break; } } } - ImageInfo.XmlMediaType = XmlMediaType.OpticalDisc; + imageInfo.XmlMediaType = XmlMediaType.OpticalDisc; - DicConsole.VerboseWriteLine("CDRDAO image describes a disc of type {0}", ImageInfo.MediaType); - if(!string.IsNullOrEmpty(ImageInfo.Comments)) - DicConsole.VerboseWriteLine("CDRDAO comments: {0}", ImageInfo.Comments); + DicConsole.VerboseWriteLine("CDRDAO image describes a disc of type {0}", imageInfo.MediaType); + if(!string.IsNullOrEmpty(imageInfo.Comments)) + DicConsole.VerboseWriteLine("CDRDAO comments: {0}", imageInfo.Comments); return true; } @@ -929,7 +933,7 @@ namespace DiscImageChef.DiscImages } } - public override byte[] ReadDiskTag(MediaTagType tag) + public virtual byte[] ReadDiskTag(MediaTagType tag) { switch(tag) { @@ -944,27 +948,27 @@ namespace DiscImageChef.DiscImages } } - public override byte[] ReadSector(ulong sectorAddress) + public virtual byte[] ReadSector(ulong sectorAddress) { return ReadSectors(sectorAddress, 1); } - public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag) + public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag) { return ReadSectorsTag(sectorAddress, 1, tag); } - public override byte[] ReadSector(ulong sectorAddress, uint track) + public virtual byte[] ReadSector(ulong sectorAddress, uint track) { return ReadSectors(sectorAddress, 1, track); } - public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag) + public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag) { return ReadSectorsTag(sectorAddress, 1, track, tag); } - public override byte[] ReadSectors(ulong sectorAddress, uint length) + public virtual byte[] ReadSectors(ulong sectorAddress, uint length) { foreach(KeyValuePair kvp in from kvp in offsetmap where sectorAddress >= kvp.Value @@ -977,7 +981,7 @@ namespace DiscImageChef.DiscImages throw new ArgumentOutOfRangeException(nameof(sectorAddress), $"Sector address {sectorAddress} not found"); } - public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag) + public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag) { foreach(KeyValuePair kvp in from kvp in offsetmap where sectorAddress >= kvp.Value @@ -990,7 +994,7 @@ namespace DiscImageChef.DiscImages throw new ArgumentOutOfRangeException(nameof(sectorAddress), $"Sector address {sectorAddress} not found"); } - public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track) + public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track) { CdrdaoTrack dicTrack = new CdrdaoTrack {Sequence = 0}; @@ -1082,7 +1086,7 @@ namespace DiscImageChef.DiscImages return buffer; } - public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag) + public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag) { CdrdaoTrack dicTrack = new CdrdaoTrack {Sequence = 0}; @@ -1248,17 +1252,17 @@ namespace DiscImageChef.DiscImages return buffer; } - public override byte[] ReadSectorLong(ulong sectorAddress) + public virtual byte[] ReadSectorLong(ulong sectorAddress) { return ReadSectorsLong(sectorAddress, 1); } - public override byte[] ReadSectorLong(ulong sectorAddress, uint track) + public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track) { return ReadSectorsLong(sectorAddress, 1, track); } - public override byte[] ReadSectorsLong(ulong sectorAddress, uint length) + public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length) { foreach(KeyValuePair kvp in from kvp in offsetmap where sectorAddress >= kvp.Value @@ -1271,7 +1275,7 @@ namespace DiscImageChef.DiscImages throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found"); } - public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track) + public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track) { CdrdaoTrack dicTrack = new CdrdaoTrack {Sequence = 0}; @@ -1354,31 +1358,31 @@ namespace DiscImageChef.DiscImages return buffer; } - public override List GetSessionTracks(Session session) + public virtual List GetSessionTracks(Session session) { return GetSessionTracks(session.SessionSequence); } - public override List GetSessionTracks(ushort session) + public virtual List GetSessionTracks(ushort session) { if(session == 1) return Tracks; throw new ImageNotSupportedException("Session does not exist in disc image"); } - public override bool? VerifySector(ulong sectorAddress) + public virtual bool? VerifySector(ulong sectorAddress) { byte[] buffer = ReadSectorLong(sectorAddress); return CdChecksums.CheckCdSector(buffer); } - public override bool? VerifySector(ulong sectorAddress, uint track) + public virtual bool? VerifySector(ulong sectorAddress, uint track) { byte[] buffer = ReadSectorLong(sectorAddress, track); return CdChecksums.CheckCdSector(buffer); } - public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas, + public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas, out List unknownLbas) { byte[] buffer = ReadSectorsLong(sectorAddress, length); @@ -1408,7 +1412,7 @@ namespace DiscImageChef.DiscImages return failingLbas.Count <= 0; } - public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas, + public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas, out List unknownLbas) { byte[] buffer = ReadSectorsLong(sectorAddress, length, track); @@ -1438,7 +1442,7 @@ namespace DiscImageChef.DiscImages return failingLbas.Count <= 0; } - public override bool? VerifyMediaImage() + public virtual bool? VerifyMediaImage() { return null; } @@ -1497,7 +1501,7 @@ namespace DiscImageChef.DiscImages /// Track # public uint Sequence; /// Filter of file containing track - public Filter Datafilter; + public IFilter Datafilter; /// Path of file containing track public string Datafile; /// Offset of track start in file diff --git a/DiscImageChef.DiscImages/CDRWin.cs b/DiscImageChef.DiscImages/CDRWin.cs index e9127f18..b9550bcd 100644 --- a/DiscImageChef.DiscImages/CDRWin.cs +++ b/DiscImageChef.DiscImages/CDRWin.cs @@ -44,7 +44,7 @@ using DiscImageChef.Filters; namespace DiscImageChef.DiscImages { // TODO: Implement track flags - public class CdrWin : ImagePlugin + public class CdrWin : IMediaImage { // Type for FILE entity /// Data as-is in little-endian @@ -170,9 +170,10 @@ namespace DiscImageChef.DiscImages const string REGEX_POSTGAP = @"\bPOSTGAP\s+(?[\d]+:[\d]+:[\d]+)$"; const string REGEX_FLAGS = @"\bFLAGS\s+(((?DCP)|(?4CH)|(?
PRE)|(?SCMS))\s*)+$";
 
-        Filter cdrwinFilter;
+        IFilter cdrwinFilter;
         StreamReader cueStream;
         CdrWinDisc discimage;
+        ImageInfo imageInfo;
         Stream imageStream;
         /// Dictionary, index is track #, value is TrackFile
         Dictionary offsetmap;
@@ -180,9 +181,7 @@ namespace DiscImageChef.DiscImages
 
         public CdrWin()
         {
-            Name = "CDRWin cuesheet";
-            PluginUuid = new Guid("664568B2-15D4-4E64-8A7A-20BDA8B8386F");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -204,11 +203,16 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "CDRWin CUESheet";
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Partitions => partitions;
+        public virtual string Name => "CDRWin cuesheet";
+        public virtual Guid Id => new Guid("664568B2-15D4-4E64-8A7A-20BDA8B8386F");
 
-        public override List Tracks
+        public virtual string ImageFormat => "CDRWin CUESheet";
+
+        public virtual List Partitions => partitions;
+
+        public virtual List Tracks
         {
             get
             {
@@ -255,10 +259,10 @@ namespace DiscImageChef.DiscImages
             }
         }
 
-        public override List Sessions => discimage.Sessions;
+        public virtual List Sessions => discimage.Sessions;
 
         // Due to .cue format, this method must parse whole file, ignoring errors (those will be thrown by OpenImage()).
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             cdrwinFilter = imageFilter;
 
@@ -319,7 +323,7 @@ namespace DiscImageChef.DiscImages
             }
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             if(imageFilter == null) return false;
 
@@ -1083,99 +1087,99 @@ namespace DiscImageChef.DiscImages
                     DicConsole.DebugWriteLine("CDRWin plugin", "\tPartition size in bytes: {0}", partition.Size);
                 }
 
-                foreach(CdrWinTrack track in discimage.Tracks) ImageInfo.ImageSize += track.Bps * track.Sectors;
-                foreach(CdrWinTrack track in discimage.Tracks) ImageInfo.Sectors += track.Sectors;
+                foreach(CdrWinTrack track in discimage.Tracks) imageInfo.ImageSize += track.Bps * track.Sectors;
+                foreach(CdrWinTrack track in discimage.Tracks) imageInfo.Sectors += track.Sectors;
 
                 if(discimage.Disktype == MediaType.CDG || discimage.Disktype == MediaType.CDEG ||
                    discimage.Disktype == MediaType.CDMIDI)
-                    ImageInfo.SectorSize = 2448; // CD+G subchannels ARE user data, as CD+G are useless without them
+                    imageInfo.SectorSize = 2448; // CD+G subchannels ARE user data, as CD+G are useless without them
                 else if(discimage.Disktype != MediaType.CDROMXA && discimage.Disktype != MediaType.CDDA &&
                         discimage.Disktype != MediaType.CDI &&
-                        discimage.Disktype != MediaType.CDPLUS) ImageInfo.SectorSize = 2048; // Only data tracks
-                else ImageInfo.SectorSize = 2352; // All others
+                        discimage.Disktype != MediaType.CDPLUS) imageInfo.SectorSize = 2048; // Only data tracks
+                else imageInfo.SectorSize = 2352; // All others
 
-                if(discimage.Mcn != null) ImageInfo.ReadableMediaTags.Add(MediaTagType.CD_MCN);
-                if(discimage.Cdtextfile != null) ImageInfo.ReadableMediaTags.Add(MediaTagType.CD_TEXT);
+                if(discimage.Mcn != null) imageInfo.ReadableMediaTags.Add(MediaTagType.CD_MCN);
+                if(discimage.Cdtextfile != null) imageInfo.ReadableMediaTags.Add(MediaTagType.CD_TEXT);
 
                 // Detect ISOBuster extensions
                 if(discimage.Disktypestr != null || discimage.Comment.ToLower().Contains("isobuster") ||
-                   discimage.Sessions.Count > 1) ImageInfo.Application = "ISOBuster";
-                else ImageInfo.Application = "CDRWin";
+                   discimage.Sessions.Count > 1) imageInfo.Application = "ISOBuster";
+                else imageInfo.Application = "CDRWin";
 
-                ImageInfo.CreationTime = imageFilter.GetCreationTime();
-                ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+                imageInfo.CreationTime = imageFilter.GetCreationTime();
+                imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
 
-                ImageInfo.Comments = discimage.Comment;
-                ImageInfo.MediaSerialNumber = discimage.Mcn;
-                ImageInfo.MediaBarcode = discimage.Barcode;
-                ImageInfo.MediaType = discimage.Disktype;
+                imageInfo.Comments = discimage.Comment;
+                imageInfo.MediaSerialNumber = discimage.Mcn;
+                imageInfo.MediaBarcode = discimage.Barcode;
+                imageInfo.MediaType = discimage.Disktype;
 
-                ImageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackFlags);
+                imageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackFlags);
 
                 foreach(CdrWinTrack track in discimage.Tracks)
                     switch(track.Tracktype)
                     {
                         case CDRWIN_TRACK_TYPE_AUDIO:
                         {
-                            if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdTrackIsrc))
-                                ImageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackIsrc);
+                            if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdTrackIsrc))
+                                imageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackIsrc);
                             break;
                         }
                         case CDRWIN_TRACK_TYPE_CDG:
                         {
-                            if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdTrackIsrc))
-                                ImageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackIsrc);
-                            if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubchannel))
-                                ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubchannel);
+                            if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdTrackIsrc))
+                                imageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackIsrc);
+                            if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubchannel))
+                                imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubchannel);
                             break;
                         }
                         case CDRWIN_TRACK_TYPE_MODE2_FORMLESS:
                         case CDRWIN_TRACK_TYPE_CDI:
                         {
-                            if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader))
-                                ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader);
-                            if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc))
-                                ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc);
+                            if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader))
+                                imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader);
+                            if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc))
+                                imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc);
                             break;
                         }
                         case CDRWIN_TRACK_TYPE_MODE2_RAW:
                         case CDRWIN_TRACK_TYPE_CDI_RAW:
                         {
-                            if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync))
-                                ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync);
-                            if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader))
-                                ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader);
-                            if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader))
-                                ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader);
-                            if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc))
-                                ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc);
+                            if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync))
+                                imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync);
+                            if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader))
+                                imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader);
+                            if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader))
+                                imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader);
+                            if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc))
+                                imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc);
                             break;
                         }
                         case CDRWIN_TRACK_TYPE_MODE1_RAW:
                         {
-                            if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync))
-                                ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync);
-                            if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader))
-                                ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader);
-                            if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader))
-                                ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader);
-                            if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEcc))
-                                ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc);
-                            if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccP))
-                                ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP);
-                            if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccQ))
-                                ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ);
-                            if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc))
-                                ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc);
+                            if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync))
+                                imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync);
+                            if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader))
+                                imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader);
+                            if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader))
+                                imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader);
+                            if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEcc))
+                                imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc);
+                            if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccP))
+                                imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP);
+                            if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccQ))
+                                imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ);
+                            if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc))
+                                imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc);
                             break;
                         }
                     }
 
-                ImageInfo.XmlMediaType = XmlMediaType.OpticalDisc;
+                imageInfo.XmlMediaType = XmlMediaType.OpticalDisc;
 
-                DicConsole.VerboseWriteLine("CDRWIN image describes a disc of type {0}", ImageInfo.MediaType);
-                if(!string.IsNullOrEmpty(ImageInfo.Comments))
-                    DicConsole.VerboseWriteLine("CDRWIN comments: {0}", ImageInfo.Comments);
+                DicConsole.VerboseWriteLine("CDRWIN image describes a disc of type {0}", imageInfo.MediaType);
+                if(!string.IsNullOrEmpty(imageInfo.Comments))
+                    DicConsole.VerboseWriteLine("CDRWIN comments: {0}", imageInfo.Comments);
 
                 return true;
             }
@@ -1188,7 +1192,7 @@ namespace DiscImageChef.DiscImages
             }
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             switch(tag)
             {
@@ -1211,27 +1215,27 @@ namespace DiscImageChef.DiscImages
             }
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
             return ReadSectors(sectorAddress, 1);
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             return ReadSectorsTag(sectorAddress, 1, tag);
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             return ReadSectors(sectorAddress, 1, track);
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             return ReadSectorsTag(sectorAddress, 1, track, tag);
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
             foreach(KeyValuePair kvp in from kvp in offsetmap
                                                      where sectorAddress >= kvp.Value
@@ -1244,7 +1248,7 @@ namespace DiscImageChef.DiscImages
             throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             foreach(KeyValuePair kvp in from kvp in offsetmap
                                                      where sectorAddress >= kvp.Value
@@ -1257,7 +1261,7 @@ namespace DiscImageChef.DiscImages
             throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             CdrWinTrack dicTrack = new CdrWinTrack {Sequence = 0};
 
@@ -1361,7 +1365,7 @@ namespace DiscImageChef.DiscImages
             return buffer;
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             CdrWinTrack dicTrack = new CdrWinTrack {Sequence = 0};
 
@@ -1542,17 +1546,17 @@ namespace DiscImageChef.DiscImages
             return buffer;
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             return ReadSectorsLong(sectorAddress, 1);
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             return ReadSectorsLong(sectorAddress, 1, track);
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             foreach(KeyValuePair kvp in from kvp in offsetmap
                                                      where sectorAddress >= kvp.Value
@@ -1565,7 +1569,7 @@ namespace DiscImageChef.DiscImages
             throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             CdrWinTrack dicTrack = new CdrWinTrack {Sequence = 0};
 
@@ -1654,14 +1658,14 @@ namespace DiscImageChef.DiscImages
             return buffer;
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             if(discimage.Sessions.Contains(session)) return GetSessionTracks(session.SessionSequence);
 
             throw new ImageNotSupportedException("Session does not exist in disc image");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             List tracks = new List();
 
@@ -1702,19 +1706,19 @@ namespace DiscImageChef.DiscImages
             return tracks;
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             byte[] buffer = ReadSectorLong(sectorAddress);
             return CdChecksums.CheckCdSector(buffer);
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             byte[] buffer = ReadSectorLong(sectorAddress, track);
             return CdChecksums.CheckCdSector(buffer);
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             byte[] buffer = ReadSectorsLong(sectorAddress, length);
@@ -1744,7 +1748,7 @@ namespace DiscImageChef.DiscImages
             return failingLbas.Count <= 0;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             byte[] buffer = ReadSectorsLong(sectorAddress, length, track);
@@ -1774,7 +1778,7 @@ namespace DiscImageChef.DiscImages
             return failingLbas.Count <= 0;
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return null;
         }
@@ -1892,7 +1896,7 @@ namespace DiscImageChef.DiscImages
             /// Track #
             public uint Sequence;
             /// Filter of file containing track
-            public Filter Datafilter;
+            public IFilter Datafilter;
             /// Offset of track start in file
             public ulong Offset;
             /// Type of file
diff --git a/DiscImageChef.DiscImages/CHD.cs b/DiscImageChef.DiscImages/CHD.cs
index 05522f92..abba9305 100644
--- a/DiscImageChef.DiscImages/CHD.cs
+++ b/DiscImageChef.DiscImages/CHD.cs
@@ -48,7 +48,7 @@ using SharpCompress.Compressors.Deflate;
 namespace DiscImageChef.DiscImages
 {
     // TODO: Implement PCMCIA support
-    public class Chd : ImagePlugin
+    public class Chd : IMediaImage
     {
         /// "GDDD"
         const uint HARD_DISK_METADATA = 0x47444444;
@@ -119,6 +119,7 @@ namespace DiscImageChef.DiscImages
         ulong[] hunkTable;
         uint[] hunkTableSmall;
         byte[] identify;
+        ImageInfo imageInfo;
         Stream imageStream;
         bool isCdrom;
         bool isGdrom;
@@ -136,9 +137,7 @@ namespace DiscImageChef.DiscImages
 
         public Chd()
         {
-            Name = "MAME Compressed Hunks of Data";
-            PluginUuid = new Guid("0D50233A-08BD-47D4-988B-27EAA0358597");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -161,9 +160,14 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "Compressed Hunks of Data";
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Partitions
+        public virtual string Name => "MAME Compressed Hunks of Data";
+        public virtual Guid Id => new Guid("0D50233A-08BD-47D4-988B-27EAA0358597");
+
+        public virtual string ImageFormat => "Compressed Hunks of Data";
+
+        public virtual List Partitions
         {
             get
             {
@@ -175,7 +179,7 @@ namespace DiscImageChef.DiscImages
             }
         }
 
-        public override List Tracks
+        public virtual List Tracks
         {
             get
             {
@@ -187,7 +191,7 @@ namespace DiscImageChef.DiscImages
             }
         }
 
-        public override List Sessions
+        public virtual List Sessions
         {
             get
             {
@@ -199,7 +203,7 @@ namespace DiscImageChef.DiscImages
             }
         }
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -209,7 +213,7 @@ namespace DiscImageChef.DiscImages
             return chdTag.SequenceEqual(magic);
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -282,12 +286,12 @@ namespace DiscImageChef.DiscImages
                     DateTime end = DateTime.UtcNow;
                     System.Console.WriteLine("Took {0} seconds", (end - start).TotalSeconds);
 
-                    ImageInfo.MediaType = MediaType.GENERIC_HDD;
-                    ImageInfo.Sectors = hdrV1.hunksize * hdrV1.totalhunks;
-                    ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
-                    ImageInfo.SectorSize = 512;
-                    ImageInfo.Version = "1";
-                    ImageInfo.ImageSize = ImageInfo.SectorSize * hdrV1.hunksize * hdrV1.totalhunks;
+                    imageInfo.MediaType = MediaType.GENERIC_HDD;
+                    imageInfo.Sectors = hdrV1.hunksize * hdrV1.totalhunks;
+                    imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+                    imageInfo.SectorSize = 512;
+                    imageInfo.Version = "1";
+                    imageInfo.ImageSize = imageInfo.SectorSize * hdrV1.hunksize * hdrV1.totalhunks;
 
                     totalHunks = hdrV1.totalhunks;
                     sectorsPerHunk = hdrV1.hunksize;
@@ -295,9 +299,9 @@ namespace DiscImageChef.DiscImages
                     mapVersion = 1;
                     isHdd = true;
 
-                    ImageInfo.Cylinders = hdrV1.cylinders;
-                    ImageInfo.Heads = hdrV1.heads;
-                    ImageInfo.SectorsPerTrack = hdrV1.sectors;
+                    imageInfo.Cylinders = hdrV1.cylinders;
+                    imageInfo.Heads = hdrV1.heads;
+                    imageInfo.SectorsPerTrack = hdrV1.sectors;
 
                     break;
                 }
@@ -353,12 +357,12 @@ namespace DiscImageChef.DiscImages
                     DateTime end = DateTime.UtcNow;
                     System.Console.WriteLine("Took {0} seconds", (end - start).TotalSeconds);
 
-                    ImageInfo.MediaType = MediaType.GENERIC_HDD;
-                    ImageInfo.Sectors = hdrV2.hunksize * hdrV2.totalhunks;
-                    ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
-                    ImageInfo.SectorSize = hdrV2.seclen;
-                    ImageInfo.Version = "2";
-                    ImageInfo.ImageSize = ImageInfo.SectorSize * hdrV2.hunksize * hdrV2.totalhunks;
+                    imageInfo.MediaType = MediaType.GENERIC_HDD;
+                    imageInfo.Sectors = hdrV2.hunksize * hdrV2.totalhunks;
+                    imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+                    imageInfo.SectorSize = hdrV2.seclen;
+                    imageInfo.Version = "2";
+                    imageInfo.ImageSize = imageInfo.SectorSize * hdrV2.hunksize * hdrV2.totalhunks;
 
                     totalHunks = hdrV2.totalhunks;
                     sectorsPerHunk = hdrV2.hunksize;
@@ -366,9 +370,9 @@ namespace DiscImageChef.DiscImages
                     mapVersion = 1;
                     isHdd = true;
 
-                    ImageInfo.Cylinders = hdrV2.cylinders;
-                    ImageInfo.Heads = hdrV2.heads;
-                    ImageInfo.SectorsPerTrack = hdrV2.sectors;
+                    imageInfo.Cylinders = hdrV2.cylinders;
+                    imageInfo.Heads = hdrV2.heads;
+                    imageInfo.SectorsPerTrack = hdrV2.sectors;
 
                     break;
                 }
@@ -409,8 +413,8 @@ namespace DiscImageChef.DiscImages
 
                     nextMetaOff = hdrV3.metaoffset;
 
-                    ImageInfo.ImageSize = hdrV3.logicalbytes;
-                    ImageInfo.Version = "3";
+                    imageInfo.ImageSize = hdrV3.logicalbytes;
+                    imageInfo.Version = "3";
 
                     totalHunks = hdrV3.totalhunks;
                     bytesPerHunk = hdrV3.hunkbytes;
@@ -453,8 +457,8 @@ namespace DiscImageChef.DiscImages
 
                     nextMetaOff = hdrV4.metaoffset;
 
-                    ImageInfo.ImageSize = hdrV4.logicalbytes;
-                    ImageInfo.Version = "4";
+                    imageInfo.ImageSize = hdrV4.logicalbytes;
+                    imageInfo.Version = "4";
 
                     totalHunks = hdrV4.totalhunks;
                     bytesPerHunk = hdrV4.hunkbytes;
@@ -536,8 +540,8 @@ namespace DiscImageChef.DiscImages
 
                     nextMetaOff = hdrV5.metaoffset;
 
-                    ImageInfo.ImageSize = hdrV5.logicalbytes;
-                    ImageInfo.Version = "5";
+                    imageInfo.ImageSize = hdrV5.logicalbytes;
+                    imageInfo.Version = "5";
 
                     totalHunks = (uint)(hdrV5.logicalbytes / hdrV5.hunkbytes);
                     bytesPerHunk = hdrV5.hunkbytes;
@@ -591,10 +595,10 @@ namespace DiscImageChef.DiscImages
                             if(gdddMatch.Success)
                             {
                                 isHdd = true;
-                                ImageInfo.SectorSize = uint.Parse(gdddMatch.Groups["bps"].Value);
-                                ImageInfo.Cylinders = uint.Parse(gdddMatch.Groups["cylinders"].Value);
-                                ImageInfo.Heads = uint.Parse(gdddMatch.Groups["heads"].Value);
-                                ImageInfo.SectorsPerTrack = uint.Parse(gdddMatch.Groups["sectors"].Value);
+                                imageInfo.SectorSize = uint.Parse(gdddMatch.Groups["bps"].Value);
+                                imageInfo.Cylinders = uint.Parse(gdddMatch.Groups["cylinders"].Value);
+                                imageInfo.Heads = uint.Parse(gdddMatch.Groups["heads"].Value);
+                                imageInfo.SectorsPerTrack = uint.Parse(gdddMatch.Groups["sectors"].Value);
                             }
                             break;
                         // "CHCD"
@@ -1054,33 +1058,33 @@ namespace DiscImageChef.DiscImages
                             Identify.IdentifyDevice? idnt = Identify.Decode(meta);
                             if(idnt.HasValue)
                             {
-                                ImageInfo.MediaManufacturer = idnt.Value.MediaManufacturer;
-                                ImageInfo.MediaSerialNumber = idnt.Value.MediaSerial;
-                                ImageInfo.DriveModel = idnt.Value.Model;
-                                ImageInfo.DriveSerialNumber = idnt.Value.SerialNumber;
-                                ImageInfo.DriveFirmwareRevision = idnt.Value.FirmwareRevision;
+                                imageInfo.MediaManufacturer = idnt.Value.MediaManufacturer;
+                                imageInfo.MediaSerialNumber = idnt.Value.MediaSerial;
+                                imageInfo.DriveModel = idnt.Value.Model;
+                                imageInfo.DriveSerialNumber = idnt.Value.SerialNumber;
+                                imageInfo.DriveFirmwareRevision = idnt.Value.FirmwareRevision;
                                 if(idnt.Value.CurrentCylinders > 0 && idnt.Value.CurrentHeads > 0 &&
                                    idnt.Value.CurrentSectorsPerTrack > 0)
                                 {
-                                    ImageInfo.Cylinders = idnt.Value.CurrentCylinders;
-                                    ImageInfo.Heads = idnt.Value.CurrentHeads;
-                                    ImageInfo.SectorsPerTrack = idnt.Value.CurrentSectorsPerTrack;
+                                    imageInfo.Cylinders = idnt.Value.CurrentCylinders;
+                                    imageInfo.Heads = idnt.Value.CurrentHeads;
+                                    imageInfo.SectorsPerTrack = idnt.Value.CurrentSectorsPerTrack;
                                 }
                                 else
                                 {
-                                    ImageInfo.Cylinders = idnt.Value.Cylinders;
-                                    ImageInfo.Heads = idnt.Value.Heads;
-                                    ImageInfo.SectorsPerTrack = idnt.Value.SectorsPerTrack;
+                                    imageInfo.Cylinders = idnt.Value.Cylinders;
+                                    imageInfo.Heads = idnt.Value.Heads;
+                                    imageInfo.SectorsPerTrack = idnt.Value.SectorsPerTrack;
                                 }
                             }
                             identify = meta;
-                            if(!ImageInfo.ReadableMediaTags.Contains(MediaTagType.ATA_IDENTIFY))
-                                ImageInfo.ReadableMediaTags.Add(MediaTagType.ATA_IDENTIFY);
+                            if(!imageInfo.ReadableMediaTags.Contains(MediaTagType.ATA_IDENTIFY))
+                                imageInfo.ReadableMediaTags.Add(MediaTagType.ATA_IDENTIFY);
                             break;
                         case PCMCIA_CIS_METADATA:
                             cis = meta;
-                            if(!ImageInfo.ReadableMediaTags.Contains(MediaTagType.PCMCIA_CIS))
-                                ImageInfo.ReadableMediaTags.Add(MediaTagType.PCMCIA_CIS);
+                            if(!imageInfo.ReadableMediaTags.Contains(MediaTagType.PCMCIA_CIS))
+                                imageInfo.ReadableMediaTags.Add(MediaTagType.PCMCIA_CIS);
                             break;
                     }
 
@@ -1089,30 +1093,30 @@ namespace DiscImageChef.DiscImages
 
                 if(isHdd)
                 {
-                    sectorsPerHunk = bytesPerHunk / ImageInfo.SectorSize;
-                    ImageInfo.Sectors = ImageInfo.ImageSize / ImageInfo.SectorSize;
-                    ImageInfo.MediaType = MediaType.GENERIC_HDD;
-                    ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+                    sectorsPerHunk = bytesPerHunk / imageInfo.SectorSize;
+                    imageInfo.Sectors = imageInfo.ImageSize / imageInfo.SectorSize;
+                    imageInfo.MediaType = MediaType.GENERIC_HDD;
+                    imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
                 }
                 else if(isCdrom)
                 {
                     // Hardcoded on MAME for CD-ROM
                     sectorsPerHunk = 8;
-                    ImageInfo.MediaType = MediaType.CDROM;
-                    ImageInfo.XmlMediaType = XmlMediaType.OpticalDisc;
+                    imageInfo.MediaType = MediaType.CDROM;
+                    imageInfo.XmlMediaType = XmlMediaType.OpticalDisc;
 
                     foreach(Track dicTrack in tracks.Values)
-                        ImageInfo.Sectors += dicTrack.TrackEndSector - dicTrack.TrackStartSector + 1;
+                        imageInfo.Sectors += dicTrack.TrackEndSector - dicTrack.TrackStartSector + 1;
                 }
                 else if(isGdrom)
                 {
                     // Hardcoded on MAME for GD-ROM
                     sectorsPerHunk = 8;
-                    ImageInfo.MediaType = MediaType.GDROM;
-                    ImageInfo.XmlMediaType = XmlMediaType.OpticalDisc;
+                    imageInfo.MediaType = MediaType.GDROM;
+                    imageInfo.XmlMediaType = XmlMediaType.OpticalDisc;
 
                     foreach(Track dicTrack in tracks.Values)
-                        ImageInfo.Sectors += dicTrack.TrackEndSector - dicTrack.TrackStartSector + 1;
+                        imageInfo.Sectors += dicTrack.TrackEndSector - dicTrack.TrackStartSector + 1;
                 }
                 else throw new ImageNotSupportedException("Image does not represent a known media, aborting");
             }
@@ -1140,8 +1144,8 @@ namespace DiscImageChef.DiscImages
                     offsetmap.Add(dicTrack.TrackStartSector, dicTrack.TrackSequence);
 
                     if(dicTrack.TrackSubchannelType != TrackSubchannelType.None)
-                        if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubchannel))
-                            ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubchannel);
+                        if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubchannel))
+                            imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubchannel);
 
                     switch(dicTrack.TrackType)
                     {
@@ -1149,58 +1153,58 @@ namespace DiscImageChef.DiscImages
                         case TrackType.CdMode2Form1:
                             if(dicTrack.TrackRawBytesPerSector == 2352)
                             {
-                                if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync))
-                                    ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync);
-                                if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader))
-                                    ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader);
-                                if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader))
-                                    ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader);
-                                if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEcc))
-                                    ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc);
-                                if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccP))
-                                    ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP);
-                                if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccQ))
-                                    ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ);
-                                if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc))
-                                    ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc);
+                                if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync))
+                                    imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync);
+                                if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader))
+                                    imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader);
+                                if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader))
+                                    imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader);
+                                if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEcc))
+                                    imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc);
+                                if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccP))
+                                    imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP);
+                                if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccQ))
+                                    imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ);
+                                if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc))
+                                    imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc);
                             }
                             break;
                         case TrackType.CdMode2Form2:
                             if(dicTrack.TrackRawBytesPerSector == 2352)
                             {
-                                if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync))
-                                    ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync);
-                                if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader))
-                                    ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader);
-                                if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader))
-                                    ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader);
-                                if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc))
-                                    ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc);
+                                if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync))
+                                    imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync);
+                                if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader))
+                                    imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader);
+                                if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader))
+                                    imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader);
+                                if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc))
+                                    imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc);
                             }
                             break;
                         case TrackType.CdMode2Formless:
                             if(dicTrack.TrackRawBytesPerSector == 2352)
                             {
-                                if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync))
-                                    ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync);
-                                if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader))
-                                    ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader);
+                                if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync))
+                                    imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync);
+                                if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader))
+                                    imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader);
                             }
                             break;
                     }
 
-                    if(dicTrack.TrackBytesPerSector > ImageInfo.SectorSize)
-                        ImageInfo.SectorSize = (uint)dicTrack.TrackBytesPerSector;
+                    if(dicTrack.TrackBytesPerSector > imageInfo.SectorSize)
+                        imageInfo.SectorSize = (uint)dicTrack.TrackBytesPerSector;
 
                     partitions.Add(partition);
                 }
 
-                ImageInfo.HasPartitions = true;
-                ImageInfo.HasSessions = true;
+                imageInfo.HasPartitions = true;
+                imageInfo.HasSessions = true;
             }
 
-            maxBlockCache = (int)(MAX_CACHE_SIZE / (ImageInfo.SectorSize * sectorsPerHunk));
-            maxSectorCache = (int)(MAX_CACHE_SIZE / ImageInfo.SectorSize);
+            maxBlockCache = (int)(MAX_CACHE_SIZE / (imageInfo.SectorSize * sectorsPerHunk));
+            maxSectorCache = (int)(MAX_CACHE_SIZE / imageInfo.SectorSize);
 
             imageStream = stream;
 
@@ -1209,7 +1213,7 @@ namespace DiscImageChef.DiscImages
 
             // TODO: Detect CompactFlash
             // TODO: Get manufacturer and drive name from CIS if applicable
-            if(cis != null) ImageInfo.MediaType = MediaType.PCCardTypeI;
+            if(cis != null) imageInfo.MediaType = MediaType.PCCardTypeI;
 
             return true;
         }
@@ -1243,7 +1247,7 @@ namespace DiscImageChef.DiscImages
                     imageStream.Seek((long)offset, SeekOrigin.Begin);
                     imageStream.Read(compHunk, 0, compHunk.Length);
 
-                    if(length == sectorsPerHunk * ImageInfo.SectorSize) hunk = compHunk;
+                    if(length == sectorsPerHunk * imageInfo.SectorSize) hunk = compHunk;
                     else if((ChdCompression)hdrCompression > ChdCompression.Zlib)
                         throw new
                             ImageNotSupportedException($"Unsupported compression {(ChdCompression)hdrCompression}");
@@ -1251,11 +1255,11 @@ namespace DiscImageChef.DiscImages
                     {
                         DeflateStream zStream =
                             new DeflateStream(new MemoryStream(compHunk), CompressionMode.Decompress);
-                        hunk = new byte[sectorsPerHunk * ImageInfo.SectorSize];
-                        int read = zStream.Read(hunk, 0, (int)(sectorsPerHunk * ImageInfo.SectorSize));
-                        if(read != sectorsPerHunk * ImageInfo.SectorSize)
+                        hunk = new byte[sectorsPerHunk * imageInfo.SectorSize];
+                        int read = zStream.Read(hunk, 0, (int)(sectorsPerHunk * imageInfo.SectorSize));
+                        if(read != sectorsPerHunk * imageInfo.SectorSize)
                             throw new
-                                IOException($"Unable to decompress hunk correctly, got {read} bytes, expected {sectorsPerHunk * ImageInfo.SectorSize}");
+                                IOException($"Unable to decompress hunk correctly, got {read} bytes, expected {sectorsPerHunk * imageInfo.SectorSize}");
 
                         zStream.Close();
                     }
@@ -1344,7 +1348,7 @@ namespace DiscImageChef.DiscImages
             return hunk;
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             if(isHdd) return null;
 
@@ -1352,7 +1356,7 @@ namespace DiscImageChef.DiscImages
             return CdChecksums.CheckCdSector(buffer);
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             if(isHdd)
                 throw new FeaturedNotSupportedByDiscImageException("Cannot access optical tracks on a hard disk image");
@@ -1360,7 +1364,7 @@ namespace DiscImageChef.DiscImages
             return VerifySector(GetAbsoluteSector(sectorAddress, track));
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             unknownLbas = new List();
@@ -1392,7 +1396,7 @@ namespace DiscImageChef.DiscImages
             return failingLbas.Count <= 0;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             unknownLbas = new List();
@@ -1424,7 +1428,7 @@ namespace DiscImageChef.DiscImages
             return failingLbas.Count <= 0;
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             byte[] calculated;
             if(mapVersion >= 3)
@@ -1447,9 +1451,9 @@ namespace DiscImageChef.DiscImages
             return expectedChecksum.SequenceEqual(calculated);
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress),
                                                       $"Sector address {sectorAddress} not found");
 
@@ -1458,7 +1462,7 @@ namespace DiscImageChef.DiscImages
 
             if(!sectorCache.TryGetValue(sectorAddress, out byte[] sector))
             {
-                if(isHdd) sectorSize = ImageInfo.SectorSize;
+                if(isHdd) sectorSize = imageInfo.SectorSize;
                 else
                 {
                     track = GetTrack(sectorAddress);
@@ -1470,7 +1474,7 @@ namespace DiscImageChef.DiscImages
 
                 byte[] hunk = GetHunk(hunkNo);
 
-                sector = new byte[ImageInfo.SectorSize];
+                sector = new byte[imageInfo.SectorSize];
                 Array.Copy(hunk, (int)secOff, sector, 0, sector.Length);
 
                 if(sectorCache.Count >= maxSectorCache) sectorCache.Clear();
@@ -1549,11 +1553,11 @@ namespace DiscImageChef.DiscImages
             return buffer;
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             if(isHdd) throw new FeatureNotPresentImageException("Hard disk images do not have sector tags");
 
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress),
                                                       $"Sector address {sectorAddress} not found");
 
@@ -1571,7 +1575,7 @@ namespace DiscImageChef.DiscImages
 
                 byte[] hunk = GetHunk(hunkNo);
 
-                sector = new byte[ImageInfo.SectorSize];
+                sector = new byte[imageInfo.SectorSize];
                 Array.Copy(hunk, (int)secOff, sector, 0, sector.Length);
 
                 if(sectorCache.Count >= maxSectorCache) sectorCache.Clear();
@@ -1765,15 +1769,15 @@ namespace DiscImageChef.DiscImages
             return buffer;
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress),
                                                       $"Sector address {sectorAddress} not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length),
-                                                      $"Requested more sectors ({sectorAddress + length}) than available ({ImageInfo.Sectors})");
+                                                      $"Requested more sectors ({sectorAddress + length}) than available ({imageInfo.Sectors})");
 
             MemoryStream ms = new MemoryStream();
 
@@ -1786,15 +1790,15 @@ namespace DiscImageChef.DiscImages
             return ms.ToArray();
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress),
                                                       $"Sector address {sectorAddress} not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length),
-                                                      $"Requested more sectors ({sectorAddress + length}) than available ({ImageInfo.Sectors})");
+                                                      $"Requested more sectors ({sectorAddress + length}) than available ({imageInfo.Sectors})");
 
             MemoryStream ms = new MemoryStream();
 
@@ -1807,11 +1811,11 @@ namespace DiscImageChef.DiscImages
             return ms.ToArray();
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             if(isHdd) return ReadSector(sectorAddress);
 
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress),
                                                       $"Sector address {sectorAddress} not found");
 
@@ -1829,7 +1833,7 @@ namespace DiscImageChef.DiscImages
 
                 byte[] hunk = GetHunk(hunkNo);
 
-                sector = new byte[ImageInfo.SectorSize];
+                sector = new byte[imageInfo.SectorSize];
                 Array.Copy(hunk, (int)secOff, sector, 0, sector.Length);
 
                 if(sectorCache.Count >= maxSectorCache) sectorCache.Clear();
@@ -1850,15 +1854,15 @@ namespace DiscImageChef.DiscImages
             return buffer;
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress),
                                                       $"Sector address {sectorAddress} not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length),
-                                                      $"Requested more sectors ({sectorAddress + length}) than available ({ImageInfo.Sectors})");
+                                                      $"Requested more sectors ({sectorAddress + length}) than available ({imageInfo.Sectors})");
 
             MemoryStream ms = new MemoryStream();
 
@@ -1871,16 +1875,16 @@ namespace DiscImageChef.DiscImages
             return ms.ToArray();
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
-            if(ImageInfo.ReadableMediaTags.Contains(MediaTagType.ATA_IDENTIFY)) return identify;
+            if(imageInfo.ReadableMediaTags.Contains(MediaTagType.ATA_IDENTIFY)) return identify;
 
-            if(ImageInfo.ReadableMediaTags.Contains(MediaTagType.PCMCIA_CIS)) return cis;
+            if(imageInfo.ReadableMediaTags.Contains(MediaTagType.PCMCIA_CIS)) return cis;
 
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             if(isHdd)
                 throw new FeaturedNotSupportedByDiscImageException("Cannot access optical tracks on a hard disk image");
@@ -1888,7 +1892,7 @@ namespace DiscImageChef.DiscImages
             return GetSessionTracks(session.SessionSequence);
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             if(isHdd)
                 throw new FeaturedNotSupportedByDiscImageException("Cannot access optical tracks on a hard disk image");
@@ -1896,7 +1900,7 @@ namespace DiscImageChef.DiscImages
             return tracks.Values.Where(track => track.TrackSession == session).ToList();
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             if(isHdd)
                 throw new FeaturedNotSupportedByDiscImageException("Cannot access optical tracks on a hard disk image");
@@ -1904,7 +1908,7 @@ namespace DiscImageChef.DiscImages
             return ReadSector(GetAbsoluteSector(sectorAddress, track));
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             if(isHdd)
                 throw new FeaturedNotSupportedByDiscImageException("Cannot access optical tracks on a hard disk image");
@@ -1912,7 +1916,7 @@ namespace DiscImageChef.DiscImages
             return ReadSectorTag(GetAbsoluteSector(sectorAddress, track), tag);
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             if(isHdd)
                 throw new FeaturedNotSupportedByDiscImageException("Cannot access optical tracks on a hard disk image");
@@ -1920,7 +1924,7 @@ namespace DiscImageChef.DiscImages
             return ReadSectors(GetAbsoluteSector(sectorAddress, track), length);
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             if(isHdd)
                 throw new FeaturedNotSupportedByDiscImageException("Cannot access optical tracks on a hard disk image");
@@ -1928,7 +1932,7 @@ namespace DiscImageChef.DiscImages
             return ReadSectorsTag(GetAbsoluteSector(sectorAddress, track), length, tag);
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             if(isHdd)
                 throw new FeaturedNotSupportedByDiscImageException("Cannot access optical tracks on a hard disk image");
@@ -1936,7 +1940,7 @@ namespace DiscImageChef.DiscImages
             return ReadSectorLong(GetAbsoluteSector(sectorAddress, track));
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             if(isHdd)
                 throw new FeaturedNotSupportedByDiscImageException("Cannot access optical tracks on a hard disk image");
diff --git a/DiscImageChef.DiscImages/CPCDSK.cs b/DiscImageChef.DiscImages/CPCDSK.cs
index ff2661f9..834c3484 100644
--- a/DiscImageChef.DiscImages/CPCDSK.cs
+++ b/DiscImageChef.DiscImages/CPCDSK.cs
@@ -43,7 +43,7 @@ using DiscImageChef.Filters;
 
 namespace DiscImageChef.DiscImages
 {
-    public class Cpcdsk : ImagePlugin
+    public class Cpcdsk : IMediaImage
     {
         /// 
         ///     Identifier for CPCEMU disk images, "MV - CPCEMU Disk-File"
@@ -76,13 +76,12 @@ namespace DiscImageChef.DiscImages
         Dictionary addressMarks;
 
         bool extended;
+        ImageInfo imageInfo;
         Dictionary sectors;
 
         public Cpcdsk()
         {
-            Name = "CPCEMU Disk-File and Extended CPC Disk-File";
-            PluginUuid = new Guid("724B16CC-ADB9-492E-BA07-CAEEC1012B16");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -107,18 +106,23 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => extended ? "CPCEMU Extended disk image" : "CPCEMU disk image";
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Partitions =>
+        public virtual string Name => "CPCEMU Disk-File and Extended CPC Disk-File";
+        public virtual Guid Id => new Guid("724B16CC-ADB9-492E-BA07-CAEEC1012B16");
+
+        public virtual string ImageFormat => extended ? "CPCEMU Extended disk image" : "CPCEMU disk image";
+
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Sessions =>
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -139,7 +143,7 @@ namespace DiscImageChef.DiscImages
                    du54Id.SequenceEqual(header.magic);
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -296,20 +300,20 @@ namespace DiscImageChef.DiscImages
                         sectors.Add(currentSector, thisTrackSectors[s]);
                         addressMarks.Add(currentSector, thisTrackAddressMarks[s]);
                         currentSector++;
-                        if(thisTrackSectors[s].Length > ImageInfo.SectorSize)
-                            ImageInfo.SectorSize = (uint)thisTrackSectors[s].Length;
+                        if(thisTrackSectors[s].Length > imageInfo.SectorSize)
+                            imageInfo.SectorSize = (uint)thisTrackSectors[s].Length;
                     }
 
                     stream.Seek(trackPos, SeekOrigin.Begin);
                     if(extended)
                     {
                         stream.Seek(header.tracksizeTable[i * header.sides + j] * 256, SeekOrigin.Current);
-                        ImageInfo.ImageSize += (ulong)(header.tracksizeTable[i * header.sides + j] * 256) - 256;
+                        imageInfo.ImageSize += (ulong)(header.tracksizeTable[i * header.sides + j] * 256) - 256;
                     }
                     else
                     {
                         stream.Seek(header.tracksize, SeekOrigin.Current);
-                        ImageInfo.ImageSize += (ulong)header.tracksize - 256;
+                        imageInfo.ImageSize += (ulong)header.tracksize - 256;
                     }
 
                     readtracks++;
@@ -320,14 +324,14 @@ namespace DiscImageChef.DiscImages
             DicConsole.DebugWriteLine("CPCDSK plugin", "Read {0} tracks", readtracks);
             DicConsole.DebugWriteLine("CPCDSK plugin", "All tracks are same size? {0}", allTracksSameSize);
 
-            ImageInfo.Application = StringHandlers.CToString(header.creator);
-            ImageInfo.CreationTime = imageFilter.GetCreationTime();
-            ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
-            ImageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
-            ImageInfo.Sectors = (ulong)sectors.Count;
-            ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
-            ImageInfo.MediaType = MediaType.CompactFloppy;
-            ImageInfo.ReadableSectorTags.Add(SectorTagType.FloppyAddressMark);
+            imageInfo.Application = StringHandlers.CToString(header.creator);
+            imageInfo.CreationTime = imageFilter.GetCreationTime();
+            imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+            imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
+            imageInfo.Sectors = (ulong)sectors.Count;
+            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+            imageInfo.MediaType = MediaType.CompactFloppy;
+            imageInfo.ReadableSectorTags.Add(SectorTagType.FloppyAddressMark);
 
             // Debug writing full disk as raw
             /*
@@ -341,9 +345,9 @@ namespace DiscImageChef.DiscImages
             foo.Close();
             */
 
-            ImageInfo.Cylinders = header.tracks;
-            ImageInfo.Heads = header.sides;
-            ImageInfo.SectorsPerTrack = (uint)(ImageInfo.Sectors / (ImageInfo.Cylinders * ImageInfo.Heads));
+            imageInfo.Cylinders = header.tracks;
+            imageInfo.Heads = header.sides;
+            imageInfo.SectorsPerTrack = (uint)(imageInfo.Sectors / (imageInfo.Cylinders * imageInfo.Heads));
 
             return true;
         }
@@ -364,20 +368,20 @@ namespace DiscImageChef.DiscImages
             }
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
             if(sectors.TryGetValue(sectorAddress, out byte[] sector)) return sector;
 
             throw new ArgumentOutOfRangeException(nameof(sectorAddress), $"Sector address {sectorAddress} not found");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress),
                                                       $"Sector address {sectorAddress} not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
             MemoryStream ms = new MemoryStream();
@@ -391,7 +395,7 @@ namespace DiscImageChef.DiscImages
             return ms.ToArray();
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             if(tag != SectorTagType.FloppyAddressMark)
                 throw new FeatureUnsupportedImageException($"Tag {tag} not supported by image format");
@@ -401,16 +405,16 @@ namespace DiscImageChef.DiscImages
             throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             if(tag != SectorTagType.FloppyAddressMark)
                 throw new FeatureUnsupportedImageException($"Tag {tag} not supported by image format");
 
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress),
                                                       $"Sector address {sectorAddress} not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
             MemoryStream ms = new MemoryStream();
@@ -424,88 +428,88 @@ namespace DiscImageChef.DiscImages
             return ms.ToArray();
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             return null;
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
             unknownLbas = new List();
-            for(ulong i = 0; i < ImageInfo.Sectors; i++) unknownLbas.Add(i);
+            for(ulong i = 0; i < imageInfo.Sectors; i++) unknownLbas.Add(i);
 
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return null;
         }
diff --git a/DiscImageChef.DiscImages/CisCopy.cs b/DiscImageChef.DiscImages/CisCopy.cs
index 8fae59e2..54690658 100644
--- a/DiscImageChef.DiscImages/CisCopy.cs
+++ b/DiscImageChef.DiscImages/CisCopy.cs
@@ -55,15 +55,14 @@ namespace DiscImageChef.DiscImages
      * 2) High compression, algorithm unknown
      * Then the data for whole tracks follow.
      */
-    public class CisCopy : ImagePlugin
+    public class CisCopy : IMediaImage
     {
         byte[] decodedDisk;
+        ImageInfo imageInfo;
 
         public CisCopy()
         {
-            Name = "CisCopy Disk Image (DC-File)";
-            PluginUuid = new Guid("EDF20CC7-6012-49E2-9E92-663A53E42130");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -88,18 +87,22 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "CisCopy";
+        public virtual string Name => "CisCopy Disk Image (DC-File)";
+        public virtual Guid Id => new Guid("EDF20CC7-6012-49E2-9E92-663A53E42130");
 
-        public override List Partitions =>
+        public virtual string ImageFormat => "CisCopy";
+
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Sessions =>
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
+        public virtual ImageInfo Info => imageInfo;
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -169,7 +172,7 @@ namespace DiscImageChef.DiscImages
             return true;
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -243,87 +246,87 @@ namespace DiscImageChef.DiscImages
                         debugStream.Close();
             */
 
-            ImageInfo.Application = "CisCopy";
-            ImageInfo.CreationTime = imageFilter.GetCreationTime();
-            ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
-            ImageInfo.MediaTitle = imageFilter.GetFilename();
-            ImageInfo.ImageSize = (ulong)(stream.Length - 2 - trackBytes.Length);
-            ImageInfo.SectorSize = 512;
+            imageInfo.Application = "CisCopy";
+            imageInfo.CreationTime = imageFilter.GetCreationTime();
+            imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+            imageInfo.MediaTitle = imageFilter.GetFilename();
+            imageInfo.ImageSize = (ulong)(stream.Length - 2 - trackBytes.Length);
+            imageInfo.SectorSize = 512;
 
             switch(type)
             {
                 case DiskType.MD1DD8:
-                    ImageInfo.MediaType = MediaType.DOS_525_SS_DD_8;
-                    ImageInfo.Sectors = 40 * 1 * 8;
-                    ImageInfo.Heads = 1;
-                    ImageInfo.Cylinders = 40;
-                    ImageInfo.SectorsPerTrack = 8;
+                    imageInfo.MediaType = MediaType.DOS_525_SS_DD_8;
+                    imageInfo.Sectors = 40 * 1 * 8;
+                    imageInfo.Heads = 1;
+                    imageInfo.Cylinders = 40;
+                    imageInfo.SectorsPerTrack = 8;
                     break;
                 case DiskType.MD2DD8:
-                    ImageInfo.MediaType = MediaType.DOS_525_DS_DD_8;
-                    ImageInfo.Sectors = 40 * 2 * 8;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.Cylinders = 40;
-                    ImageInfo.SectorsPerTrack = 8;
+                    imageInfo.MediaType = MediaType.DOS_525_DS_DD_8;
+                    imageInfo.Sectors = 40 * 2 * 8;
+                    imageInfo.Heads = 2;
+                    imageInfo.Cylinders = 40;
+                    imageInfo.SectorsPerTrack = 8;
                     break;
                 case DiskType.MD1DD:
-                    ImageInfo.MediaType = MediaType.DOS_525_SS_DD_9;
-                    ImageInfo.Sectors = 40 * 1 * 9;
-                    ImageInfo.Heads = 1;
-                    ImageInfo.Cylinders = 40;
-                    ImageInfo.SectorsPerTrack = 9;
+                    imageInfo.MediaType = MediaType.DOS_525_SS_DD_9;
+                    imageInfo.Sectors = 40 * 1 * 9;
+                    imageInfo.Heads = 1;
+                    imageInfo.Cylinders = 40;
+                    imageInfo.SectorsPerTrack = 9;
                     break;
                 case DiskType.MD2DD:
-                    ImageInfo.MediaType = MediaType.DOS_525_DS_DD_9;
-                    ImageInfo.Sectors = 40 * 2 * 9;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.Cylinders = 40;
-                    ImageInfo.SectorsPerTrack = 9;
+                    imageInfo.MediaType = MediaType.DOS_525_DS_DD_9;
+                    imageInfo.Sectors = 40 * 2 * 9;
+                    imageInfo.Heads = 2;
+                    imageInfo.Cylinders = 40;
+                    imageInfo.SectorsPerTrack = 9;
                     break;
                 case DiskType.MF2DD:
-                    ImageInfo.MediaType = MediaType.DOS_35_DS_DD_9;
-                    ImageInfo.Sectors = 80 * 2 * 9;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.SectorsPerTrack = 9;
+                    imageInfo.MediaType = MediaType.DOS_35_DS_DD_9;
+                    imageInfo.Sectors = 80 * 2 * 9;
+                    imageInfo.Heads = 2;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.SectorsPerTrack = 9;
                     break;
                 case DiskType.MD2HD:
-                    ImageInfo.MediaType = MediaType.DOS_525_HD;
-                    ImageInfo.Sectors = 80 * 2 * 15;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.SectorsPerTrack = 15;
+                    imageInfo.MediaType = MediaType.DOS_525_HD;
+                    imageInfo.Sectors = 80 * 2 * 15;
+                    imageInfo.Heads = 2;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.SectorsPerTrack = 15;
                     break;
                 case DiskType.MF2HD:
-                    ImageInfo.MediaType = MediaType.DOS_35_HD;
-                    ImageInfo.Sectors = 80 * 2 * 18;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.SectorsPerTrack = 18;
+                    imageInfo.MediaType = MediaType.DOS_35_HD;
+                    imageInfo.Sectors = 80 * 2 * 18;
+                    imageInfo.Heads = 2;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.SectorsPerTrack = 18;
                     break;
             }
 
-            ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
             decodedDisk = decodedImage.ToArray();
 
             decodedImage.Close();
 
-            DicConsole.VerboseWriteLine("CisCopy image contains a disk of type {0}", ImageInfo.MediaType);
+            DicConsole.VerboseWriteLine("CisCopy image contains a disk of type {0}", imageInfo.MediaType);
 
             return true;
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             return null;
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
@@ -334,7 +337,7 @@ namespace DiscImageChef.DiscImages
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
@@ -345,93 +348,93 @@ namespace DiscImageChef.DiscImages
             return null;
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return null;
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
             return ReadSectors(sectorAddress, 1);
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
-            byte[] buffer = new byte[length * ImageInfo.SectorSize];
+            byte[] buffer = new byte[length * imageInfo.SectorSize];
 
-            Array.Copy(decodedDisk, (int)sectorAddress * ImageInfo.SectorSize, buffer, 0,
-                       length * ImageInfo.SectorSize);
+            Array.Copy(decodedDisk, (int)sectorAddress * imageInfo.SectorSize, buffer, 0,
+                       length * imageInfo.SectorSize);
 
             return buffer;
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
diff --git a/DiscImageChef.DiscImages/CloneCD.cs b/DiscImageChef.DiscImages/CloneCD.cs
index 2acfddd0..256cb046 100644
--- a/DiscImageChef.DiscImages/CloneCD.cs
+++ b/DiscImageChef.DiscImages/CloneCD.cs
@@ -43,7 +43,7 @@ using DiscImageChef.Filters;
 
 namespace DiscImageChef.DiscImages
 {
-    public class CloneCd : ImagePlugin
+    public class CloneCd : IMediaImage
     {
         const string CCD_IDENTIFIER = @"^\s*\[CloneCD\]";
         const string DISC_IDENTIFIER = @"^\s*\[Disc\]";
@@ -77,25 +77,24 @@ namespace DiscImageChef.DiscImages
         const string CDTEXT_ENTRY = @"^\s*Entry\s*(?\d+)\s*=\s*(?([0-9a-fA-F]+\s*)+)";
         string catalog; // TODO: Use it
 
-        Filter ccdFilter;
+        IFilter ccdFilter;
         byte[] cdtext;
         StreamReader cueStream;
-        Filter dataFilter;
+        IFilter dataFilter;
         Stream dataStream;
         byte[] fulltoc;
+        ImageInfo imageInfo;
         Dictionary offsetmap;
         List partitions;
         bool scrambled;
         List sessions;
-        Filter subFilter;
+        IFilter subFilter;
         Stream subStream;
         List tracks;
 
         public CloneCd()
         {
-            Name = "CloneCD";
-            PluginUuid = new Guid("EE9C2975-2E79-427A-8EE9-F86F19165784");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -117,15 +116,20 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "CloneCD";
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Partitions => partitions;
+        public virtual string Name => "CloneCD";
+        public virtual Guid Id => new Guid("EE9C2975-2E79-427A-8EE9-F86F19165784");
 
-        public override List Tracks => tracks;
+        public virtual string ImageFormat => "CloneCD";
 
-        public override List Sessions => sessions;
+        public virtual List Partitions => partitions;
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual List Tracks => tracks;
+
+        public virtual List Sessions => sessions;
+
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             ccdFilter = imageFilter;
 
@@ -172,7 +176,7 @@ namespace DiscImageChef.DiscImages
             }
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             if(imageFilter == null) return false;
 
@@ -281,11 +285,11 @@ namespace DiscImageChef.DiscImages
 
                             DicConsole.DebugWriteLine("CloneCD plugin", "Found Version at line {0}", lineNumber);
 
-                            ImageInfo.Version = ccdVerMatch.Groups["value"].Value;
-                            if(ImageInfo.Version != "2" && ImageInfo.Version != "3")
+                            imageInfo.Version = ccdVerMatch.Groups["value"].Value;
+                            if(imageInfo.Version != "2" && imageInfo.Version != "3")
                                 DicConsole
                                     .ErrorWriteLine("(CloneCD plugin): Warning! Unknown CCD image version {0}, may not work!",
-                                                    ImageInfo.Version);
+                                                    imageInfo.Version);
                         }
                         else if(inDisk)
                         {
@@ -462,7 +466,7 @@ namespace DiscImageChef.DiscImages
                 }
 
                 fulltoc = tocMs.ToArray();
-                ImageInfo.ReadableMediaTags.Add(MediaTagType.CD_FullTOC);
+                imageInfo.ReadableMediaTags.Add(MediaTagType.CD_FullTOC);
 
                 DicConsole.DebugWriteLine("CloneCD plugin", "{0}", FullTOC.Prettify(toc));
 
@@ -571,23 +575,23 @@ namespace DiscImageChef.DiscImages
                                                 {
                                                     currentTrack.TrackBytesPerSector = 2048;
                                                     currentTrack.TrackType = TrackType.CdMode1;
-                                                    if(!ImageInfo.ReadableSectorTags
+                                                    if(!imageInfo.ReadableSectorTags
                                                                  .Contains(SectorTagType.CdSectorSync))
-                                                        ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync);
-                                                    if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType
+                                                        imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync);
+                                                    if(!imageInfo.ReadableSectorTags.Contains(SectorTagType
                                                                                                   .CdSectorHeader))
-                                                        ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader);
-                                                    if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEcc)
-                                                    ) ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc);
-                                                    if(!ImageInfo.ReadableSectorTags
+                                                        imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader);
+                                                    if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEcc)
+                                                    ) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc);
+                                                    if(!imageInfo.ReadableSectorTags
                                                                  .Contains(SectorTagType.CdSectorEccP))
-                                                        ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP);
-                                                    if(!ImageInfo.ReadableSectorTags
+                                                        imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP);
+                                                    if(!imageInfo.ReadableSectorTags
                                                                  .Contains(SectorTagType.CdSectorEccQ))
-                                                        ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ);
-                                                    if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)
-                                                    ) ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc);
-                                                    if(ImageInfo.SectorSize < 2048) ImageInfo.SectorSize = 2048;
+                                                        imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ);
+                                                    if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)
+                                                    ) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc);
+                                                    if(imageInfo.SectorSize < 2048) imageInfo.SectorSize = 2048;
                                                 }
                                                 else if(sectTest[15] == 2)
                                                 {
@@ -603,84 +607,84 @@ namespace DiscImageChef.DiscImages
                                                         {
                                                             currentTrack.TrackBytesPerSector = 2324;
                                                             currentTrack.TrackType = TrackType.CdMode2Form2;
-                                                            if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType
+                                                            if(!imageInfo.ReadableSectorTags.Contains(SectorTagType
                                                                                                           .CdSectorSync)
                                                             )
-                                                                ImageInfo.ReadableSectorTags.Add(SectorTagType
+                                                                imageInfo.ReadableSectorTags.Add(SectorTagType
                                                                                                      .CdSectorSync);
-                                                            if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType
+                                                            if(!imageInfo.ReadableSectorTags.Contains(SectorTagType
                                                                                                           .CdSectorHeader)
                                                             )
-                                                                ImageInfo.ReadableSectorTags.Add(SectorTagType
+                                                                imageInfo.ReadableSectorTags.Add(SectorTagType
                                                                                                      .CdSectorHeader);
-                                                            if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType
+                                                            if(!imageInfo.ReadableSectorTags.Contains(SectorTagType
                                                                                                           .CdSectorSubHeader)
                                                             )
-                                                                ImageInfo.ReadableSectorTags.Add(SectorTagType
+                                                                imageInfo.ReadableSectorTags.Add(SectorTagType
                                                                                                      .CdSectorSubHeader);
-                                                            if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType
+                                                            if(!imageInfo.ReadableSectorTags.Contains(SectorTagType
                                                                                                           .CdSectorEdc))
-                                                                ImageInfo.ReadableSectorTags.Add(SectorTagType
+                                                                imageInfo.ReadableSectorTags.Add(SectorTagType
                                                                                                      .CdSectorEdc);
-                                                            if(ImageInfo.SectorSize < 2324) ImageInfo.SectorSize = 2324;
+                                                            if(imageInfo.SectorSize < 2324) imageInfo.SectorSize = 2324;
                                                         }
                                                         else
                                                         {
                                                             currentTrack.TrackBytesPerSector = 2048;
                                                             currentTrack.TrackType = TrackType.CdMode2Form1;
-                                                            if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType
+                                                            if(!imageInfo.ReadableSectorTags.Contains(SectorTagType
                                                                                                           .CdSectorSync)
                                                             )
-                                                                ImageInfo.ReadableSectorTags.Add(SectorTagType
+                                                                imageInfo.ReadableSectorTags.Add(SectorTagType
                                                                                                      .CdSectorSync);
-                                                            if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType
+                                                            if(!imageInfo.ReadableSectorTags.Contains(SectorTagType
                                                                                                           .CdSectorHeader)
                                                             )
-                                                                ImageInfo.ReadableSectorTags.Add(SectorTagType
+                                                                imageInfo.ReadableSectorTags.Add(SectorTagType
                                                                                                      .CdSectorHeader);
-                                                            if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType
+                                                            if(!imageInfo.ReadableSectorTags.Contains(SectorTagType
                                                                                                           .CdSectorSubHeader)
                                                             )
-                                                                ImageInfo.ReadableSectorTags.Add(SectorTagType
+                                                                imageInfo.ReadableSectorTags.Add(SectorTagType
                                                                                                      .CdSectorSubHeader);
-                                                            if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType
+                                                            if(!imageInfo.ReadableSectorTags.Contains(SectorTagType
                                                                                                           .CdSectorEcc))
-                                                                ImageInfo.ReadableSectorTags.Add(SectorTagType
+                                                                imageInfo.ReadableSectorTags.Add(SectorTagType
                                                                                                      .CdSectorEcc);
-                                                            if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType
+                                                            if(!imageInfo.ReadableSectorTags.Contains(SectorTagType
                                                                                                           .CdSectorEccP)
                                                             )
-                                                                ImageInfo.ReadableSectorTags.Add(SectorTagType
+                                                                imageInfo.ReadableSectorTags.Add(SectorTagType
                                                                                                      .CdSectorEccP);
-                                                            if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType
+                                                            if(!imageInfo.ReadableSectorTags.Contains(SectorTagType
                                                                                                           .CdSectorEccQ)
                                                             )
-                                                                ImageInfo.ReadableSectorTags.Add(SectorTagType
+                                                                imageInfo.ReadableSectorTags.Add(SectorTagType
                                                                                                      .CdSectorEccQ);
-                                                            if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType
+                                                            if(!imageInfo.ReadableSectorTags.Contains(SectorTagType
                                                                                                           .CdSectorEdc))
-                                                                ImageInfo.ReadableSectorTags.Add(SectorTagType
+                                                                imageInfo.ReadableSectorTags.Add(SectorTagType
                                                                                                      .CdSectorEdc);
-                                                            if(ImageInfo.SectorSize < 2048) ImageInfo.SectorSize = 2048;
+                                                            if(imageInfo.SectorSize < 2048) imageInfo.SectorSize = 2048;
                                                         }
                                                     else
                                                     {
                                                         currentTrack.TrackBytesPerSector = 2336;
                                                         currentTrack.TrackType = TrackType.CdMode2Formless;
-                                                        if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType
+                                                        if(!imageInfo.ReadableSectorTags.Contains(SectorTagType
                                                                                                       .CdSectorSync))
-                                                            ImageInfo.ReadableSectorTags
+                                                            imageInfo.ReadableSectorTags
                                                                      .Add(SectorTagType.CdSectorSync);
-                                                        if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType
+                                                        if(!imageInfo.ReadableSectorTags.Contains(SectorTagType
                                                                                                       .CdSectorHeader))
-                                                            ImageInfo.ReadableSectorTags.Add(SectorTagType
+                                                            imageInfo.ReadableSectorTags.Add(SectorTagType
                                                                                                  .CdSectorHeader);
-                                                        if(ImageInfo.SectorSize < 2336) ImageInfo.SectorSize = 2336;
+                                                        if(imageInfo.SectorSize < 2336) imageInfo.SectorSize = 2336;
                                                     }
                                                 }
                                             }
                                         }
-                                        else { if(ImageInfo.SectorSize < 2352) ImageInfo.SectorSize = 2352; }
+                                        else { if(imageInfo.SectorSize < 2352) imageInfo.SectorSize = 2352; }
                                     }
                                     break;
                             }
@@ -695,11 +699,11 @@ namespace DiscImageChef.DiscImages
                                         int type = descriptor.PFRAME % 10;
                                         int frm = descriptor.PFRAME - type;
 
-                                        ImageInfo.MediaManufacturer = ATIP.ManufacturerFromATIP(descriptor.PSEC, frm);
+                                        imageInfo.MediaManufacturer = ATIP.ManufacturerFromATIP(descriptor.PSEC, frm);
 
-                                        if(ImageInfo.MediaManufacturer != "")
+                                        if(imageInfo.MediaManufacturer != "")
                                             DicConsole.DebugWriteLine("CloneCD plugin", "Disc manufactured by: {0}",
-                                                                      ImageInfo.MediaManufacturer);
+                                                                      imageInfo.MediaManufacturer);
                                     }
                                     break;
                             }
@@ -709,7 +713,7 @@ namespace DiscImageChef.DiscImages
                         {
                             uint id = (uint)((descriptor.Min << 16) + (descriptor.Sec << 8) + descriptor.Frame);
                             DicConsole.DebugWriteLine("CloneCD plugin", "Disc ID: {0:X6}", id & 0x00FFFFFF);
-                            ImageInfo.MediaSerialNumber = $"{id & 0x00FFFFFF:X6}";
+                            imageInfo.MediaSerialNumber = $"{id & 0x00FFFFFF:X6}";
                             break;
                         }
                     }
@@ -721,8 +725,8 @@ namespace DiscImageChef.DiscImages
                     tracks.Add(currentTrack);
                 }
 
-                if(subFilter != null && !ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubchannel))
-                    ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubchannel);
+                if(subFilter != null && !imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubchannel))
+                    imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubchannel);
 
                 sessions = new List();
                 Session currentSession = new Session
@@ -772,7 +776,7 @@ namespace DiscImageChef.DiscImages
                         Start = track.TrackStartSector,
                         Type = track.TrackType.ToString()
                     };
-                    ImageInfo.Sectors += partition.Length;
+                    imageInfo.Sectors += partition.Length;
                     partitions.Add(partition);
                     offsetmap.Add(track.TrackSequence, track.TrackStartSector);
                 }
@@ -810,17 +814,17 @@ namespace DiscImageChef.DiscImages
                 // TODO: Check format
                 cdtext = cdtMs.ToArray();
 
-                if(!data && !firstdata) ImageInfo.MediaType = MediaType.CDDA;
-                else if(firstaudio && data && sessions.Count > 1 && mode2) ImageInfo.MediaType = MediaType.CDPLUS;
-                else if(firstdata && audio || mode2) ImageInfo.MediaType = MediaType.CDROMXA;
-                else if(!audio) ImageInfo.MediaType = MediaType.CDROM;
-                else ImageInfo.MediaType = MediaType.CD;
+                if(!data && !firstdata) imageInfo.MediaType = MediaType.CDDA;
+                else if(firstaudio && data && sessions.Count > 1 && mode2) imageInfo.MediaType = MediaType.CDPLUS;
+                else if(firstdata && audio || mode2) imageInfo.MediaType = MediaType.CDROMXA;
+                else if(!audio) imageInfo.MediaType = MediaType.CDROM;
+                else imageInfo.MediaType = MediaType.CD;
 
-                ImageInfo.Application = "CloneCD";
-                ImageInfo.ImageSize = (ulong)imageFilter.GetDataForkLength();
-                ImageInfo.CreationTime = imageFilter.GetCreationTime();
-                ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
-                ImageInfo.XmlMediaType = XmlMediaType.OpticalDisc;
+                imageInfo.Application = "CloneCD";
+                imageInfo.ImageSize = (ulong)imageFilter.GetDataForkLength();
+                imageInfo.CreationTime = imageFilter.GetCreationTime();
+                imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+                imageInfo.XmlMediaType = XmlMediaType.OpticalDisc;
 
                 return true;
             }
@@ -838,7 +842,7 @@ namespace DiscImageChef.DiscImages
             return (ulong)(hour * 60 * 60 * 75 + minute * 60 * 75 + second * 75 + frame - 150);
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             switch(tag)
             {
@@ -857,27 +861,27 @@ namespace DiscImageChef.DiscImages
             }
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
             return ReadSectors(sectorAddress, 1);
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             return ReadSectorsTag(sectorAddress, 1, tag);
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             return ReadSectors(sectorAddress, 1, track);
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             return ReadSectorsTag(sectorAddress, 1, track, tag);
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
             foreach(KeyValuePair kvp in from kvp in offsetmap
                                                      where sectorAddress >= kvp.Value
@@ -890,7 +894,7 @@ namespace DiscImageChef.DiscImages
             throw new ArgumentOutOfRangeException(nameof(sectorAddress), $"Sector address {sectorAddress} not found");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             foreach(KeyValuePair kvp in from kvp in offsetmap
                                                      where sectorAddress >= kvp.Value
@@ -903,7 +907,7 @@ namespace DiscImageChef.DiscImages
             throw new ArgumentOutOfRangeException(nameof(sectorAddress), $"Sector address {sectorAddress} not found");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             Track dicTrack = new Track {TrackSequence = 0};
 
@@ -985,7 +989,7 @@ namespace DiscImageChef.DiscImages
         }
 
         // TODO: Flags
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             Track dicTrack = new Track {TrackSequence = 0};
 
@@ -1225,17 +1229,17 @@ namespace DiscImageChef.DiscImages
             return buffer;
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             return ReadSectorsLong(sectorAddress, 1);
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             return ReadSectorsLong(sectorAddress, 1, track);
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             foreach(KeyValuePair kvp in from kvp in offsetmap
                                                      where sectorAddress >= kvp.Value
@@ -1249,7 +1253,7 @@ namespace DiscImageChef.DiscImages
             throw new ArgumentOutOfRangeException(nameof(sectorAddress), $"Sector address {sectorAddress} not found");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             Track dicTrack = new Track {TrackSequence = 0};
 
@@ -1274,31 +1278,31 @@ namespace DiscImageChef.DiscImages
             return buffer;
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             if(sessions.Contains(session)) return GetSessionTracks(session.SessionSequence);
 
             throw new ImageNotSupportedException("Session does not exist in disc image");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             return tracks.Where(track => track.TrackSession == session).ToList();
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             byte[] buffer = ReadSectorLong(sectorAddress);
             return CdChecksums.CheckCdSector(buffer);
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             byte[] buffer = ReadSectorLong(sectorAddress, track);
             return CdChecksums.CheckCdSector(buffer);
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             byte[] buffer = ReadSectorsLong(sectorAddress, length);
@@ -1328,7 +1332,7 @@ namespace DiscImageChef.DiscImages
             return failingLbas.Count <= 0;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             byte[] buffer = ReadSectorsLong(sectorAddress, length, track);
@@ -1358,7 +1362,7 @@ namespace DiscImageChef.DiscImages
             return failingLbas.Count <= 0;
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return null;
         }
diff --git a/DiscImageChef.DiscImages/CopyQM.cs b/DiscImageChef.DiscImages/CopyQM.cs
index e072e5c3..38704733 100644
--- a/DiscImageChef.DiscImages/CopyQM.cs
+++ b/DiscImageChef.DiscImages/CopyQM.cs
@@ -40,7 +40,7 @@ using DiscImageChef.Filters;
 
 namespace DiscImageChef.DiscImages
 {
-    public class CopyQm : ImagePlugin
+    public class CopyQm : IMediaImage
     {
         const ushort COPYQM_MAGIC = 0x5143;
         const byte COPYQM_MARK = 0x14;
@@ -94,12 +94,11 @@ namespace DiscImageChef.DiscImages
         CopyQmHeader header;
 
         bool headerChecksumOk;
+        ImageInfo imageInfo;
 
         public CopyQm()
         {
-            Name = "Sydex CopyQM";
-            PluginUuid = new Guid("147E927D-3A92-4E0C-82CD-142F5A4FA76D");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -124,18 +123,23 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "Sydex CopyQM";
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Partitions =>
+        public virtual string Name => "Sydex CopyQM";
+        public virtual Guid Id => new Guid("147E927D-3A92-4E0C-82CD-142F5A4FA76D");
+
+        public virtual string ImageFormat => "Sydex CopyQM";
+
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Sessions =>
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -149,7 +153,7 @@ namespace DiscImageChef.DiscImages
             return magic == COPYQM_MAGIC && hdr[0x02] == COPYQM_MARK && 133 + hdr[0x6F] < stream.Length;
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -195,7 +199,7 @@ namespace DiscImageChef.DiscImages
 
             byte[] cmt = new byte[header.commentLength];
             stream.Read(cmt, 0, header.commentLength);
-            ImageInfo.Comments = StringHandlers.CToString(cmt);
+            imageInfo.Comments = StringHandlers.CToString(cmt);
             decodedImage = new MemoryStream();
 
             calculatedDataCrc = 0;
@@ -259,115 +263,115 @@ namespace DiscImageChef.DiscImages
             DicConsole.DebugWriteLine("CopyQM plugin", "Calculated data CRC = 0x{0:X8}, {1}", calculatedDataCrc,
                                       calculatedDataCrc == header.crc);
 
-            ImageInfo.Application = "CopyQM";
-            ImageInfo.CreationTime = DateHandlers.DosToDateTime(header.date, header.time);
-            ImageInfo.LastModificationTime = ImageInfo.CreationTime;
-            ImageInfo.MediaTitle = header.volumeLabel;
-            ImageInfo.ImageSize = (ulong)(stream.Length - 133 - header.commentLength);
-            ImageInfo.Sectors = (ulong)sectors;
-            ImageInfo.SectorSize = header.sectorSize;
+            imageInfo.Application = "CopyQM";
+            imageInfo.CreationTime = DateHandlers.DosToDateTime(header.date, header.time);
+            imageInfo.LastModificationTime = imageInfo.CreationTime;
+            imageInfo.MediaTitle = header.volumeLabel;
+            imageInfo.ImageSize = (ulong)(stream.Length - 133 - header.commentLength);
+            imageInfo.Sectors = (ulong)sectors;
+            imageInfo.SectorSize = header.sectorSize;
 
             switch(header.drive)
             {
                 case COPYQM_525_HD:
                     if(header.heads == 2 && header.totalCylinders == 80 && header.sectorsPerTrack == 15 &&
-                       header.sectorSize == 512) ImageInfo.MediaType = MediaType.DOS_525_HD;
+                       header.sectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_HD;
                     else if(header.heads == 2 && header.totalCylinders == 80 && header.sectorsPerTrack == 16 &&
-                            header.sectorSize == 256) ImageInfo.MediaType = MediaType.ACORN_525_DS_DD;
+                            header.sectorSize == 256) imageInfo.MediaType = MediaType.ACORN_525_DS_DD;
                     else if(header.heads == 1 && header.totalCylinders == 80 && header.sectorsPerTrack == 16 &&
-                            header.sectorSize == 256) ImageInfo.MediaType = MediaType.ACORN_525_SS_DD_80;
+                            header.sectorSize == 256) imageInfo.MediaType = MediaType.ACORN_525_SS_DD_80;
                     else if(header.heads == 1 && header.totalCylinders == 80 && header.sectorsPerTrack == 10 &&
-                            header.sectorSize == 256) ImageInfo.MediaType = MediaType.ACORN_525_SS_SD_80;
+                            header.sectorSize == 256) imageInfo.MediaType = MediaType.ACORN_525_SS_SD_80;
                     else if(header.heads == 2 && header.totalCylinders == 80 && header.sectorsPerTrack == 8 &&
-                            header.sectorSize == 1024) ImageInfo.MediaType = MediaType.NEC_525_HD;
+                            header.sectorSize == 1024) imageInfo.MediaType = MediaType.NEC_525_HD;
                     else if(header.heads == 2 && header.totalCylinders == 77 && header.sectorsPerTrack == 8 &&
-                            header.sectorSize == 1024) ImageInfo.MediaType = MediaType.SHARP_525;
+                            header.sectorSize == 1024) imageInfo.MediaType = MediaType.SHARP_525;
                     else goto case COPYQM_525_DD;
                     break;
                 case COPYQM_525_DD:
                     if(header.heads == 1 && header.totalCylinders == 40 && header.sectorsPerTrack == 8 &&
-                       header.sectorSize == 512) ImageInfo.MediaType = MediaType.DOS_525_SS_DD_8;
+                       header.sectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_SS_DD_8;
                     else if(header.heads == 1 && header.totalCylinders == 40 && header.sectorsPerTrack == 9 &&
-                            header.sectorSize == 512) ImageInfo.MediaType = MediaType.DOS_525_SS_DD_9;
+                            header.sectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_SS_DD_9;
                     else if(header.heads == 2 && header.totalCylinders == 40 && header.sectorsPerTrack == 8 &&
-                            header.sectorSize == 512) ImageInfo.MediaType = MediaType.DOS_525_DS_DD_8;
+                            header.sectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_DS_DD_8;
                     else if(header.heads == 2 && header.totalCylinders == 40 && header.sectorsPerTrack == 9 &&
-                            header.sectorSize == 512) ImageInfo.MediaType = MediaType.DOS_525_DS_DD_9;
+                            header.sectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_DS_DD_9;
                     else if(header.heads == 1 && header.totalCylinders == 40 && header.sectorsPerTrack == 18 &&
-                            header.sectorSize == 128) ImageInfo.MediaType = MediaType.ATARI_525_SD;
+                            header.sectorSize == 128) imageInfo.MediaType = MediaType.ATARI_525_SD;
                     else if(header.heads == 1 && header.totalCylinders == 40 && header.sectorsPerTrack == 26 &&
-                            header.sectorSize == 128) ImageInfo.MediaType = MediaType.ATARI_525_ED;
+                            header.sectorSize == 128) imageInfo.MediaType = MediaType.ATARI_525_ED;
                     else if(header.heads == 1 && header.totalCylinders == 40 && header.sectorsPerTrack == 18 &&
-                            header.sectorSize == 256) ImageInfo.MediaType = MediaType.ATARI_525_DD;
-                    else ImageInfo.MediaType = MediaType.Unknown;
+                            header.sectorSize == 256) imageInfo.MediaType = MediaType.ATARI_525_DD;
+                    else imageInfo.MediaType = MediaType.Unknown;
                     break;
                 case COPYQM_35_ED:
                     if(header.heads == 2 && header.totalCylinders == 80 && header.sectorsPerTrack == 36 &&
-                       header.sectorSize == 512) ImageInfo.MediaType = MediaType.DOS_35_ED;
+                       header.sectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_ED;
                     else goto case COPYQM_35_HD;
                     break;
                 case COPYQM_35_HD:
                     if(header.heads == 2 && header.totalCylinders == 80 && header.sectorsPerTrack == 18 &&
-                       header.sectorSize == 512) ImageInfo.MediaType = MediaType.DOS_35_HD;
+                       header.sectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_HD;
                     else if(header.heads == 2 && header.totalCylinders == 80 && header.sectorsPerTrack == 21 &&
-                            header.sectorSize == 512) ImageInfo.MediaType = MediaType.DMF;
+                            header.sectorSize == 512) imageInfo.MediaType = MediaType.DMF;
                     else if(header.heads == 2 && header.totalCylinders == 82 && header.sectorsPerTrack == 21 &&
-                            header.sectorSize == 512) ImageInfo.MediaType = MediaType.DMF_82;
+                            header.sectorSize == 512) imageInfo.MediaType = MediaType.DMF_82;
                     else if(header.heads == 2 && header.totalCylinders == 80 && header.sectorsPerTrack == 8 &&
-                            header.sectorSize == 1024) ImageInfo.MediaType = MediaType.NEC_35_HD_8;
+                            header.sectorSize == 1024) imageInfo.MediaType = MediaType.NEC_35_HD_8;
                     else if(header.heads == 2 && header.totalCylinders == 80 && header.sectorsPerTrack == 15 &&
-                            header.sectorSize == 512) ImageInfo.MediaType = MediaType.NEC_35_HD_15;
+                            header.sectorSize == 512) imageInfo.MediaType = MediaType.NEC_35_HD_15;
                     else goto case COPYQM_35_DD;
                     break;
                 case COPYQM_35_DD:
                     if(header.heads == 2 && header.totalCylinders == 80 && header.sectorsPerTrack == 9 &&
-                       header.sectorSize == 512) ImageInfo.MediaType = MediaType.DOS_35_DS_DD_9;
+                       header.sectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_DS_DD_9;
                     else if(header.heads == 2 && header.totalCylinders == 80 && header.sectorsPerTrack == 8 &&
-                            header.sectorSize == 512) ImageInfo.MediaType = MediaType.DOS_35_DS_DD_8;
+                            header.sectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_DS_DD_8;
                     else if(header.heads == 1 && header.totalCylinders == 80 && header.sectorsPerTrack == 9 &&
-                            header.sectorSize == 512) ImageInfo.MediaType = MediaType.DOS_35_SS_DD_9;
+                            header.sectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_SS_DD_9;
                     else if(header.heads == 1 && header.totalCylinders == 80 && header.sectorsPerTrack == 8 &&
-                            header.sectorSize == 512) ImageInfo.MediaType = MediaType.DOS_35_SS_DD_8;
+                            header.sectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_SS_DD_8;
                     else if(header.heads == 2 && header.totalCylinders == 80 && header.sectorsPerTrack == 5 &&
-                            header.sectorSize == 1024) ImageInfo.MediaType = MediaType.ACORN_35_DS_DD;
+                            header.sectorSize == 1024) imageInfo.MediaType = MediaType.ACORN_35_DS_DD;
                     else if(header.heads == 2 && header.totalCylinders == 77 && header.sectorsPerTrack == 8 &&
-                            header.sectorSize == 1024) ImageInfo.MediaType = MediaType.SHARP_35;
+                            header.sectorSize == 1024) imageInfo.MediaType = MediaType.SHARP_35;
                     else if(header.heads == 1 && header.totalCylinders == 70 && header.sectorsPerTrack == 9 &&
-                            header.sectorSize == 512) ImageInfo.MediaType = MediaType.Apricot_35;
-                    else ImageInfo.MediaType = MediaType.Unknown;
+                            header.sectorSize == 512) imageInfo.MediaType = MediaType.Apricot_35;
+                    else imageInfo.MediaType = MediaType.Unknown;
                     break;
                 default:
-                    ImageInfo.MediaType = MediaType.Unknown;
+                    imageInfo.MediaType = MediaType.Unknown;
                     break;
             }
 
-            ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
             decodedDisk = decodedImage.ToArray();
 
             decodedImage.Close();
 
-            DicConsole.VerboseWriteLine("CopyQM image contains a disk of type {0}", ImageInfo.MediaType);
-            if(!string.IsNullOrEmpty(ImageInfo.Comments))
-                DicConsole.VerboseWriteLine("CopyQM comments: {0}", ImageInfo.Comments);
+            DicConsole.VerboseWriteLine("CopyQM image contains a disk of type {0}", imageInfo.MediaType);
+            if(!string.IsNullOrEmpty(imageInfo.Comments))
+                DicConsole.VerboseWriteLine("CopyQM comments: {0}", imageInfo.Comments);
 
-            ImageInfo.Heads = header.heads;
-            ImageInfo.Cylinders = header.imageCylinders;
-            ImageInfo.SectorsPerTrack = header.sectorsPerTrack;
+            imageInfo.Heads = header.heads;
+            imageInfo.Cylinders = header.imageCylinders;
+            imageInfo.SectorsPerTrack = header.sectorsPerTrack;
 
             return true;
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             return null;
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
@@ -378,7 +382,7 @@ namespace DiscImageChef.DiscImages
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
@@ -389,93 +393,93 @@ namespace DiscImageChef.DiscImages
             return null;
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return calculatedDataCrc == header.crc && headerChecksumOk;
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
             return ReadSectors(sectorAddress, 1);
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
-            byte[] buffer = new byte[length * ImageInfo.SectorSize];
+            byte[] buffer = new byte[length * imageInfo.SectorSize];
 
-            Array.Copy(decodedDisk, (int)sectorAddress * ImageInfo.SectorSize, buffer, 0,
-                       length * ImageInfo.SectorSize);
+            Array.Copy(decodedDisk, (int)sectorAddress * imageInfo.SectorSize, buffer, 0,
+                       length * imageInfo.SectorSize);
 
             return buffer;
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
diff --git a/DiscImageChef.DiscImages/D88.cs b/DiscImageChef.DiscImages/D88.cs
index 113ea9b4..5ce6fba4 100644
--- a/DiscImageChef.DiscImages/D88.cs
+++ b/DiscImageChef.DiscImages/D88.cs
@@ -45,19 +45,18 @@ namespace DiscImageChef.DiscImages
 {
     // Information from Quasi88's FORMAT.TXT file
     // Japanese comments copied from there
-    public class D88 : ImagePlugin
+    public class D88 : IMediaImage
     {
         const byte READ_ONLY = 0x10;
 
         readonly byte[] reservedEmpty = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+        ImageInfo imageInfo;
 
         List sectorsData;
 
         public D88()
         {
-            Name = "D88 Disk Image";
-            PluginUuid = new Guid("669EDC77-EC41-4720-A88C-49C38CFFBAA0");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -82,18 +81,22 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "D88 disk image";
+        public virtual string Name => "D88 Disk Image";
+        public virtual Guid Id => new Guid("669EDC77-EC41-4720-A88C-49C38CFFBAA0");
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Partitions =>
+        public virtual string ImageFormat => "D88 disk image";
+
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Sessions =>
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -140,7 +143,7 @@ namespace DiscImageChef.DiscImages
             return counter > 0;
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -265,25 +268,25 @@ namespace DiscImageChef.DiscImages
             debugStream.Close();
             */
 
-            ImageInfo.MediaType = MediaType.Unknown;
+            imageInfo.MediaType = MediaType.Unknown;
             if(allEqual)
                 if(trkCounter == 154 && spt == 26 && bps == IBMSectorSizeCode.EighthKilo)
-                    ImageInfo.MediaType = MediaType.NEC_8_SD;
+                    imageInfo.MediaType = MediaType.NEC_8_SD;
                 else if(bps == IBMSectorSizeCode.QuarterKilo)
                     switch(trkCounter)
                     {
                         case 80 when spt == 16:
-                            ImageInfo.MediaType = MediaType.NEC_525_SS;
+                            imageInfo.MediaType = MediaType.NEC_525_SS;
                             break;
                         case 154 when spt == 26:
-                            ImageInfo.MediaType = MediaType.NEC_8_DD;
+                            imageInfo.MediaType = MediaType.NEC_8_DD;
                             break;
                         case 160 when spt == 16:
-                            ImageInfo.MediaType = MediaType.NEC_525_DS;
+                            imageInfo.MediaType = MediaType.NEC_525_DS;
                             break;
                     }
                 else if(trkCounter == 154 && spt == 8 && bps == IBMSectorSizeCode.Kilo)
-                    ImageInfo.MediaType = MediaType.NEC_525_HD;
+                    imageInfo.MediaType = MediaType.NEC_525_HD;
                 else if(bps == IBMSectorSizeCode.HalfKilo)
                     switch(d88Hdr.track_table.Length)
                     {
@@ -292,10 +295,10 @@ namespace DiscImageChef.DiscImages
                             switch(spt)
                             {
                                 case 8:
-                                    ImageInfo.MediaType = MediaType.DOS_525_SS_DD_8;
+                                    imageInfo.MediaType = MediaType.DOS_525_SS_DD_8;
                                     break;
                                 case 9:
-                                    ImageInfo.MediaType = MediaType.DOS_525_SS_DD_9;
+                                    imageInfo.MediaType = MediaType.DOS_525_SS_DD_9;
                                     break;
                             }
                         }
@@ -306,10 +309,10 @@ namespace DiscImageChef.DiscImages
                             switch(spt)
                             {
                                 case 8:
-                                    ImageInfo.MediaType = MediaType.DOS_525_DS_DD_8;
+                                    imageInfo.MediaType = MediaType.DOS_525_DS_DD_8;
                                     break;
                                 case 9:
-                                    ImageInfo.MediaType = MediaType.DOS_525_DS_DD_9;
+                                    imageInfo.MediaType = MediaType.DOS_525_DS_DD_9;
                                     break;
                             }
                         }
@@ -320,121 +323,121 @@ namespace DiscImageChef.DiscImages
                             switch(spt)
                             {
                                 case 15:
-                                    ImageInfo.MediaType = MediaType.NEC_35_HD_15;
+                                    imageInfo.MediaType = MediaType.NEC_35_HD_15;
                                     break;
                                 case 9:
-                                    ImageInfo.MediaType = MediaType.DOS_35_DS_DD_9;
+                                    imageInfo.MediaType = MediaType.DOS_35_DS_DD_9;
                                     break;
                                 case 18:
-                                    ImageInfo.MediaType = MediaType.DOS_35_HD;
+                                    imageInfo.MediaType = MediaType.DOS_35_HD;
                                     break;
                                 case 36:
-                                    ImageInfo.MediaType = MediaType.DOS_35_ED;
+                                    imageInfo.MediaType = MediaType.DOS_35_ED;
                                     break;
                             }
                         }
 
                             break;
                         case 480:
-                            if(spt == 38) ImageInfo.MediaType = MediaType.NEC_35_TD;
+                            if(spt == 38) imageInfo.MediaType = MediaType.NEC_35_TD;
                             break;
                     }
 
-            DicConsole.DebugWriteLine("D88 plugin", "MediaType: {0}", ImageInfo.MediaType);
+            DicConsole.DebugWriteLine("D88 plugin", "MediaType: {0}", imageInfo.MediaType);
 
-            ImageInfo.ImageSize = (ulong)d88Hdr.disk_size;
-            ImageInfo.CreationTime = imageFilter.GetCreationTime();
-            ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
-            ImageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
-            ImageInfo.Sectors = (ulong)sectorsData.Count;
-            ImageInfo.Comments = StringHandlers.CToString(d88Hdr.name, shiftjis);
-            ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
-            ImageInfo.SectorSize = (uint)(128 << (int)bps);
+            imageInfo.ImageSize = (ulong)d88Hdr.disk_size;
+            imageInfo.CreationTime = imageFilter.GetCreationTime();
+            imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+            imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
+            imageInfo.Sectors = (ulong)sectorsData.Count;
+            imageInfo.Comments = StringHandlers.CToString(d88Hdr.name, shiftjis);
+            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+            imageInfo.SectorSize = (uint)(128 << (int)bps);
 
-            switch(ImageInfo.MediaType)
+            switch(imageInfo.MediaType)
             {
                 case MediaType.NEC_525_SS:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 1;
-                    ImageInfo.SectorsPerTrack = 16;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 1;
+                    imageInfo.SectorsPerTrack = 16;
                     break;
                 case MediaType.NEC_8_SD:
                 case MediaType.NEC_8_DD:
-                    ImageInfo.Cylinders = 77;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 26;
+                    imageInfo.Cylinders = 77;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 26;
                     break;
                 case MediaType.NEC_525_DS:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 16;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 16;
                     break;
                 case MediaType.NEC_525_HD:
-                    ImageInfo.Cylinders = 77;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 8;
+                    imageInfo.Cylinders = 77;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 8;
                     break;
                 case MediaType.DOS_525_SS_DD_8:
-                    ImageInfo.Cylinders = 40;
-                    ImageInfo.Heads = 1;
-                    ImageInfo.SectorsPerTrack = 8;
+                    imageInfo.Cylinders = 40;
+                    imageInfo.Heads = 1;
+                    imageInfo.SectorsPerTrack = 8;
                     break;
                 case MediaType.DOS_525_SS_DD_9:
-                    ImageInfo.Cylinders = 40;
-                    ImageInfo.Heads = 1;
-                    ImageInfo.SectorsPerTrack = 9;
+                    imageInfo.Cylinders = 40;
+                    imageInfo.Heads = 1;
+                    imageInfo.SectorsPerTrack = 9;
                     break;
                 case MediaType.DOS_525_DS_DD_8:
-                    ImageInfo.Cylinders = 40;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 8;
+                    imageInfo.Cylinders = 40;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 8;
                     break;
                 case MediaType.DOS_525_DS_DD_9:
-                    ImageInfo.Cylinders = 40;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 9;
+                    imageInfo.Cylinders = 40;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 9;
                     break;
                 case MediaType.NEC_35_HD_15:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 15;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 15;
                     break;
                 case MediaType.DOS_35_DS_DD_9:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 9;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 9;
                     break;
                 case MediaType.DOS_35_HD:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 18;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 18;
                     break;
                 case MediaType.DOS_35_ED:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 36;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 36;
                     break;
                 case MediaType.NEC_35_TD:
-                    ImageInfo.Cylinders = 240;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 38;
+                    imageInfo.Cylinders = 240;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 38;
                     break;
             }
 
             return true;
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
             return ReadSectors(sectorAddress, 1);
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
             MemoryStream buffer = new MemoryStream();
@@ -444,98 +447,98 @@ namespace DiscImageChef.DiscImages
             return buffer.ToArray();
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             return null;
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
             unknownLbas = new List();
-            for(ulong i = 0; i < ImageInfo.Sectors; i++) unknownLbas.Add(i);
+            for(ulong i = 0; i < imageInfo.Sectors; i++) unknownLbas.Add(i);
 
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return null;
         }
diff --git a/DiscImageChef.DiscImages/DART.cs b/DiscImageChef.DiscImages/DART.cs
index ebab2d9a..18708d13 100644
--- a/DiscImageChef.DiscImages/DART.cs
+++ b/DiscImageChef.DiscImages/DART.cs
@@ -44,7 +44,7 @@ using Version = Resources.Version;
 
 namespace DiscImageChef.DiscImages
 {
-    public class Dart : ImagePlugin
+    public class Dart : IMediaImage
     {
         // Disk types
         const byte DISK_MAC = 1;
@@ -85,14 +85,13 @@ namespace DiscImageChef.DiscImages
         // DART images are at most 1474560 bytes, so let's cache the whole
         byte[] dataCache;
         uint dataChecksum;
+        ImageInfo imageInfo;
         byte[] tagCache;
         uint tagChecksum;
 
         public Dart()
         {
-            Name = "Apple Disk Archival/Retrieval Tool";
-            PluginUuid = new Guid("B3E06BF8-F98D-4F9B-BBE2-342C373BAF3E");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -117,18 +116,22 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "Apple Disk Archival/Retrieval Tool";
+        public virtual string Name => "Apple Disk Archival/Retrieval Tool";
+        public virtual Guid Id => new Guid("B3E06BF8-F98D-4F9B-BBE2-342C373BAF3E");
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Partitions =>
+        public virtual string ImageFormat => "Apple Disk Archival/Retrieval Tool";
+
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Sessions =>
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
 
@@ -179,7 +182,7 @@ namespace DiscImageChef.DiscImages
             return stream.Length <= expectedMaxSize;
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
 
@@ -274,7 +277,7 @@ namespace DiscImageChef.DiscImages
             dataCache = dataMs.ToArray();
             if(header.srcType == DISK_LISA || header.srcType == DISK_MAC || header.srcType == DISK_APPLE2)
             {
-                ImageInfo.ReadableSectorTags.Add(SectorTagType.AppleSectorTag);
+                imageInfo.ReadableSectorTags.Add(SectorTagType.AppleSectorTag);
                 tagCache = tagMs.ToArray();
             }
 
@@ -318,9 +321,9 @@ namespace DiscImageChef.DiscImages
 
                             if(dev != null) pre = $"{version.PreReleaseVersion}";
 
-                            ImageInfo.ApplicationVersion = $"{major}{minor}{release}{dev}{pre}";
-                            ImageInfo.Application = version.VersionString;
-                            ImageInfo.Comments = version.VersionMessage;
+                            imageInfo.ApplicationVersion = $"{major}{minor}{release}{dev}{pre}";
+                            imageInfo.Application = version.VersionString;
+                            imageInfo.Comments = version.VersionMessage;
                         }
                     }
 
@@ -339,8 +342,8 @@ namespace DiscImageChef.DiscImages
 
                             if(dArtMatch.Success)
                             {
-                                ImageInfo.Application = "DART";
-                                ImageInfo.ApplicationVersion = dArtMatch.Groups["version"].Value;
+                                imageInfo.Application = "DART";
+                                imageInfo.ApplicationVersion = dArtMatch.Groups["version"].Value;
                                 dataChecksum = Convert.ToUInt32(dArtMatch.Groups["datachk"].Value, 16);
                                 tagChecksum = Convert.ToUInt32(dArtMatch.Groups["tagchk"].Value, 16);
                             }
@@ -366,75 +369,75 @@ namespace DiscImageChef.DiscImages
             }
             catch(InvalidCastException) { }
 
-            DicConsole.DebugWriteLine("DART plugin", "Image application = {0} version {1}", ImageInfo.Application,
-                                      ImageInfo.ApplicationVersion);
+            DicConsole.DebugWriteLine("DART plugin", "Image application = {0} version {1}", imageInfo.Application,
+                                      imageInfo.ApplicationVersion);
 
-            ImageInfo.Sectors = (ulong)(header.srcSize * 2);
-            ImageInfo.CreationTime = imageFilter.GetCreationTime();
-            ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
-            ImageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
-            ImageInfo.SectorSize = SECTOR_SIZE;
-            ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
-            ImageInfo.ImageSize = ImageInfo.Sectors * SECTOR_SIZE;
-            ImageInfo.Version = header.srcCmp == COMPRESS_NONE ? "1.4" : "1.5";
+            imageInfo.Sectors = (ulong)(header.srcSize * 2);
+            imageInfo.CreationTime = imageFilter.GetCreationTime();
+            imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+            imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
+            imageInfo.SectorSize = SECTOR_SIZE;
+            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+            imageInfo.ImageSize = imageInfo.Sectors * SECTOR_SIZE;
+            imageInfo.Version = header.srcCmp == COMPRESS_NONE ? "1.4" : "1.5";
 
             switch(header.srcSize)
             {
                 case SIZE_MAC_SS:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 1;
-                    ImageInfo.SectorsPerTrack = 10;
-                    ImageInfo.MediaType = MediaType.AppleSonySS;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 1;
+                    imageInfo.SectorsPerTrack = 10;
+                    imageInfo.MediaType = MediaType.AppleSonySS;
                     break;
                 case SIZE_MAC:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 10;
-                    ImageInfo.MediaType = MediaType.AppleSonyDS;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 10;
+                    imageInfo.MediaType = MediaType.AppleSonyDS;
                     break;
                 case SIZE_DOS:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 9;
-                    ImageInfo.MediaType = MediaType.DOS_35_DS_DD_9;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 9;
+                    imageInfo.MediaType = MediaType.DOS_35_DS_DD_9;
                     break;
                 case SIZE_MAC_HD:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 18;
-                    ImageInfo.MediaType = MediaType.DOS_35_HD;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 18;
+                    imageInfo.MediaType = MediaType.DOS_35_HD;
                     break;
             }
 
             return true;
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
             return ReadSectors(sectorAddress, 1);
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             return ReadSectorsTag(sectorAddress, 1, tag);
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
-            byte[] buffer = new byte[length * ImageInfo.SectorSize];
+            byte[] buffer = new byte[length * imageInfo.SectorSize];
 
-            Array.Copy(dataCache, (int)sectorAddress * ImageInfo.SectorSize, buffer, 0, length * ImageInfo.SectorSize);
+            Array.Copy(dataCache, (int)sectorAddress * imageInfo.SectorSize, buffer, 0, length * imageInfo.SectorSize);
 
             return buffer;
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             if(tag != SectorTagType.AppleSectorTag)
                 throw new FeatureUnsupportedImageException($"Tag {tag} not supported by image format");
@@ -442,10 +445,10 @@ namespace DiscImageChef.DiscImages
             if(tagCache == null || tagCache.Length == 0)
                 throw new FeatureNotPresentImageException("Disk image does not have tags");
 
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
             byte[] buffer = new byte[length * TAG_SECTOR_SIZE];
@@ -455,17 +458,17 @@ namespace DiscImageChef.DiscImages
             return buffer;
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             return ReadSectorsLong(sectorAddress, 1);
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
             byte[] data = ReadSectors(sectorAddress, length);
@@ -474,87 +477,87 @@ namespace DiscImageChef.DiscImages
 
             for(uint i = 0; i < length; i++)
             {
-                Array.Copy(data, i * ImageInfo.SectorSize, buffer, i * (ImageInfo.SectorSize + TAG_SECTOR_SIZE),
-                           ImageInfo.SectorSize);
+                Array.Copy(data, i * imageInfo.SectorSize, buffer, i * (imageInfo.SectorSize + TAG_SECTOR_SIZE),
+                           imageInfo.SectorSize);
                 Array.Copy(tags, i * TAG_SECTOR_SIZE, buffer,
-                           i * (ImageInfo.SectorSize + TAG_SECTOR_SIZE) + ImageInfo.SectorSize, TAG_SECTOR_SIZE);
+                           i * (imageInfo.SectorSize + TAG_SECTOR_SIZE) + imageInfo.SectorSize, TAG_SECTOR_SIZE);
             }
 
             return buffer;
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             return null;
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
             unknownLbas = new List();
-            for(ulong i = 0; i < ImageInfo.Sectors; i++) unknownLbas.Add(i);
+            for(ulong i = 0; i < imageInfo.Sectors; i++) unknownLbas.Add(i);
 
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return null;
         }
diff --git a/DiscImageChef.DiscImages/DIM.cs b/DiscImageChef.DiscImages/DIM.cs
index b971d179..591846fb 100644
--- a/DiscImageChef.DiscImages/DIM.cs
+++ b/DiscImageChef.DiscImages/DIM.cs
@@ -41,7 +41,7 @@ using DiscImageChef.Filters;
 
 namespace DiscImageChef.DiscImages
 {
-    public class Dim : ImagePlugin
+    public class Dim : IMediaImage
     {
         /// Start of data sectors in disk image, should be 0x100
         const uint DATA_OFFSET = 0x100;
@@ -49,15 +49,14 @@ namespace DiscImageChef.DiscImages
         readonly byte[] headerId = {0x44, 0x49, 0x46, 0x43, 0x20, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x20, 0x20};
         byte[] comment;
         /// Disk image file
-        Filter dimImageFilter;
+        IFilter dimImageFilter;
         DiskType dskType;
         byte[] hdrId;
+        ImageInfo imageInfo;
 
         public Dim()
         {
-            Name = "DIM Disk Image";
-            PluginUuid = new Guid("0240B7B1-E959-4CDC-B0BD-386D6E467B88");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -82,18 +81,22 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "DIM disk image";
+        public virtual string Name => "DIM Disk Image";
+        public virtual Guid Id => new Guid("0240B7B1-E959-4CDC-B0BD-386D6E467B88");
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Partitions =>
+        public virtual string ImageFormat => "DIM disk image";
+
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Sessions =>
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -112,7 +115,7 @@ namespace DiscImageChef.DiscImages
             return headerId.SequenceEqual(hdrId);
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -132,7 +135,7 @@ namespace DiscImageChef.DiscImages
 
             if(!headerId.SequenceEqual(hdrId)) return false;
 
-            ImageInfo.MediaType = MediaType.Unknown;
+            imageInfo.MediaType = MediaType.Unknown;
 
             switch(dskType)
             {
@@ -144,8 +147,8 @@ namespace DiscImageChef.DiscImages
                         return false;
                     }
 
-                    if(diskSize / (2 * 8 * 1024) == 77) ImageInfo.MediaType = MediaType.SHARP_525;
-                    ImageInfo.SectorSize = 1024;
+                    if(diskSize / (2 * 8 * 1024) == 77) imageInfo.MediaType = MediaType.SHARP_525;
+                    imageInfo.SectorSize = 1024;
                     break;
                 // 9 spt, 1024 bps
                 case DiskType.Hs2:
@@ -155,8 +158,8 @@ namespace DiscImageChef.DiscImages
                         return false;
                     }
 
-                    if(diskSize / (2 * 9 * 512) == 80) ImageInfo.MediaType = MediaType.SHARP_525_9;
-                    ImageInfo.SectorSize = 512;
+                    if(diskSize / (2 * 9 * 512) == 80) imageInfo.MediaType = MediaType.SHARP_525_9;
+                    imageInfo.SectorSize = 512;
                     break;
                 // 15 spt, 512 bps
                 case DiskType.Hc2:
@@ -166,8 +169,8 @@ namespace DiscImageChef.DiscImages
                         return false;
                     }
 
-                    if(diskSize / (2 * 15 * 512) == 80) ImageInfo.MediaType = MediaType.DOS_525_HD;
-                    ImageInfo.SectorSize = 512;
+                    if(diskSize / (2 * 15 * 512) == 80) imageInfo.MediaType = MediaType.DOS_525_HD;
+                    imageInfo.SectorSize = 512;
                     break;
                 // 9 spt, 1024 bps
                 case DiskType.Hde2:
@@ -177,8 +180,8 @@ namespace DiscImageChef.DiscImages
                         return false;
                     }
 
-                    if(diskSize / (2 * 9 * 512) == 80) ImageInfo.MediaType = MediaType.SHARP_35_9;
-                    ImageInfo.SectorSize = 512;
+                    if(diskSize / (2 * 9 * 512) == 80) imageInfo.MediaType = MediaType.SHARP_35_9;
+                    imageInfo.SectorSize = 512;
                     break;
                 // 18 spt, 512 bps
                 case DiskType.Hq2:
@@ -188,20 +191,20 @@ namespace DiscImageChef.DiscImages
                         return false;
                     }
 
-                    if(diskSize / (2 * 18 * 512) == 80) ImageInfo.MediaType = MediaType.DOS_35_HD;
-                    ImageInfo.SectorSize = 512;
+                    if(diskSize / (2 * 18 * 512) == 80) imageInfo.MediaType = MediaType.DOS_35_HD;
+                    imageInfo.SectorSize = 512;
                     break;
                 // 26 spt, 256 bps
                 case DiskType.N88:
                     if(diskSize % (2 * 26 * 256) == 0)
                     {
-                        if(diskSize % (2 * 26 * 256) == 77) ImageInfo.MediaType = MediaType.NEC_8_DD;
-                        ImageInfo.SectorSize = 256;
+                        if(diskSize % (2 * 26 * 256) == 77) imageInfo.MediaType = MediaType.NEC_8_DD;
+                        imageInfo.SectorSize = 256;
                     }
                     else if(diskSize % (2 * 26 * 128) == 0)
                     {
-                        if(diskSize % (2 * 26 * 128) == 77) ImageInfo.MediaType = MediaType.NEC_8_SD;
-                        ImageInfo.SectorSize = 256;
+                        if(diskSize % (2 * 26 * 128) == 77) imageInfo.MediaType = MediaType.NEC_8_SD;
+                        imageInfo.SectorSize = 256;
                     }
                     else
                     {
@@ -213,174 +216,174 @@ namespace DiscImageChef.DiscImages
                 default: return false;
             }
 
-            DicConsole.VerboseWriteLine("DIM image contains a disk of type {0}", ImageInfo.MediaType);
-            if(!string.IsNullOrEmpty(ImageInfo.Comments))
-                DicConsole.VerboseWriteLine("DIM comments: {0}", ImageInfo.Comments);
+            DicConsole.VerboseWriteLine("DIM image contains a disk of type {0}", imageInfo.MediaType);
+            if(!string.IsNullOrEmpty(imageInfo.Comments))
+                DicConsole.VerboseWriteLine("DIM comments: {0}", imageInfo.Comments);
 
             dimImageFilter = imageFilter;
 
-            ImageInfo.ImageSize = (ulong)diskSize;
-            ImageInfo.CreationTime = imageFilter.GetCreationTime();
-            ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
-            ImageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
-            ImageInfo.Sectors = ImageInfo.ImageSize / ImageInfo.SectorSize;
-            ImageInfo.Comments = StringHandlers.CToString(comment, Encoding.GetEncoding(932));
-            ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+            imageInfo.ImageSize = (ulong)diskSize;
+            imageInfo.CreationTime = imageFilter.GetCreationTime();
+            imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+            imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
+            imageInfo.Sectors = imageInfo.ImageSize / imageInfo.SectorSize;
+            imageInfo.Comments = StringHandlers.CToString(comment, Encoding.GetEncoding(932));
+            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
 
-            switch(ImageInfo.MediaType)
+            switch(imageInfo.MediaType)
             {
                 case MediaType.SHARP_525:
-                    ImageInfo.Cylinders = 77;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 8;
+                    imageInfo.Cylinders = 77;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 8;
                     break;
                 case MediaType.SHARP_525_9:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 9;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 9;
                     break;
                 case MediaType.DOS_525_HD:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 15;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 15;
                     break;
                 case MediaType.SHARP_35_9:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 9;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 9;
                     break;
                 case MediaType.DOS_35_HD:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 18;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 18;
                     break;
                 case MediaType.NEC_8_DD:
                 case MediaType.NEC_8_SD:
-                    ImageInfo.Cylinders = 77;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 26;
+                    imageInfo.Cylinders = 77;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 26;
                     break;
             }
 
             return true;
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
             return ReadSectors(sectorAddress, 1);
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
-            byte[] buffer = new byte[length * ImageInfo.SectorSize];
+            byte[] buffer = new byte[length * imageInfo.SectorSize];
 
             Stream stream = dimImageFilter.GetDataForkStream();
 
-            stream.Seek((long)(DATA_OFFSET + sectorAddress * ImageInfo.SectorSize), SeekOrigin.Begin);
+            stream.Seek((long)(DATA_OFFSET + sectorAddress * imageInfo.SectorSize), SeekOrigin.Begin);
 
-            stream.Read(buffer, 0, (int)(length * ImageInfo.SectorSize));
+            stream.Read(buffer, 0, (int)(length * imageInfo.SectorSize));
 
             return buffer;
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             return null;
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
             unknownLbas = new List();
-            for(ulong i = 0; i < ImageInfo.Sectors; i++) unknownLbas.Add(i);
+            for(ulong i = 0; i < imageInfo.Sectors; i++) unknownLbas.Add(i);
 
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return null;
         }
diff --git a/DiscImageChef.DiscImages/DiscFerret.cs b/DiscImageChef.DiscImages/DiscFerret.cs
index 44c2f271..d53cc3cb 100644
--- a/DiscImageChef.DiscImages/DiscFerret.cs
+++ b/DiscImageChef.DiscImages/DiscFerret.cs
@@ -40,7 +40,7 @@ using DiscImageChef.Filters;
 
 namespace DiscImageChef.DiscImages
 {
-    public class DiscFerret : ImagePlugin
+    public class DiscFerret : IMediaImage
     {
         /// 
         ///     "DFER"
@@ -50,15 +50,14 @@ namespace DiscImageChef.DiscImages
         ///     "DFE2"
         /// 
         const uint DFI_MAGIC2 = 0x32454644;
+        ImageInfo imageInfo;
         // TODO: These variables have been made public so create-sidecar can access to this information until I define an API >4.0
         public SortedDictionary TrackLengths;
         public SortedDictionary TrackOffsets;
 
         public DiscFerret()
         {
-            Name = "DiscFerret";
-            PluginUuid = new Guid("70EA7B9B-5323-42EB-9B40-8DDA37C5EB4D");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -83,18 +82,22 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "DiscFerret";
+        public virtual string Name => "DiscFerret";
+        public virtual Guid Id => new Guid("70EA7B9B-5323-42EB-9B40-8DDA37C5EB4D");
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Partitions =>
+        public virtual string ImageFormat => "DiscFerret";
+
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Sessions =>
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             byte[] magicB = new byte[4];
             Stream stream = imageFilter.GetDataForkStream();
@@ -104,7 +107,7 @@ namespace DiscImageChef.DiscImages
             return magic == DFI_MAGIC || magic == DFI_MAGIC2;
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             byte[] magicB = new byte[4];
             Stream stream = imageFilter.GetDataForkStream();
@@ -162,117 +165,117 @@ namespace DiscImageChef.DiscImages
                     t++;
                 }
 
-                if(blockHeader.cylinder > ImageInfo.Cylinders) ImageInfo.Cylinders = blockHeader.cylinder;
-                if(blockHeader.head > ImageInfo.Heads) ImageInfo.Heads = blockHeader.head;
+                if(blockHeader.cylinder > imageInfo.Cylinders) imageInfo.Cylinders = blockHeader.cylinder;
+                if(blockHeader.head > imageInfo.Heads) imageInfo.Heads = blockHeader.head;
             }
 
-            ImageInfo.Heads++;
-            ImageInfo.Cylinders++;
+            imageInfo.Heads++;
+            imageInfo.Cylinders++;
 
-            ImageInfo.Application = "DiscFerret";
-            ImageInfo.ApplicationVersion = magic == DFI_MAGIC2 ? "2.0" : "1.0";
+            imageInfo.Application = "DiscFerret";
+            imageInfo.ApplicationVersion = magic == DFI_MAGIC2 ? "2.0" : "1.0";
 
             throw new NotImplementedException("Flux decoding is not yet implemented.");
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new NotImplementedException("Flux decoding is not yet implemented.");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
             return ReadSectors(sectorAddress, 1);
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             throw new NotImplementedException("Flux decoding is not yet implemented.");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
             throw new NotImplementedException("Flux decoding is not yet implemented.");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             throw new NotImplementedException("Flux decoding is not yet implemented.");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             throw new NotImplementedException("Flux decoding is not yet implemented.");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             throw new NotImplementedException("Flux decoding is not yet implemented.");
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             throw new NotImplementedException("Flux decoding is not yet implemented.");
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             throw new NotImplementedException("Flux decoding is not yet implemented.");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
diff --git a/DiscImageChef.DiscImages/DiscImageChef.DiscImages.csproj b/DiscImageChef.DiscImages/DiscImageChef.DiscImages.csproj
index eb0f247f..fc5b8a55 100644
--- a/DiscImageChef.DiscImages/DiscImageChef.DiscImages.csproj
+++ b/DiscImageChef.DiscImages/DiscImageChef.DiscImages.csproj
@@ -51,15 +51,17 @@
   
   
     
+    
+    
     
     
     
     
     
     
-    
-    
+    
     
+    
     
     
     
diff --git a/DiscImageChef.DiscImages/DiscJuggler.cs b/DiscImageChef.DiscImages/DiscJuggler.cs
index 903d712a..5ffa8669 100644
--- a/DiscImageChef.DiscImages/DiscJuggler.cs
+++ b/DiscImageChef.DiscImages/DiscJuggler.cs
@@ -43,9 +43,10 @@ using DiscImageChef.Filters;
 namespace DiscImageChef.DiscImages
 {
     // Support separate data files? Never seen a DiscJuggler image using them anyways...
-    public class DiscJuggler : ImagePlugin
+    public class DiscJuggler : IMediaImage
     {
         byte[] cdtext;
+        ImageInfo imageInfo;
         Stream imageStream;
         Dictionary offsetmap;
         List partitions;
@@ -55,9 +56,7 @@ namespace DiscImageChef.DiscImages
 
         public DiscJuggler()
         {
-            Name = "DiscJuggler";
-            PluginUuid = new Guid("2444DBC6-CD35-424C-A227-39B0C4DB01B2");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -79,15 +78,19 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "DiscJuggler";
+        public virtual string Name => "DiscJuggler";
+        public virtual Guid Id => new Guid("2444DBC6-CD35-424C-A227-39B0C4DB01B2");
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Partitions => partitions;
+        public virtual string ImageFormat => "DiscJuggler";
 
-        public override List Tracks => tracks;
+        public virtual List Partitions => partitions;
 
-        public override List Sessions => sessions;
+        public virtual List Tracks => tracks;
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual List Sessions => sessions;
+
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             imageStream = imageFilter.GetDataForkStream();
 
@@ -117,7 +120,7 @@ namespace DiscImageChef.DiscImages
             return descriptor[2] <= 99;
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             imageStream = imageFilter.GetDataForkStream();
 
@@ -326,7 +329,7 @@ namespace DiscImageChef.DiscImages
                     {
                         // Audio
                         case 0:
-                            if(ImageInfo.SectorSize < 2352) ImageInfo.SectorSize = 2352;
+                            if(imageInfo.SectorSize < 2352) imageInfo.SectorSize = 2352;
                             track.TrackType = TrackType.Audio;
                             track.TrackBytesPerSector = 2352;
                             track.TrackRawBytesPerSector = 2352;
@@ -359,7 +362,7 @@ namespace DiscImageChef.DiscImages
                             break;
                         // Mode 1 or DVD
                         case 1:
-                            if(ImageInfo.SectorSize < 2048) ImageInfo.SectorSize = 2048;
+                            if(imageInfo.SectorSize < 2048) imageInfo.SectorSize = 2048;
                             track.TrackType = TrackType.CdMode1;
                             track.TrackBytesPerSector = 2048;
                             switch(readMode)
@@ -376,18 +379,18 @@ namespace DiscImageChef.DiscImages
                                 case 2:
                                     track.TrackRawBytesPerSector = 2352;
                                     currentOffset += trackLen * (ulong)track.TrackRawBytesPerSector;
-                                    if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync))
-                                        ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync);
-                                    if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader))
-                                        ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader);
-                                    if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEcc))
-                                        ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc);
-                                    if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccP))
-                                        ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP);
-                                    if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccQ))
-                                        ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ);
-                                    if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc))
-                                        ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc);
+                                    if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync))
+                                        imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync);
+                                    if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader))
+                                        imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader);
+                                    if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEcc))
+                                        imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc);
+                                    if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccP))
+                                        imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP);
+                                    if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccQ))
+                                        imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ);
+                                    if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc))
+                                        imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc);
                                     break;
                                 case 3:
                                     track.TrackRawBytesPerSector = 2352;
@@ -397,18 +400,18 @@ namespace DiscImageChef.DiscImages
                                     track.TrackSubchannelOffset = currentOffset;
                                     track.TrackSubchannelType = TrackSubchannelType.Q16Interleaved;
                                     currentOffset += trackLen * (ulong)(track.TrackRawBytesPerSector + 16);
-                                    if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync))
-                                        ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync);
-                                    if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader))
-                                        ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader);
-                                    if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEcc))
-                                        ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc);
-                                    if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccP))
-                                        ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP);
-                                    if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccQ))
-                                        ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ);
-                                    if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc))
-                                        ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc);
+                                    if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync))
+                                        imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync);
+                                    if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader))
+                                        imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader);
+                                    if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEcc))
+                                        imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc);
+                                    if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccP))
+                                        imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP);
+                                    if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccQ))
+                                        imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ);
+                                    if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc))
+                                        imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc);
                                     break;
                                 case 4:
                                     track.TrackRawBytesPerSector = 2352;
@@ -418,18 +421,18 @@ namespace DiscImageChef.DiscImages
                                     track.TrackSubchannelOffset = currentOffset;
                                     track.TrackSubchannelType = TrackSubchannelType.RawInterleaved;
                                     currentOffset += trackLen * (ulong)(track.TrackRawBytesPerSector + 96);
-                                    if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync))
-                                        ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync);
-                                    if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader))
-                                        ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader);
-                                    if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEcc))
-                                        ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc);
-                                    if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccP))
-                                        ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP);
-                                    if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccQ))
-                                        ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ);
-                                    if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc))
-                                        ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc);
+                                    if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync))
+                                        imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync);
+                                    if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader))
+                                        imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader);
+                                    if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEcc))
+                                        imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc);
+                                    if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccP))
+                                        imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP);
+                                    if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccQ))
+                                        imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ);
+                                    if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc))
+                                        imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc);
                                     break;
                                 default: throw new ImageNotSupportedException($"Unknown read mode {readMode}");
                             }
@@ -437,7 +440,7 @@ namespace DiscImageChef.DiscImages
                             break;
                         // Mode 2
                         case 2:
-                            if(ImageInfo.SectorSize < 2336) ImageInfo.SectorSize = 2336;
+                            if(imageInfo.SectorSize < 2336) imageInfo.SectorSize = 2336;
                             track.TrackType = TrackType.CdMode2Formless;
                             track.TrackBytesPerSector = 2336;
                             switch(readMode)
@@ -454,10 +457,10 @@ namespace DiscImageChef.DiscImages
                                 case 2:
                                     track.TrackRawBytesPerSector = 2352;
                                     currentOffset += trackLen * (ulong)track.TrackRawBytesPerSector;
-                                    if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync))
-                                        ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync);
-                                    if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader))
-                                        ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader);
+                                    if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync))
+                                        imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync);
+                                    if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader))
+                                        imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader);
                                     break;
                                 case 3:
                                     track.TrackRawBytesPerSector = 2352;
@@ -467,10 +470,10 @@ namespace DiscImageChef.DiscImages
                                     track.TrackSubchannelOffset = currentOffset;
                                     track.TrackSubchannelType = TrackSubchannelType.Q16Interleaved;
                                     currentOffset += trackLen * (ulong)(track.TrackRawBytesPerSector + 16);
-                                    if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync))
-                                        ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync);
-                                    if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader))
-                                        ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader);
+                                    if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync))
+                                        imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync);
+                                    if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader))
+                                        imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader);
                                     break;
                                 case 4:
                                     track.TrackRawBytesPerSector = 2352;
@@ -480,10 +483,10 @@ namespace DiscImageChef.DiscImages
                                     track.TrackSubchannelOffset = currentOffset;
                                     track.TrackSubchannelType = TrackSubchannelType.RawInterleaved;
                                     currentOffset += trackLen * (ulong)(track.TrackRawBytesPerSector + 96);
-                                    if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync))
-                                        ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync);
-                                    if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader))
-                                        ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader);
+                                    if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync))
+                                        imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync);
+                                    if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader))
+                                        imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader);
                                     break;
                                 default: throw new ImageNotSupportedException($"Unknown read mode {readMode}");
                             }
@@ -498,8 +501,8 @@ namespace DiscImageChef.DiscImages
                     {
                         track.TrackSubchannelFile = imageFilter.GetFilename();
                         track.TrackSubchannelFilter = imageFilter;
-                        if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubchannel))
-                            ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubchannel);
+                        if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubchannel))
+                            imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubchannel);
                     }
 
                     Partition partition = new Partition
@@ -512,7 +515,7 @@ namespace DiscImageChef.DiscImages
                         Start = track.TrackStartSector,
                         Type = track.TrackType.ToString()
                     };
-                    ImageInfo.Sectors += partition.Length;
+                    imageInfo.Sectors += partition.Length;
                     partitions.Add(partition);
                     offsetmap.Add(track.TrackSequence, track.TrackStartSector);
                     tracks.Add(track);
@@ -580,7 +583,7 @@ namespace DiscImageChef.DiscImages
                 cdtext = new byte[cdtextLen];
                 Array.Copy(descriptor, position, cdtext, 0, cdtextLen);
                 position += (int)cdtextLen;
-                ImageInfo.ReadableMediaTags.Add(MediaTagType.CD_TEXT);
+                imageInfo.ReadableMediaTags.Add(MediaTagType.CD_TEXT);
             }
 
             // Skip unknown
@@ -588,7 +591,7 @@ namespace DiscImageChef.DiscImages
 
             DicConsole.DebugWriteLine("DiscJuggler plugin", "End position = {0}", position);
 
-            if(ImageInfo.MediaType == MediaType.CDROM)
+            if(imageInfo.MediaType == MediaType.CDROM)
             {
                 bool data = false;
                 bool mode2 = false;
@@ -620,18 +623,18 @@ namespace DiscImageChef.DiscImages
                     }
                 }
 
-                if(!data && !firstdata) ImageInfo.MediaType = MediaType.CDDA;
-                else if(firstaudio && data && sessions.Count > 1 && mode2) ImageInfo.MediaType = MediaType.CDPLUS;
-                else if(firstdata && audio || mode2) ImageInfo.MediaType = MediaType.CDROMXA;
-                else if(!audio) ImageInfo.MediaType = MediaType.CDROM;
-                else ImageInfo.MediaType = MediaType.CD;
+                if(!data && !firstdata) imageInfo.MediaType = MediaType.CDDA;
+                else if(firstaudio && data && sessions.Count > 1 && mode2) imageInfo.MediaType = MediaType.CDPLUS;
+                else if(firstdata && audio || mode2) imageInfo.MediaType = MediaType.CDROMXA;
+                else if(!audio) imageInfo.MediaType = MediaType.CDROM;
+                else imageInfo.MediaType = MediaType.CD;
             }
 
-            ImageInfo.Application = "DiscJuggler";
-            ImageInfo.ImageSize = (ulong)imageFilter.GetDataForkLength();
-            ImageInfo.CreationTime = imageFilter.GetCreationTime();
-            ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
-            ImageInfo.XmlMediaType = XmlMediaType.OpticalDisc;
+            imageInfo.Application = "DiscJuggler";
+            imageInfo.ImageSize = (ulong)imageFilter.GetDataForkLength();
+            imageInfo.CreationTime = imageFilter.GetCreationTime();
+            imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+            imageInfo.XmlMediaType = XmlMediaType.OpticalDisc;
 
             return true;
         }
@@ -646,7 +649,7 @@ namespace DiscImageChef.DiscImages
             }
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             switch(tag)
             {
@@ -661,27 +664,27 @@ namespace DiscImageChef.DiscImages
             }
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
             return ReadSectors(sectorAddress, 1);
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             return ReadSectorsTag(sectorAddress, 1, tag);
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             return ReadSectors(sectorAddress, 1, track);
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             return ReadSectorsTag(sectorAddress, 1, track, tag);
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
             foreach(KeyValuePair kvp in from kvp in offsetmap
                                                      where sectorAddress >= kvp.Value
@@ -694,7 +697,7 @@ namespace DiscImageChef.DiscImages
             throw new ArgumentOutOfRangeException(nameof(sectorAddress), $"Sector address {sectorAddress} not found");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             foreach(KeyValuePair kvp in offsetmap
                 .Where(kvp => sectorAddress >= kvp.Value)
@@ -705,7 +708,7 @@ namespace DiscImageChef.DiscImages
             throw new ArgumentOutOfRangeException(nameof(sectorAddress), $"Sector address {sectorAddress} not found");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             Track dicTrack = new Track {TrackSequence = 0};
 
@@ -798,7 +801,7 @@ namespace DiscImageChef.DiscImages
             return buffer;
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             Track dicTrack = new Track {TrackSequence = 0};
 
@@ -1013,17 +1016,17 @@ namespace DiscImageChef.DiscImages
             return buffer;
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             return ReadSectorsLong(sectorAddress, 1);
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             return ReadSectorsLong(sectorAddress, 1, track);
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             foreach(KeyValuePair kvp in from kvp in offsetmap
                                                      where sectorAddress >= kvp.Value
@@ -1037,7 +1040,7 @@ namespace DiscImageChef.DiscImages
             throw new ArgumentOutOfRangeException(nameof(sectorAddress), $"Sector address {sectorAddress} not found");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             Track dicTrack = new Track {TrackSequence = 0};
 
@@ -1088,31 +1091,31 @@ namespace DiscImageChef.DiscImages
             return buffer;
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             if(sessions.Contains(session)) return GetSessionTracks(session.SessionSequence);
 
             throw new ImageNotSupportedException("Session does not exist in disc image");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             return tracks.Where(track => track.TrackSession == session).ToList();
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             byte[] buffer = ReadSectorLong(sectorAddress);
             return CdChecksums.CheckCdSector(buffer);
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             byte[] buffer = ReadSectorLong(sectorAddress, track);
             return CdChecksums.CheckCdSector(buffer);
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             byte[] buffer = ReadSectorsLong(sectorAddress, length);
@@ -1142,7 +1145,7 @@ namespace DiscImageChef.DiscImages
             return failingLbas.Count <= 0;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             byte[] buffer = ReadSectorsLong(sectorAddress, length, track);
@@ -1172,7 +1175,7 @@ namespace DiscImageChef.DiscImages
             return failingLbas.Count <= 0;
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return null;
         }
diff --git a/DiscImageChef.DiscImages/DiskCopy42.cs b/DiscImageChef.DiscImages/DiskCopy42.cs
index fee21de7..dd769f64 100644
--- a/DiscImageChef.DiscImages/DiskCopy42.cs
+++ b/DiscImageChef.DiscImages/DiskCopy42.cs
@@ -46,7 +46,7 @@ namespace DiscImageChef.DiscImages
 {
     // Checked using several images and strings inside Apple's DiskImages.framework
     [SuppressMessage("ReSharper", "InconsistentNaming")]
-    public class DiskCopy42 : ImagePlugin
+    public class DiskCopy42 : IMediaImage
     {
         // format byte
         /// 3.5", single side, double density, GCR
@@ -97,7 +97,7 @@ namespace DiscImageChef.DiscImages
         /// Start of data sectors in disk image, should be 0x58
         uint dataOffset;
         /// Disk image file
-        Filter dc42ImageFilter;
+        IFilter dc42ImageFilter;
         /// Header of opened image
         Dc42Header header;
         /// Start of tags in disk image, after data sectors
@@ -105,12 +105,15 @@ namespace DiscImageChef.DiscImages
         bool twiggy;
         byte[] twiggyCache;
         byte[] twiggyCacheTags;
+        ImageInfo imageInfo;
+        public virtual ImageInfo Info => imageInfo;
+
+        public virtual string Name => "Apple DiskCopy 4.2";
+        public virtual Guid Id => new Guid("0240B7B1-E959-4CDC-B0BD-386D6E467B88");
 
         public DiskCopy42()
         {
-            Name = "Apple DiskCopy 4.2";
-            PluginUuid = new Guid("0240B7B1-E959-4CDC-B0BD-386D6E467B88");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -135,7 +138,7 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -216,7 +219,7 @@ namespace DiscImageChef.DiscImages
             return false;
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -295,15 +298,15 @@ namespace DiscImageChef.DiscImages
 
             dataOffset = 0x54;
             tagOffset = header.TagSize != 0 ? 0x54 + header.DataSize : 0;
-            ImageInfo.SectorSize = 512;
+            imageInfo.SectorSize = 512;
             bptag = (uint)(header.TagSize != 0 ? 12 : 0);
             dc42ImageFilter = imageFilter;
 
-            ImageInfo.Sectors = header.DataSize / 512;
+            imageInfo.Sectors = header.DataSize / 512;
 
             if(header.TagSize != 0)
             {
-                bptag = (uint)(header.TagSize / ImageInfo.Sectors);
+                bptag = (uint)(header.TagSize / imageInfo.Sectors);
                 DicConsole.DebugWriteLine("DC42 plugin", "bptag = {0} bytes", bptag);
 
                 if(bptag != 12 && bptag != 20 && bptag != 24)
@@ -312,61 +315,61 @@ namespace DiscImageChef.DiscImages
                     return false;
                 }
 
-                ImageInfo.ReadableSectorTags.Add(SectorTagType.AppleSectorTag);
+                imageInfo.ReadableSectorTags.Add(SectorTagType.AppleSectorTag);
             }
 
-            ImageInfo.ImageSize = ImageInfo.Sectors * ImageInfo.SectorSize + ImageInfo.Sectors * bptag;
-            ImageInfo.CreationTime = imageFilter.GetCreationTime();
-            ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
-            ImageInfo.MediaTitle = header.DiskName;
+            imageInfo.ImageSize = imageInfo.Sectors * imageInfo.SectorSize + imageInfo.Sectors * bptag;
+            imageInfo.CreationTime = imageFilter.GetCreationTime();
+            imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+            imageInfo.MediaTitle = header.DiskName;
 
             switch(header.Format)
             {
                 case kSonyFormat400K:
-                    ImageInfo.MediaType = ImageInfo.Sectors == 1600 ? MediaType.AppleSonyDS : MediaType.AppleSonySS;
+                    imageInfo.MediaType = imageInfo.Sectors == 1600 ? MediaType.AppleSonyDS : MediaType.AppleSonySS;
                     break;
                 case kSonyFormat800K:
-                    ImageInfo.MediaType = MediaType.AppleSonyDS;
+                    imageInfo.MediaType = MediaType.AppleSonyDS;
                     break;
                 case kSonyFormat720K:
-                    ImageInfo.MediaType = MediaType.DOS_35_DS_DD_9;
+                    imageInfo.MediaType = MediaType.DOS_35_DS_DD_9;
                     break;
                 case kSonyFormat1440K:
-                    ImageInfo.MediaType = MediaType.DOS_35_HD;
+                    imageInfo.MediaType = MediaType.DOS_35_HD;
                     break;
                 case kSonyFormat1680K:
-                    ImageInfo.MediaType = MediaType.DMF;
+                    imageInfo.MediaType = MediaType.DMF;
                     break;
                 case kSigmaFormatTwiggy:
-                    ImageInfo.MediaType = MediaType.AppleFileWare;
+                    imageInfo.MediaType = MediaType.AppleFileWare;
                     break;
                 case kNotStandardFormat:
-                    switch(ImageInfo.Sectors)
+                    switch(imageInfo.Sectors)
                     {
                         case 9728:
-                            ImageInfo.MediaType = MediaType.AppleProfile;
+                            imageInfo.MediaType = MediaType.AppleProfile;
                             break;
                         case 19456:
-                            ImageInfo.MediaType = MediaType.AppleProfile;
+                            imageInfo.MediaType = MediaType.AppleProfile;
                             break;
                         case 38912:
-                            ImageInfo.MediaType = MediaType.AppleWidget;
+                            imageInfo.MediaType = MediaType.AppleWidget;
                             break;
                         case 39040:
-                            ImageInfo.MediaType = MediaType.AppleHD20;
+                            imageInfo.MediaType = MediaType.AppleHD20;
                             break;
                         default:
-                            ImageInfo.MediaType = MediaType.Unknown;
+                            imageInfo.MediaType = MediaType.Unknown;
                             break;
                     }
 
                     break;
                 default:
-                    ImageInfo.MediaType = MediaType.Unknown;
+                    imageInfo.MediaType = MediaType.Unknown;
                     break;
             }
 
-            if(ImageInfo.MediaType == MediaType.AppleFileWare)
+            if(imageInfo.MediaType == MediaType.AppleFileWare)
             {
                 byte[] data = new byte[header.DataSize];
                 byte[] tags = new byte[header.TagSize];
@@ -465,9 +468,9 @@ namespace DiscImageChef.DiscImages
 
                             if(dev != null) pre = $"{version.PreReleaseVersion}";
 
-                            ImageInfo.ApplicationVersion = $"{major}{minor}{release}{dev}{pre}";
-                            ImageInfo.Application = version.VersionString;
-                            ImageInfo.Comments = version.VersionMessage;
+                            imageInfo.ApplicationVersion = $"{major}{minor}{release}{dev}{pre}";
+                            imageInfo.Application = version.VersionString;
+                            imageInfo.Comments = version.VersionMessage;
                         }
                     }
 
@@ -485,12 +488,11 @@ namespace DiscImageChef.DiscImages
 
                             if(dCpyMatch.Success)
                             {
-                                ImageInfo.Application = dCpyMatch.Groups["application"].Value;
-                                ImageInfo.ApplicationVersion = dCpyMatch.Groups["version"].Value;
+                                imageInfo.Application = dCpyMatch.Groups["application"].Value;
+                                imageInfo.ApplicationVersion = dCpyMatch.Groups["version"].Value;
 
                                 // Until MacRoman is implemented
-                                if(ImageInfo.Application == "ShrinkWrap?")
-                                    ImageInfo.Application = "ShrinkWrapâ„¢";
+                                if(imageInfo.Application == "ShrinkWrap?") imageInfo.Application = "ShrinkWrapâ„¢";
                             }
                         }
                     }
@@ -498,84 +500,84 @@ namespace DiscImageChef.DiscImages
             }
             catch(InvalidCastException) { }
 
-            DicConsole.DebugWriteLine("DC42 plugin", "Image application = {0} version {1}", ImageInfo.Application,
-                                      ImageInfo.ApplicationVersion);
+            DicConsole.DebugWriteLine("DC42 plugin", "Image application = {0} version {1}", imageInfo.Application,
+                                      imageInfo.ApplicationVersion);
 
-            ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
-            DicConsole.VerboseWriteLine("DiskCopy 4.2 image contains a disk of type {0}", ImageInfo.MediaType);
+            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+            DicConsole.VerboseWriteLine("DiskCopy 4.2 image contains a disk of type {0}", imageInfo.MediaType);
 
-            switch(ImageInfo.MediaType)
+            switch(imageInfo.MediaType)
             {
                 case MediaType.AppleSonySS:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 1;
-                    ImageInfo.SectorsPerTrack = 10;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 1;
+                    imageInfo.SectorsPerTrack = 10;
                     break;
                 case MediaType.AppleSonyDS:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 10;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 10;
                     break;
                 case MediaType.DOS_35_DS_DD_9:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 9;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 9;
                     break;
                 case MediaType.DOS_35_HD:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 18;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 18;
                     break;
                 case MediaType.DMF:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 21;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 21;
                     break;
                 case MediaType.AppleProfile:
-                    switch(ImageInfo.Sectors)
+                    switch(imageInfo.Sectors)
                     {
                         case 9728:
-                            ImageInfo.Cylinders = 152;
+                            imageInfo.Cylinders = 152;
                             break;
                         case 19456:
-                            ImageInfo.Cylinders = 304;
+                            imageInfo.Cylinders = 304;
                             break;
                     }
 
-                    ImageInfo.Heads = 4;
-                    ImageInfo.SectorsPerTrack = 16;
+                    imageInfo.Heads = 4;
+                    imageInfo.SectorsPerTrack = 16;
                     break;
                 case MediaType.AppleWidget:
-                    ImageInfo.Cylinders = 608;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 16;
+                    imageInfo.Cylinders = 608;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 16;
                     break;
                 case MediaType.AppleHD20:
-                    ImageInfo.Cylinders = 610;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 16;
+                    imageInfo.Cylinders = 610;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 16;
                     break;
                 default:
-                    ImageInfo.Cylinders = (uint)(ImageInfo.Sectors / 16 / 63);
-                    ImageInfo.Heads = 16;
-                    ImageInfo.SectorsPerTrack = 63;
+                    imageInfo.Cylinders = (uint)(imageInfo.Sectors / 16 / 63);
+                    imageInfo.Heads = 16;
+                    imageInfo.SectorsPerTrack = 63;
                     break;
             }
 
             return true;
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             return null;
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
@@ -586,7 +588,7 @@ namespace DiscImageChef.DiscImages
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
@@ -597,7 +599,7 @@ namespace DiscImageChef.DiscImages
             return null;
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             byte[] data = new byte[header.DataSize];
             byte[] tags = new byte[header.TagSize];
@@ -629,50 +631,50 @@ namespace DiscImageChef.DiscImages
             return dataChk == header.DataChecksum && tagsChk == header.TagChecksum;
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
             return ReadSectors(sectorAddress, 1);
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             return ReadSectorsTag(sectorAddress, 1, tag);
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
-            byte[] buffer = new byte[length * ImageInfo.SectorSize];
+            byte[] buffer = new byte[length * imageInfo.SectorSize];
 
             if(twiggy)
-                Array.Copy(twiggyCache, (int)sectorAddress * ImageInfo.SectorSize, buffer, 0,
-                           length * ImageInfo.SectorSize);
+                Array.Copy(twiggyCache, (int)sectorAddress * imageInfo.SectorSize, buffer, 0,
+                           length * imageInfo.SectorSize);
             else
             {
                 Stream stream = dc42ImageFilter.GetDataForkStream();
-                stream.Seek((long)(dataOffset + sectorAddress * ImageInfo.SectorSize), SeekOrigin.Begin);
-                stream.Read(buffer, 0, (int)(length * ImageInfo.SectorSize));
+                stream.Seek((long)(dataOffset + sectorAddress * imageInfo.SectorSize), SeekOrigin.Begin);
+                stream.Read(buffer, 0, (int)(length * imageInfo.SectorSize));
             }
 
             return buffer;
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             if(tag != SectorTagType.AppleSectorTag)
                 throw new FeatureUnsupportedImageException($"Tag {tag} not supported by image format");
 
             if(header.TagSize == 0) throw new FeatureNotPresentImageException("Disk image does not have tags");
 
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
             byte[] buffer = new byte[length * bptag];
@@ -688,17 +690,17 @@ namespace DiscImageChef.DiscImages
             return buffer;
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             return ReadSectorsLong(sectorAddress, 1);
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
             byte[] data = ReadSectors(sectorAddress, length);
@@ -707,66 +709,66 @@ namespace DiscImageChef.DiscImages
 
             for(uint i = 0; i < length; i++)
             {
-                Array.Copy(data, i * ImageInfo.SectorSize, buffer, i * (ImageInfo.SectorSize + bptag),
-                           ImageInfo.SectorSize);
-                Array.Copy(tags, i * bptag, buffer, i * (ImageInfo.SectorSize + bptag) + ImageInfo.SectorSize, bptag);
+                Array.Copy(data, i * imageInfo.SectorSize, buffer, i * (imageInfo.SectorSize + bptag),
+                           imageInfo.SectorSize);
+                Array.Copy(tags, i * bptag, buffer, i * (imageInfo.SectorSize + bptag) + imageInfo.SectorSize, bptag);
             }
 
             return buffer;
         }
 
-        public override string ImageFormat => "Apple DiskCopy 4.2";
+        public virtual string ImageFormat => "Apple DiskCopy 4.2";
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List Partitions =>
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List Sessions =>
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
diff --git a/DiscImageChef.DiscImages/DriDiskCopy.cs b/DiscImageChef.DiscImages/DriDiskCopy.cs
index d16905c8..87bbb158 100644
--- a/DiscImageChef.DiscImages/DriDiskCopy.cs
+++ b/DiscImageChef.DiscImages/DriDiskCopy.cs
@@ -42,21 +42,20 @@ using DiscImageChef.Filters;
 
 namespace DiscImageChef.DiscImages
 {
-    public class DriDiskCopy : ImagePlugin
+    public class DriDiskCopy : IMediaImage
     {
         const string REGEX_DRI = @"DiskImage\s(?\d+.\d+)\s\(C\)\s\d+\,*\d*\s+Digital Research Inc";
 
         /// Disk image file
-        Filter driImageFilter;
+        IFilter driImageFilter;
 
         /// Footer of opened image
         DriFooter footer;
+        ImageInfo imageInfo;
 
         public DriDiskCopy()
         {
-            Name = "Digital Research DiskCopy";
-            PluginUuid = new Guid("9F0BE551-8BAB-4038-8B5A-691F1BF5FFF3");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -79,18 +78,23 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "Digital Research DiskCopy";
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Partitions =>
+        public virtual string Name => "Digital Research DiskCopy";
+        public virtual Guid Id => new Guid("9F0BE551-8BAB-4038-8B5A-691F1BF5FFF3");
+
+        public virtual string ImageFormat => "Digital Research DiskCopy";
+
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Sessions =>
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
 
@@ -145,7 +149,7 @@ namespace DiscImageChef.DiscImages
             return tmpFooter.bpb.sectors * tmpFooter.bpb.bps + Marshal.SizeOf(tmpFooter) == stream.Length;
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
 
@@ -172,119 +176,119 @@ namespace DiscImageChef.DiscImages
 
             if(footer.bpb.sectors * footer.bpb.bps + Marshal.SizeOf(footer) != stream.Length) return false;
 
-            ImageInfo.Cylinders = footer.bpb.cylinders;
-            ImageInfo.Heads = footer.bpb.heads;
-            ImageInfo.SectorsPerTrack = footer.bpb.sptrack;
-            ImageInfo.Sectors = footer.bpb.sectors;
-            ImageInfo.SectorSize = footer.bpb.bps;
-            ImageInfo.ApplicationVersion = matchSignature.Groups["version"].Value;
+            imageInfo.Cylinders = footer.bpb.cylinders;
+            imageInfo.Heads = footer.bpb.heads;
+            imageInfo.SectorsPerTrack = footer.bpb.sptrack;
+            imageInfo.Sectors = footer.bpb.sectors;
+            imageInfo.SectorSize = footer.bpb.bps;
+            imageInfo.ApplicationVersion = matchSignature.Groups["version"].Value;
 
             driImageFilter = imageFilter;
 
-            ImageInfo.ImageSize = (ulong)(stream.Length - Marshal.SizeOf(footer));
-            ImageInfo.CreationTime = imageFilter.GetCreationTime();
-            ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+            imageInfo.ImageSize = (ulong)(stream.Length - Marshal.SizeOf(footer));
+            imageInfo.CreationTime = imageFilter.GetCreationTime();
+            imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
 
             DicConsole.DebugWriteLine("DRI DiskCopy plugin", "Image application = {0} version {1}",
-                                      ImageInfo.Application, ImageInfo.ApplicationVersion);
+                                      imageInfo.Application, imageInfo.ApplicationVersion);
 
             // Correct some incorrect data in images of NEC 2HD disks
-            if(ImageInfo.Cylinders == 77 && ImageInfo.Heads == 2 && ImageInfo.SectorsPerTrack == 16 &&
-               ImageInfo.SectorSize == 512 &&
+            if(imageInfo.Cylinders == 77 && imageInfo.Heads == 2 && imageInfo.SectorsPerTrack == 16 &&
+               imageInfo.SectorSize == 512 &&
                (footer.bpb.driveCode == DriDriveCodes.md2hd || footer.bpb.driveCode == DriDriveCodes.mf2hd))
             {
-                ImageInfo.SectorsPerTrack = 8;
-                ImageInfo.SectorSize = 1024;
+                imageInfo.SectorsPerTrack = 8;
+                imageInfo.SectorSize = 1024;
             }
 
             switch(footer.bpb.driveCode)
             {
                 case DriDriveCodes.md2hd:
-                    if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 15 &&
-                       ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DOS_525_HD;
-                    else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 16 &&
-                            ImageInfo.SectorSize == 256) ImageInfo.MediaType = MediaType.ACORN_525_DS_DD;
-                    else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 16 &&
-                            ImageInfo.SectorSize == 256) ImageInfo.MediaType = MediaType.ACORN_525_SS_DD_80;
-                    else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 10 &&
-                            ImageInfo.SectorSize == 256) ImageInfo.MediaType = MediaType.ACORN_525_SS_SD_80;
-                    else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 77 && ImageInfo.SectorsPerTrack == 8 &&
-                            ImageInfo.SectorSize == 1024) ImageInfo.MediaType = MediaType.NEC_525_HD;
+                    if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 15 &&
+                       imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_HD;
+                    else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 16 &&
+                            imageInfo.SectorSize == 256) imageInfo.MediaType = MediaType.ACORN_525_DS_DD;
+                    else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 16 &&
+                            imageInfo.SectorSize == 256) imageInfo.MediaType = MediaType.ACORN_525_SS_DD_80;
+                    else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 10 &&
+                            imageInfo.SectorSize == 256) imageInfo.MediaType = MediaType.ACORN_525_SS_SD_80;
+                    else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 77 && imageInfo.SectorsPerTrack == 8 &&
+                            imageInfo.SectorSize == 1024) imageInfo.MediaType = MediaType.NEC_525_HD;
                     else goto case DriDriveCodes.md2dd;
                     break;
                 case DriDriveCodes.md2dd:
-                    if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 40 && ImageInfo.SectorsPerTrack == 8 &&
-                       ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DOS_525_SS_DD_8;
-                    else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 40 && ImageInfo.SectorsPerTrack == 9 &&
-                            ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DOS_525_SS_DD_9;
-                    else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 40 && ImageInfo.SectorsPerTrack == 8 &&
-                            ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DOS_525_DS_DD_8;
-                    else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 40 && ImageInfo.SectorsPerTrack == 9 &&
-                            ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DOS_525_DS_DD_9;
-                    else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 40 && ImageInfo.SectorsPerTrack == 18 &&
-                            ImageInfo.SectorSize == 128) ImageInfo.MediaType = MediaType.ATARI_525_SD;
-                    else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 40 && ImageInfo.SectorsPerTrack == 26 &&
-                            ImageInfo.SectorSize == 128) ImageInfo.MediaType = MediaType.ATARI_525_ED;
-                    else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 40 && ImageInfo.SectorsPerTrack == 18 &&
-                            ImageInfo.SectorSize == 256) ImageInfo.MediaType = MediaType.ATARI_525_DD;
-                    else ImageInfo.MediaType = MediaType.Unknown;
+                    if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 8 &&
+                       imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_SS_DD_8;
+                    else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 9 &&
+                            imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_SS_DD_9;
+                    else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 8 &&
+                            imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_DS_DD_8;
+                    else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 9 &&
+                            imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_DS_DD_9;
+                    else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 18 &&
+                            imageInfo.SectorSize == 128) imageInfo.MediaType = MediaType.ATARI_525_SD;
+                    else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 26 &&
+                            imageInfo.SectorSize == 128) imageInfo.MediaType = MediaType.ATARI_525_ED;
+                    else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 18 &&
+                            imageInfo.SectorSize == 256) imageInfo.MediaType = MediaType.ATARI_525_DD;
+                    else imageInfo.MediaType = MediaType.Unknown;
                     break;
                 case DriDriveCodes.mf2ed:
-                    if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 36 &&
-                       ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DOS_35_ED;
+                    if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 36 &&
+                       imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_ED;
                     else goto case DriDriveCodes.mf2hd;
                     break;
                 case DriDriveCodes.mf2hd:
-                    if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 18 &&
-                       ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DOS_35_HD;
-                    else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 21 &&
-                            ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DMF;
-                    else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 82 && ImageInfo.SectorsPerTrack == 21 &&
-                            ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DMF_82;
-                    else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 77 && ImageInfo.SectorsPerTrack == 8 &&
-                            ImageInfo.SectorSize == 1024) ImageInfo.MediaType = MediaType.NEC_35_HD_8;
-                    else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 15 &&
-                            ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.NEC_35_HD_15;
+                    if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 18 &&
+                       imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_HD;
+                    else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 21 &&
+                            imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DMF;
+                    else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 82 && imageInfo.SectorsPerTrack == 21 &&
+                            imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DMF_82;
+                    else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 77 && imageInfo.SectorsPerTrack == 8 &&
+                            imageInfo.SectorSize == 1024) imageInfo.MediaType = MediaType.NEC_35_HD_8;
+                    else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 15 &&
+                            imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.NEC_35_HD_15;
                     else goto case DriDriveCodes.mf2dd;
                     break;
                 case DriDriveCodes.mf2dd:
-                    if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 9 &&
-                       ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DOS_35_DS_DD_9;
-                    else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 8 &&
-                            ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DOS_35_DS_DD_8;
-                    else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 9 &&
-                            ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DOS_35_SS_DD_9;
-                    else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 8 &&
-                            ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DOS_35_SS_DD_8;
-                    else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 5 &&
-                            ImageInfo.SectorSize == 1024) ImageInfo.MediaType = MediaType.ACORN_35_DS_DD;
-                    else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 70 && ImageInfo.SectorsPerTrack == 9 &&
-                            ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.Apricot_35;
-                    else ImageInfo.MediaType = MediaType.Unknown;
+                    if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 9 &&
+                       imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_DS_DD_9;
+                    else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 8 &&
+                            imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_DS_DD_8;
+                    else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 9 &&
+                            imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_SS_DD_9;
+                    else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 8 &&
+                            imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_SS_DD_8;
+                    else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 5 &&
+                            imageInfo.SectorSize == 1024) imageInfo.MediaType = MediaType.ACORN_35_DS_DD;
+                    else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 70 && imageInfo.SectorsPerTrack == 9 &&
+                            imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.Apricot_35;
+                    else imageInfo.MediaType = MediaType.Unknown;
                     break;
                 default:
-                    ImageInfo.MediaType = MediaType.Unknown;
+                    imageInfo.MediaType = MediaType.Unknown;
                     break;
             }
 
-            ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
             DicConsole.VerboseWriteLine("Digital Research DiskCopy image contains a disk of type {0}",
-                                        ImageInfo.MediaType);
+                                        imageInfo.MediaType);
 
             return true;
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             return null;
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
@@ -295,7 +299,7 @@ namespace DiscImageChef.DiscImages
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
@@ -306,94 +310,94 @@ namespace DiscImageChef.DiscImages
             return null;
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return null;
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
             return ReadSectors(sectorAddress, 1);
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
-            byte[] buffer = new byte[length * ImageInfo.SectorSize];
+            byte[] buffer = new byte[length * imageInfo.SectorSize];
 
             Stream stream = driImageFilter.GetDataForkStream();
-            stream.Seek((long)(sectorAddress * ImageInfo.SectorSize), SeekOrigin.Begin);
-            stream.Read(buffer, 0, (int)(length * ImageInfo.SectorSize));
+            stream.Seek((long)(sectorAddress * imageInfo.SectorSize), SeekOrigin.Begin);
+            stream.Read(buffer, 0, (int)(length * imageInfo.SectorSize));
 
             return buffer;
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
diff --git a/DiscImageChef.DiscImages/Enums.cs b/DiscImageChef.DiscImages/Enums.cs
new file mode 100644
index 00000000..f7fbf11f
--- /dev/null
+++ b/DiscImageChef.DiscImages/Enums.cs
@@ -0,0 +1,292 @@
+// /***************************************************************************
+// The Disc Image Chef
+// ----------------------------------------------------------------------------
+//
+// Filename       : Enums.cs
+// Author(s)      : Natalia Portillo 
+//
+// Component      : Disc image plugins.
+//
+// --[ Description ] ----------------------------------------------------------
+//
+//     Defines enumerations to be used by disc image plugins.
+//
+// --[ License ] --------------------------------------------------------------
+//
+//     This library is free software; you can redistribute it and/or modify
+//     it under the terms of the GNU Lesser General Public License as
+//     published by the Free Software Foundation; either version 2.1 of the
+//     License, or (at your option) any later version.
+//
+//     This library is distributed in the hope that it will be useful, but
+//     WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//     Lesser General Public License for more details.
+//
+//     You should have received a copy of the GNU Lesser General Public
+//     License along with this library; if not, see .
+//
+// ----------------------------------------------------------------------------
+// Copyright © 2011-2018 Natalia Portillo
+// ****************************************************************************/
+
+using System;
+
+namespace DiscImageChef.DiscImages
+{
+    /// 
+    ///     Track (as partitioning element) types.
+    /// 
+    public enum TrackType
+    {
+        /// Audio track
+        Audio,
+        /// Data track (not any of the below defined ones)
+        Data,
+        /// Data track, compact disc mode 1
+        CdMode1,
+        /// Data track, compact disc mode 2, formless
+        CdMode2Formless,
+        /// Data track, compact disc mode 2, form 1
+        CdMode2Form1,
+        /// Data track, compact disc mode 2, form 2
+        CdMode2Form2
+    }
+
+    /// 
+    ///     Type of subchannel in track
+    /// 
+    public enum TrackSubchannelType
+    {
+        /// 
+        ///     Track does not has subchannel dumped, or it's not a CD
+        /// 
+        None,
+        /// 
+        ///     Subchannel is packed and error corrected
+        /// 
+        Packed,
+        /// 
+        ///     Subchannel is interleaved
+        /// 
+        Raw,
+        /// 
+        ///     Subchannel is packed and comes interleaved with main channel in same file
+        /// 
+        PackedInterleaved,
+        /// 
+        ///     Subchannel is interleaved and comes interleaved with main channel in same file
+        /// 
+        RawInterleaved,
+        /// 
+        ///     Only Q subchannel is stored as 16 bytes
+        /// 
+        Q16,
+        /// 
+        ///     Only Q subchannel is stored as 16 bytes and comes interleaved with main channel in same file
+        /// 
+        Q16Interleaved
+    }
+
+    /// 
+    ///     Metadata present for each sector (aka, "tag").
+    /// 
+    public enum SectorTagType
+    {
+        /// Apple's GCR sector tags, 12 bytes
+        AppleSectorTag,
+        /// Sync frame from CD sector, 12 bytes
+        CdSectorSync,
+        /// CD sector header, 4 bytes
+        CdSectorHeader,
+        /// CD mode 2 sector subheader
+        CdSectorSubHeader,
+        /// CD sector EDC, 4 bytes
+        CdSectorEdc,
+        /// CD sector ECC P, 172 bytes
+        CdSectorEccP,
+        /// CD sector ECC Q, 104 bytes
+        CdSectorEccQ,
+        /// CD sector ECC (P and Q), 276 bytes
+        CdSectorEcc,
+        /// CD sector subchannel, 96 bytes
+        CdSectorSubchannel,
+        /// CD track ISRC, string, 12 bytes
+        CdTrackIsrc,
+        /// CD track text, string, 13 bytes
+        CdTrackText,
+        /// CD track flags, 1 byte
+        CdTrackFlags,
+        /// DVD sector copyright information
+        DvdCmi,
+        /// Floppy address mark (contents depend on underlying floppy format)
+        FloppyAddressMark
+    }
+
+    /// 
+    ///     Metadata present for each media.
+    /// 
+    public enum MediaTagType
+    {
+        /// CD table of contents
+        CD_TOC,
+        /// CD session information
+        CD_SessionInfo,
+        /// CD full table of contents
+        CD_FullTOC,
+        /// CD PMA
+        CD_PMA,
+        /// CD Adress-Time-In-Pregroove
+        CD_ATIP,
+        /// CD-Text
+        CD_TEXT,
+        /// CD Media Catalogue Number
+        CD_MCN,
+        /// DVD/HD DVD Physical Format Information
+        DVD_PFI,
+        /// DVD Lead-in Copyright Management Information
+        DVD_CMI,
+        /// DVD disc key
+        DVD_DiscKey,
+        /// DVD/HD DVD Burst Cutting Area
+        DVD_BCA,
+        /// DVD/HD DVD Lead-in Disc Manufacturer Information
+        DVD_DMI,
+        /// Media identifier
+        DVD_MediaIdentifier,
+        /// Media key block
+        DVD_MKB,
+        /// DVD-RAM/HD DVD-RAM DDS information
+        DVDRAM_DDS,
+        /// DVD-RAM/HD DVD-RAM Medium status
+        DVDRAM_MediumStatus,
+        /// DVD-RAM/HD DVD-RAM Spare area information
+        DVDRAM_SpareArea,
+        /// DVD-R/-RW/HD DVD-R RMD in last border-out
+        DVDR_RMD,
+        /// Pre-recorded information from DVD-R/-RW lead-in
+        DVDR_PreRecordedInfo,
+        /// DVD-R/-RW/HD DVD-R media identifier
+        DVDR_MediaIdentifier,
+        /// DVD-R/-RW/HD DVD-R physical format information
+        DVDR_PFI,
+        /// ADIP information
+        DVD_ADIP,
+        /// HD DVD Lead-in copyright protection information
+        HDDVD_CPI,
+        /// HD DVD-R Medium Status
+        HDDVD_MediumStatus,
+        /// DVD+/-R DL Layer capacity
+        DVDDL_LayerCapacity,
+        /// DVD-R DL Middle Zone start address
+        DVDDL_MiddleZoneAddress,
+        /// DVD-R DL Jump Interval Size
+        DVDDL_JumpIntervalSize,
+        /// DVD-R DL Start LBA of the manual layer jump
+        DVDDL_ManualLayerJumpLBA,
+        /// Blu-ray Disc Information
+        BD_DI,
+        /// Blu-ray Burst Cutting Area
+        BD_BCA,
+        /// Blu-ray Disc Definition Structure
+        BD_DDS,
+        /// Blu-ray Cartridge Status
+        BD_CartridgeStatus,
+        /// Blu-ray Status of Spare Area
+        BD_SpareArea,
+        /// AACS volume identifier
+        AACS_VolumeIdentifier,
+        /// AACS pre-recorded media serial number
+        AACS_SerialNumber,
+        /// AACS media identifier
+        AACS_MediaIdentifier,
+        /// Lead-in AACS media key block
+        AACS_MKB,
+        /// AACS data keys
+        AACS_DataKeys,
+        /// LBA extents flagged for bus encryption by AACS
+        AACS_LBAExtents,
+        /// CPRM media key block in Lead-in
+        AACS_CPRM_MKB,
+        /// Recognized layer formats in hybrid discs
+        Hybrid_RecognizedLayers,
+        /// Disc write protection status
+        MMC_WriteProtection,
+        /// Disc standard information
+        MMC_DiscInformation,
+        /// Disc track resources information
+        MMC_TrackResourcesInformation,
+        /// BD-R Pseudo-overwrite information
+        MMC_POWResourcesInformation,
+        /// SCSI INQUIRY response
+        SCSI_INQUIRY,
+        /// SCSI MODE PAGE 2Ah
+        SCSI_MODEPAGE_2A,
+        /// ATA IDENTIFY DEVICE response
+        ATA_IDENTIFY,
+        /// ATA IDENTIFY PACKET DEVICE response
+        ATAPI_IDENTIFY,
+        /// PCMCIA/CardBus Card Information Structure
+        PCMCIA_CIS,
+        /// SecureDigital CID
+        SD_CID,
+        /// SecureDigital CSD
+        SD_CSD,
+        /// SecureDigital SCR
+        SD_SCR,
+        /// SecureDigital OCR
+        SD_OCR,
+        /// MultiMediaCard CID
+        MMC_CID,
+        /// MultiMediaCard CSD
+        MMC_CSD,
+        /// MultiMediaCard OCR
+        MMC_OCR,
+        /// MultiMediaCard Extended CSD
+        MMC_ExtendedCSD,
+        /// Xbox Security Sector
+        Xbox_SecuritySector,
+        /// 
+        ///     On floppy disks, data in last cylinder usually in a different format that contains duplication or
+        ///     manufacturing information
+        /// 
+        Floppy_LeadOut
+    }
+
+    /// 
+    ///     Enumeration of media types defined in CICM metadata
+    /// 
+    public enum XmlMediaType
+    {
+        /// 
+        ///     Purely optical discs
+        /// 
+        OpticalDisc,
+        /// 
+        ///     Media that is physically block-based or abstracted like that
+        /// 
+        BlockMedia,
+        /// 
+        ///     Media that can be accessed by-byte or by-bit, like chips
+        /// 
+        LinearMedia,
+        /// 
+        ///     Media that can only store data when it is modulated to audio
+        /// 
+        AudioMedia
+    }
+
+    ///  CD flags bitmask
+    [Flags]
+    public enum CdFlags : byte
+    {
+        /// Track is quadraphonic.
+        FourChannel = 0x20,
+        /// Track is non-audio (data).
+        DataTrack = 0x10,
+        /// Track is copy protected.
+        CopyPrevent = 0x08,
+        /// Track has pre-emphasis.
+        PreEmphasis = 0x04
+    }
+}
\ No newline at end of file
diff --git a/DiscImageChef.DiscImages/Exceptions.cs b/DiscImageChef.DiscImages/Exceptions.cs
new file mode 100644
index 00000000..536f7fa1
--- /dev/null
+++ b/DiscImageChef.DiscImages/Exceptions.cs
@@ -0,0 +1,188 @@
+// /***************************************************************************
+// The Disc Image Chef
+// ----------------------------------------------------------------------------
+//
+// Filename       : Enums.cs
+// Author(s)      : Natalia Portillo 
+//
+// Component      : Disc image plugins.
+//
+// --[ Description ] ----------------------------------------------------------
+//
+//     Defines exceptions to be thrown by disc image plugins.
+//
+// --[ License ] --------------------------------------------------------------
+//
+//     This library is free software; you can redistribute it and/or modify
+//     it under the terms of the GNU Lesser General Public License as
+//     published by the Free Software Foundation; either version 2.1 of the
+//     License, or (at your option) any later version.
+//
+//     This library is distributed in the hope that it will be useful, but
+//     WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//     Lesser General Public License for more details.
+//
+//     You should have received a copy of the GNU Lesser General Public
+//     License along with this library; if not, see .
+//
+// ----------------------------------------------------------------------------
+// Copyright © 2011-2018 Natalia Portillo
+// ****************************************************************************/
+
+using System;
+using System.Runtime.Serialization;
+
+namespace DiscImageChef.DiscImages
+{
+    /// 
+    ///     Feature is supported by image but not implemented yet.
+    /// 
+    [Serializable]
+    public class FeatureSupportedButNotImplementedImageException : Exception
+    {
+        /// 
+        ///     Feature is supported by image but not implemented yet.
+        /// 
+        /// Message.
+        /// Inner.
+        public FeatureSupportedButNotImplementedImageException(string message, Exception inner) :
+            base(message, inner) { }
+
+        /// 
+        ///     Feature is supported by image but not implemented yet.
+        /// 
+        /// Message.
+        public FeatureSupportedButNotImplementedImageException(string message) : base(message) { }
+
+        /// 
+        ///     Feature is supported by image but not implemented yet.
+        /// 
+        /// Info.
+        /// Context.
+        protected FeatureSupportedButNotImplementedImageException(SerializationInfo info, StreamingContext context)
+        {
+            if(info == null) throw new ArgumentNullException(nameof(info));
+        }
+    }
+
+    /// 
+    ///     Feature is not supported by image.
+    /// 
+    [Serializable]
+    public class FeatureUnsupportedImageException : Exception
+    {
+        /// 
+        ///     Feature is not supported by image.
+        /// 
+        /// Message.
+        /// Inner.
+        public FeatureUnsupportedImageException(string message, Exception inner) : base(message, inner) { }
+
+        /// 
+        ///     Feature is not supported by image.
+        /// 
+        /// Message.
+        public FeatureUnsupportedImageException(string message) : base(message) { }
+
+        /// 
+        ///     Feature is not supported by image.
+        /// 
+        /// Info.
+        /// Context.
+        protected FeatureUnsupportedImageException(SerializationInfo info, StreamingContext context)
+        {
+            if(info == null) throw new ArgumentNullException(nameof(info));
+        }
+    }
+
+    /// 
+    ///     Feature is supported by image but not present on it.
+    /// 
+    [Serializable]
+    public class FeatureNotPresentImageException : Exception
+    {
+        /// 
+        ///     Feature is supported by image but not present on it.
+        /// 
+        /// Message.
+        /// Inner.
+        public FeatureNotPresentImageException(string message, Exception inner) : base(message, inner) { }
+
+        /// 
+        ///     Feature is supported by image but not present on it.
+        /// 
+        /// Message.
+        public FeatureNotPresentImageException(string message) : base(message) { }
+
+        /// 
+        ///     Feature is supported by image but not present on it.
+        /// 
+        /// Info.
+        /// Context.
+        protected FeatureNotPresentImageException(SerializationInfo info, StreamingContext context)
+        {
+            if(info == null) throw new ArgumentNullException(nameof(info));
+        }
+    }
+
+    /// 
+    ///     Feature is supported by image but not by the disc it represents.
+    /// 
+    [Serializable]
+    public class FeaturedNotSupportedByDiscImageException : Exception
+    {
+        /// 
+        ///     Feature is supported by image but not by the disc it represents.
+        /// 
+        /// Message.
+        /// Inner.
+        public FeaturedNotSupportedByDiscImageException(string message, Exception inner) : base(message, inner) { }
+
+        /// 
+        ///     Feature is supported by image but not by the disc it represents.
+        /// 
+        /// Message.
+        public FeaturedNotSupportedByDiscImageException(string message) : base(message) { }
+
+        /// 
+        ///     Feature is supported by image but not by the disc it represents.
+        /// 
+        /// Info.
+        /// Context.
+        protected FeaturedNotSupportedByDiscImageException(SerializationInfo info, StreamingContext context)
+        {
+            if(info == null) throw new ArgumentNullException(nameof(info));
+        }
+    }
+
+    /// 
+    ///     Corrupt, incorrect or unhandled feature found on image
+    /// 
+    [Serializable]
+    public class ImageNotSupportedException : Exception
+    {
+        /// 
+        ///     Corrupt, incorrect or unhandled feature found on image
+        /// 
+        /// Message.
+        /// Inner.
+        public ImageNotSupportedException(string message, Exception inner) : base(message, inner) { }
+
+        /// 
+        ///     Corrupt, incorrect or unhandled feature found on image
+        /// 
+        /// Message.
+        public ImageNotSupportedException(string message) : base(message) { }
+
+        /// 
+        ///     Corrupt, incorrect or unhandled feature found on image
+        /// 
+        /// Info.
+        /// Context.
+        protected ImageNotSupportedException(SerializationInfo info, StreamingContext context)
+        {
+            if(info == null) throw new ArgumentNullException(nameof(info));
+        }
+    }
+}
\ No newline at end of file
diff --git a/DiscImageChef.DiscImages/GDI.cs b/DiscImageChef.DiscImages/GDI.cs
index d5cbe665..ddedb9ba 100644
--- a/DiscImageChef.DiscImages/GDI.cs
+++ b/DiscImageChef.DiscImages/GDI.cs
@@ -44,7 +44,7 @@ namespace DiscImageChef.DiscImages
 {
     // TODO: There seems no be no clear definition on how to treat pregaps that are not included in the file, so this is just appending it to start of track
     // TODO: This format doesn't support to specify pregaps that are included in the file (like Redump ones)
-    public class Gdi : ImagePlugin
+    public class Gdi : IMediaImage
     {
         const string REGEX_TRACK =
             @"\s?(?\d+)\s+(?\d+)\s(?\d)\s(?2352|2048)\s(?.+)\s(?\d+)$";
@@ -52,6 +52,7 @@ namespace DiscImageChef.DiscImages
         ulong densitySeparationSectors;
         GdiDisc discimage;
         StreamReader gdiStream;
+        ImageInfo imageInfo;
         Stream imageStream;
         /// Dictionary, index is track #, value is track number, or 0 if a TOC
         Dictionary offsetmap;
@@ -59,9 +60,7 @@ namespace DiscImageChef.DiscImages
 
         public Gdi()
         {
-            Name = "Dreamcast GDI image";
-            PluginUuid = new Guid("281ECBF2-D2A7-414C-8497-1A33F6DCB2DD");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -83,11 +82,15 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "Dreamcast GDI image";
+        public virtual string Name => "Dreamcast GDI image";
+        public virtual Guid Id => new Guid("281ECBF2-D2A7-414C-8497-1A33F6DCB2DD");
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Partitions => partitions;
+        public virtual string ImageFormat => "Dreamcast GDI image";
 
-        public override List Tracks
+        public virtual List Partitions => partitions;
+
+        public virtual List Tracks
         {
             get
             {
@@ -122,10 +125,10 @@ namespace DiscImageChef.DiscImages
             }
         }
 
-        public override List Sessions => discimage.Sessions;
+        public virtual List Sessions => discimage.Sessions;
 
         // Due to .gdi format, this method must parse whole file, ignoring errors (those will be thrown by OpenImage()).
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             try
             {
@@ -187,7 +190,7 @@ namespace DiscImageChef.DiscImages
             }
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             if(imageFilter == null) return false;
 
@@ -389,35 +392,35 @@ namespace DiscImageChef.DiscImages
                     partitions.Add(partition);
                 }
 
-                foreach(GdiTrack track in discimage.Tracks) ImageInfo.ImageSize += track.Bps * track.Sectors;
-                foreach(GdiTrack track in discimage.Tracks) ImageInfo.Sectors += track.Sectors;
+                foreach(GdiTrack track in discimage.Tracks) imageInfo.ImageSize += track.Bps * track.Sectors;
+                foreach(GdiTrack track in discimage.Tracks) imageInfo.Sectors += track.Sectors;
 
-                ImageInfo.Sectors += densitySeparationSectors;
+                imageInfo.Sectors += densitySeparationSectors;
 
-                ImageInfo.SectorSize = 2352; // All others
+                imageInfo.SectorSize = 2352; // All others
 
                 foreach(GdiTrack unused in
                     discimage.Tracks.Where(track => (track.Flags & 0x40) == 0x40 && track.Bps == 2352))
                 {
-                    ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync);
-                    ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader);
-                    ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader);
-                    ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc);
-                    ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP);
-                    ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ);
-                    ImageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc);
+                    imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync);
+                    imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader);
+                    imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader);
+                    imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc);
+                    imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP);
+                    imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ);
+                    imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc);
                 }
 
-                ImageInfo.CreationTime = imageFilter.GetCreationTime();
-                ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+                imageInfo.CreationTime = imageFilter.GetCreationTime();
+                imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
 
-                ImageInfo.MediaType = discimage.Disktype;
+                imageInfo.MediaType = discimage.Disktype;
 
-                ImageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackFlags);
+                imageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackFlags);
 
-                ImageInfo.XmlMediaType = XmlMediaType.OpticalDisc;
+                imageInfo.XmlMediaType = XmlMediaType.OpticalDisc;
 
-                DicConsole.VerboseWriteLine("GDI image describes a disc of type {0}", ImageInfo.MediaType);
+                DicConsole.VerboseWriteLine("GDI image describes a disc of type {0}", imageInfo.MediaType);
 
                 return true;
             }
@@ -430,32 +433,32 @@ namespace DiscImageChef.DiscImages
             }
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new FeatureSupportedButNotImplementedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
             return ReadSectors(sectorAddress, 1);
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             return ReadSectorsTag(sectorAddress, 1, tag);
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             return ReadSectors(sectorAddress, 1, track);
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             return ReadSectorsTag(sectorAddress, 1, track, tag);
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
             foreach(KeyValuePair kvp in from kvp in offsetmap
                                                      where sectorAddress >= kvp.Value
@@ -472,7 +475,7 @@ namespace DiscImageChef.DiscImages
             throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             foreach(KeyValuePair kvp in from kvp in offsetmap
                                                      where sectorAddress >= kvp.Value
@@ -489,7 +492,7 @@ namespace DiscImageChef.DiscImages
             throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             if(track == 0)
             {
@@ -589,7 +592,7 @@ namespace DiscImageChef.DiscImages
             return buffer;
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             if(track == 0)
             {
@@ -745,17 +748,17 @@ namespace DiscImageChef.DiscImages
             return buffer;
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             return ReadSectorsLong(sectorAddress, 1);
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             return ReadSectorsLong(sectorAddress, 1, track);
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             foreach(KeyValuePair kvp in from kvp in offsetmap
                                                      where sectorAddress >= kvp.Value
@@ -768,7 +771,7 @@ namespace DiscImageChef.DiscImages
             throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             if(track == 0)
             {
@@ -868,14 +871,14 @@ namespace DiscImageChef.DiscImages
             return buffer;
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             if(discimage.Sessions.Contains(session)) return GetSessionTracks(session.SessionSequence);
 
             throw new ImageNotSupportedException("Session does not exist in disc image");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             List tracks = new List();
             bool expectedDensity;
@@ -920,19 +923,19 @@ namespace DiscImageChef.DiscImages
             return tracks;
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             byte[] buffer = ReadSectorLong(sectorAddress);
             return CdChecksums.CheckCdSector(buffer);
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             byte[] buffer = ReadSectorLong(sectorAddress, track);
             return CdChecksums.CheckCdSector(buffer);
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             byte[] buffer = ReadSectorsLong(sectorAddress, length);
@@ -962,7 +965,7 @@ namespace DiscImageChef.DiscImages
             return failingLbas.Count <= 0;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             byte[] buffer = ReadSectorsLong(sectorAddress, length, track);
@@ -992,7 +995,7 @@ namespace DiscImageChef.DiscImages
             return failingLbas.Count <= 0;
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return null;
         }
@@ -1002,7 +1005,7 @@ namespace DiscImageChef.DiscImages
             /// Track #
             public uint Sequence;
             /// Track filter
-            public Filter Trackfilter;
+            public IFilter Trackfilter;
             /// Track file
             public string Trackfile;
             /// Track byte offset in file
diff --git a/DiscImageChef.DiscImages/HDCopy.cs b/DiscImageChef.DiscImages/HDCopy.cs
index 44f26e32..85c1205f 100644
--- a/DiscImageChef.DiscImages/HDCopy.cs
+++ b/DiscImageChef.DiscImages/HDCopy.cs
@@ -74,7 +74,7 @@ using DiscImageChef.Filters;
 
 namespace DiscImageChef.DiscImages
 {
-    public class HdCopy : ImagePlugin
+    public class HdCopy : IMediaImage
     {
         readonly MediaTypeTableEntry[] mediaTypes =
         {
@@ -95,7 +95,8 @@ namespace DiscImageChef.DiscImages
         /// 
         ///     The ImageFilter we're reading from, after the file has been opened
         /// 
-        Filter hdcpImageFilter;
+        IFilter hdcpImageFilter;
+        ImageInfo imageInfo;
 
         /// 
         ///     Every track that has been read is cached here
@@ -109,9 +110,7 @@ namespace DiscImageChef.DiscImages
 
         public HdCopy()
         {
-            Name = "HD-Copy disk image";
-            PluginUuid = new Guid("8D57483F-71A5-42EC-9B87-66AEC439C792");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -136,17 +135,22 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "HD-Copy image";
-        public override List Partitions =>
+        public virtual ImageInfo Info => imageInfo;
+
+        public virtual string Name => "HD-Copy disk image";
+        public virtual Guid Id => new Guid("8D57483F-71A5-42EC-9B87-66AEC439C792");
+
+        public virtual string ImageFormat => "HD-Copy image";
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Sessions =>
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -180,7 +184,7 @@ namespace DiscImageChef.DiscImages
             return true;
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             long currentOffset;
 
@@ -198,28 +202,28 @@ namespace DiscImageChef.DiscImages
                                       "Detected HD-Copy image with {0} tracks and {1} sectors per track.",
                                       fheader.lastCylinder + 1, fheader.sectorsPerTrack);
 
-            ImageInfo.Cylinders = (uint)fheader.lastCylinder + 1;
-            ImageInfo.SectorsPerTrack = fheader.sectorsPerTrack;
-            ImageInfo.SectorSize = 512; // only 512 bytes per sector supported
-            ImageInfo.Heads = 2; // only 2-sided floppies are supported
-            ImageInfo.Sectors = 2 * ImageInfo.Cylinders * ImageInfo.SectorsPerTrack;
-            ImageInfo.ImageSize = ImageInfo.Sectors * ImageInfo.SectorSize;
+            imageInfo.Cylinders = (uint)fheader.lastCylinder + 1;
+            imageInfo.SectorsPerTrack = fheader.sectorsPerTrack;
+            imageInfo.SectorSize = 512; // only 512 bytes per sector supported
+            imageInfo.Heads = 2; // only 2-sided floppies are supported
+            imageInfo.Sectors = 2 * imageInfo.Cylinders * imageInfo.SectorsPerTrack;
+            imageInfo.ImageSize = imageInfo.Sectors * imageInfo.SectorSize;
 
-            ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
 
-            ImageInfo.CreationTime = imageFilter.GetCreationTime();
-            ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
-            ImageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
-            ImageInfo.MediaType =
+            imageInfo.CreationTime = imageFilter.GetCreationTime();
+            imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+            imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
+            imageInfo.MediaType =
                 (from ent in mediaTypes
-                 where ent.Tracks == ImageInfo.Cylinders && ent.SectorsPerTrack == ImageInfo.SectorsPerTrack
+                 where ent.Tracks == imageInfo.Cylinders && ent.SectorsPerTrack == imageInfo.SectorsPerTrack
                  select ent.MediaType).FirstOrDefault();
 
             // the start offset of the track data
             currentOffset = 2 + 2 * 82;
 
             // build table of track offsets
-            for(int i = 0; i < ImageInfo.Cylinders * 2; i++)
+            for(int i = 0; i < imageInfo.Cylinders * 2; i++)
                 if(fheader.trackMap[i] == 0) trackOffset[i] = -1;
                 else
                 {
@@ -254,7 +258,7 @@ namespace DiscImageChef.DiscImages
 
         void ReadTrackIntoCache(Stream stream, int tracknum)
         {
-            byte[] trackData = new byte[ImageInfo.SectorSize * ImageInfo.SectorsPerTrack];
+            byte[] trackData = new byte[imageInfo.SectorSize * imageInfo.SectorsPerTrack];
             byte[] blkHeader = new byte[3];
             byte escapeByte;
             short compressedLength;
@@ -288,142 +292,142 @@ namespace DiscImageChef.DiscImages
                 else trackData[dIndex++] = cBuffer[sIndex++];
 
             // check that the number of bytes decompressed matches a whole track
-            if(dIndex != ImageInfo.SectorSize * ImageInfo.SectorsPerTrack)
+            if(dIndex != imageInfo.SectorSize * imageInfo.SectorsPerTrack)
                 throw new InvalidDataException("Track decompression yielded incomplete data");
 
             // store track in cache
             trackCache[tracknum] = trackData;
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
-            int trackNum = (int)(sectorAddress / ImageInfo.SectorsPerTrack);
-            int sectorOffset = (int)(sectorAddress % (ImageInfo.SectorsPerTrack * ImageInfo.SectorSize));
+            int trackNum = (int)(sectorAddress / imageInfo.SectorsPerTrack);
+            int sectorOffset = (int)(sectorAddress % (imageInfo.SectorsPerTrack * imageInfo.SectorSize));
 
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
 
-            if(trackNum > 2 * ImageInfo.Cylinders)
+            if(trackNum > 2 * imageInfo.Cylinders)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
 
-            byte[] result = new byte[ImageInfo.SectorSize];
-            if(trackOffset[trackNum] == -1) Array.Clear(result, 0, (int)ImageInfo.SectorSize);
+            byte[] result = new byte[imageInfo.SectorSize];
+            if(trackOffset[trackNum] == -1) Array.Clear(result, 0, (int)imageInfo.SectorSize);
             else
             {
                 // track is present in file, make sure it has been loaded
                 if(!trackCache.ContainsKey(trackNum)) ReadTrackIntoCache(hdcpImageFilter.GetDataForkStream(), trackNum);
 
-                Array.Copy(trackCache[trackNum], sectorOffset, result, 0, ImageInfo.SectorSize);
+                Array.Copy(trackCache[trackNum], sectorOffset, result, 0, imageInfo.SectorSize);
             }
 
             return result;
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
-            byte[] result = new byte[length * ImageInfo.SectorSize];
+            byte[] result = new byte[length * imageInfo.SectorSize];
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
             for(int i = 0; i < length; i++)
-                ReadSector(sectorAddress + (ulong)i).CopyTo(result, i * ImageInfo.SectorSize);
+                ReadSector(sectorAddress + (ulong)i).CopyTo(result, i * imageInfo.SectorSize);
 
             return result;
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             return null;
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
             unknownLbas = new List();
-            for(ulong i = 0; i < ImageInfo.Sectors; i++) unknownLbas.Add(i);
+            for(ulong i = 0; i < imageInfo.Sectors; i++) unknownLbas.Add(i);
 
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return null;
         }
diff --git a/DiscImageChef.DiscImages/IMD.cs b/DiscImageChef.DiscImages/IMD.cs
index 9f8060d4..37e66543 100644
--- a/DiscImageChef.DiscImages/IMD.cs
+++ b/DiscImageChef.DiscImages/IMD.cs
@@ -41,7 +41,7 @@ using DiscImageChef.Filters;
 
 namespace DiscImageChef.DiscImages
 {
-    public class Imd : ImagePlugin
+    public class Imd : IMediaImage
     {
         const byte SECTOR_CYLINDER_MAP_MASK = 0x80;
         const byte SECTOR_HEAD_MAP_MASK = 0x40;
@@ -49,14 +49,13 @@ namespace DiscImageChef.DiscImages
         const string REGEX_HEADER =
                 @"IMD (?\d.\d+):\s+(?\d+)\/\s*(?\d+)\/(?\d+)\s+(?\d+):(?\d+):(?\d+)\r\n"
             ;
+        ImageInfo imageInfo;
 
         List sectorsData;
 
         public Imd()
         {
-            Name = "Dunfield's IMD";
-            PluginUuid = new Guid("0D67162E-38A3-407D-9B1A-CF40080A48CB");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -81,18 +80,22 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "IMageDisk";
+        public virtual string Name => "Dunfield's IMD";
+        public virtual Guid Id => new Guid("0D67162E-38A3-407D-9B1A-CF40080A48CB");
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Partitions =>
+        public virtual string ImageFormat => "IMageDisk";
+
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Sessions =>
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -107,7 +110,7 @@ namespace DiscImageChef.DiscImages
             return hm.Success;
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -122,12 +125,12 @@ namespace DiscImageChef.DiscImages
                 cmt.WriteByte(b);
             }
 
-            ImageInfo.Comments = StringHandlers.CToString(cmt.ToArray());
+            imageInfo.Comments = StringHandlers.CToString(cmt.ToArray());
             sectorsData = new List();
 
             byte currentCylinder = 0;
-            ImageInfo.Cylinders = 1;
-            ImageInfo.Heads = 1;
+            imageInfo.Cylinders = 1;
+            imageInfo.Heads = 1;
             ulong currentLba = 0;
 
             TransferRate mode = TransferRate.TwoHundred;
@@ -147,10 +150,10 @@ namespace DiscImageChef.DiscImages
                 if(cylinder != currentCylinder)
                 {
                     currentCylinder = cylinder;
-                    ImageInfo.Cylinders++;
+                    imageInfo.Cylinders++;
                 }
 
-                if((head & 1) == 1) ImageInfo.Heads = 2;
+                if((head & 1) == 1) imageInfo.Heads = 2;
 
                 stream.Read(idmap, 0, idmap.Length);
                 if((head & SECTOR_CYLINDER_MAP_MASK) == SECTOR_CYLINDER_MAP_MASK) stream.Read(cylmap, 0, cylmap.Length);
@@ -163,7 +166,7 @@ namespace DiscImageChef.DiscImages
                 }
                 else for(int i = 0; i < spt; i++) bps[i] = (ushort)(128 << n);
 
-                if(spt > ImageInfo.SectorsPerTrack) ImageInfo.SectorsPerTrack = spt;
+                if(spt > imageInfo.SectorsPerTrack) imageInfo.SectorsPerTrack = spt;
 
                 SortedDictionary track = new SortedDictionary();
 
@@ -173,7 +176,7 @@ namespace DiscImageChef.DiscImages
                     byte[] data = new byte[bps[i]];
 
                     // TODO; Handle disks with different bps in track 0
-                    if(bps[i] > ImageInfo.SectorSize) ImageInfo.SectorSize = bps[i];
+                    if(bps[i] > imageInfo.SectorSize) imageInfo.SectorSize = bps[i];
 
                     switch(type)
                     {
@@ -186,7 +189,7 @@ namespace DiscImageChef.DiscImages
                         case SectorType.DeletedError:
                             stream.Read(data, 0, data.Length);
                             if(!track.ContainsKey(idmap[i])) track.Add(idmap[i], data);
-                            ImageInfo.ImageSize += (ulong)data.Length;
+                            imageInfo.ImageSize += (ulong)data.Length;
                             break;
                         case SectorType.Compressed:
                         case SectorType.CompressedDeleted:
@@ -207,109 +210,109 @@ namespace DiscImageChef.DiscImages
                 }
             }
 
-            ImageInfo.Application = "IMD";
+            imageInfo.Application = "IMD";
             // TODO: The header is the date of dump or the date of the application compilation?
-            ImageInfo.CreationTime = imageFilter.GetCreationTime();
-            ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
-            ImageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
-            ImageInfo.Comments = StringHandlers.CToString(cmt.ToArray());
-            ImageInfo.Sectors = currentLba;
-            ImageInfo.MediaType = MediaType.Unknown;
+            imageInfo.CreationTime = imageFilter.GetCreationTime();
+            imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+            imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
+            imageInfo.Comments = StringHandlers.CToString(cmt.ToArray());
+            imageInfo.Sectors = currentLba;
+            imageInfo.MediaType = MediaType.Unknown;
 
             switch(mode)
             {
                 case TransferRate.TwoHundred:
                 case TransferRate.ThreeHundred:
-                    if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 40 && ImageInfo.SectorsPerTrack == 10 &&
-                       ImageInfo.SectorSize == 256) ImageInfo.MediaType = MediaType.ACORN_525_SS_SD_40;
-                    else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 10 &&
-                            ImageInfo.SectorSize == 256) ImageInfo.MediaType = MediaType.ACORN_525_SS_SD_80;
-                    else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 40 && ImageInfo.SectorsPerTrack == 18 &&
-                            ImageInfo.SectorSize == 128) ImageInfo.MediaType = MediaType.ATARI_525_SD;
+                    if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 10 &&
+                       imageInfo.SectorSize == 256) imageInfo.MediaType = MediaType.ACORN_525_SS_SD_40;
+                    else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 10 &&
+                            imageInfo.SectorSize == 256) imageInfo.MediaType = MediaType.ACORN_525_SS_SD_80;
+                    else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 18 &&
+                            imageInfo.SectorSize == 128) imageInfo.MediaType = MediaType.ATARI_525_SD;
                     break;
                 case TransferRate.FiveHundred:
-                    if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 32 && ImageInfo.SectorsPerTrack == 8 &&
-                       ImageInfo.SectorSize == 319) ImageInfo.MediaType = MediaType.IBM23FD;
-                    else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 73 && ImageInfo.SectorsPerTrack == 26 &&
-                            ImageInfo.SectorSize == 128) ImageInfo.MediaType = MediaType.IBM23FD;
-                    else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 77 && ImageInfo.SectorsPerTrack == 26 &&
-                            ImageInfo.SectorSize == 128) ImageInfo.MediaType = MediaType.NEC_8_SD;
+                    if(imageInfo.Heads == 1 && imageInfo.Cylinders == 32 && imageInfo.SectorsPerTrack == 8 &&
+                       imageInfo.SectorSize == 319) imageInfo.MediaType = MediaType.IBM23FD;
+                    else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 73 && imageInfo.SectorsPerTrack == 26 &&
+                            imageInfo.SectorSize == 128) imageInfo.MediaType = MediaType.IBM23FD;
+                    else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 77 && imageInfo.SectorsPerTrack == 26 &&
+                            imageInfo.SectorSize == 128) imageInfo.MediaType = MediaType.NEC_8_SD;
                     break;
                 case TransferRate.TwoHundredMfm:
                 case TransferRate.ThreeHundredMfm:
-                    if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 40 && ImageInfo.SectorsPerTrack == 8 &&
-                       ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DOS_525_SS_DD_8;
-                    else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 40 && ImageInfo.SectorsPerTrack == 9 &&
-                            ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DOS_525_SS_DD_9;
-                    else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 40 && ImageInfo.SectorsPerTrack == 8 &&
-                            ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DOS_525_DS_DD_8;
-                    else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 40 && ImageInfo.SectorsPerTrack == 9 &&
-                            ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DOS_525_DS_DD_9;
-                    else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 40 && ImageInfo.SectorsPerTrack == 18 &&
-                            ImageInfo.SectorSize == 128) ImageInfo.MediaType = MediaType.ATARI_525_SD;
-                    else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 40 && ImageInfo.SectorsPerTrack == 26 &&
-                            ImageInfo.SectorSize == 128) ImageInfo.MediaType = MediaType.ATARI_525_ED;
-                    else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 40 && ImageInfo.SectorsPerTrack == 18 &&
-                            ImageInfo.SectorSize == 256) ImageInfo.MediaType = MediaType.ATARI_525_DD;
-                    else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 40 && ImageInfo.SectorsPerTrack == 16 &&
-                            ImageInfo.SectorSize == 256) ImageInfo.MediaType = MediaType.ACORN_525_SS_DD_40;
-                    else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 16 &&
-                            ImageInfo.SectorSize == 256) ImageInfo.MediaType = MediaType.ACORN_525_SS_DD_80;
-                    else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 40 && ImageInfo.SectorsPerTrack == 18 &&
-                            ImageInfo.SectorSize == 256) ImageInfo.MediaType = MediaType.ATARI_525_DD;
-                    else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 10 &&
-                            ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.RX50;
-                    else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 9 &&
-                            ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DOS_35_DS_DD_9;
-                    else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 8 &&
-                            ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DOS_35_DS_DD_8;
-                    if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 9 &&
-                       ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DOS_35_SS_DD_9;
-                    else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 8 &&
-                            ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DOS_35_SS_DD_8;
-                    else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 5 &&
-                            ImageInfo.SectorSize == 1024) ImageInfo.MediaType = MediaType.ACORN_35_DS_DD;
-                    else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 82 && ImageInfo.SectorsPerTrack == 10 &&
-                            ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.FDFORMAT_35_DD;
-                    else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 70 && ImageInfo.SectorsPerTrack == 9 &&
-                            ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.Apricot_35;
+                    if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 8 &&
+                       imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_SS_DD_8;
+                    else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 9 &&
+                            imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_SS_DD_9;
+                    else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 8 &&
+                            imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_DS_DD_8;
+                    else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 9 &&
+                            imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_DS_DD_9;
+                    else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 18 &&
+                            imageInfo.SectorSize == 128) imageInfo.MediaType = MediaType.ATARI_525_SD;
+                    else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 26 &&
+                            imageInfo.SectorSize == 128) imageInfo.MediaType = MediaType.ATARI_525_ED;
+                    else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 18 &&
+                            imageInfo.SectorSize == 256) imageInfo.MediaType = MediaType.ATARI_525_DD;
+                    else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 16 &&
+                            imageInfo.SectorSize == 256) imageInfo.MediaType = MediaType.ACORN_525_SS_DD_40;
+                    else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 16 &&
+                            imageInfo.SectorSize == 256) imageInfo.MediaType = MediaType.ACORN_525_SS_DD_80;
+                    else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 18 &&
+                            imageInfo.SectorSize == 256) imageInfo.MediaType = MediaType.ATARI_525_DD;
+                    else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 10 &&
+                            imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.RX50;
+                    else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 9 &&
+                            imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_DS_DD_9;
+                    else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 8 &&
+                            imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_DS_DD_8;
+                    if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 9 &&
+                       imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_SS_DD_9;
+                    else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 8 &&
+                            imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_SS_DD_8;
+                    else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 5 &&
+                            imageInfo.SectorSize == 1024) imageInfo.MediaType = MediaType.ACORN_35_DS_DD;
+                    else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 82 && imageInfo.SectorsPerTrack == 10 &&
+                            imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.FDFORMAT_35_DD;
+                    else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 70 && imageInfo.SectorsPerTrack == 9 &&
+                            imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.Apricot_35;
                     break;
                 case TransferRate.FiveHundredMfm:
-                    if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 18 &&
-                       ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DOS_35_HD;
-                    else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 21 &&
-                            ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DMF;
-                    else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 82 && ImageInfo.SectorsPerTrack == 21 &&
-                            ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DMF_82;
-                    else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 23 &&
-                            ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.XDF_35;
-                    else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 15 &&
-                            ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DOS_525_HD;
-                    else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 10 &&
-                            ImageInfo.SectorSize == 1024) ImageInfo.MediaType = MediaType.ACORN_35_DS_HD;
-                    else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 77 && ImageInfo.SectorsPerTrack == 8 &&
-                            ImageInfo.SectorSize == 1024) ImageInfo.MediaType = MediaType.NEC_525_HD;
-                    else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 9 &&
-                            ImageInfo.SectorSize == 1024) ImageInfo.MediaType = MediaType.SHARP_525_9;
-                    else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 10 &&
-                            ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.ATARI_35_SS_DD;
-                    else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 10 &&
-                            ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.ATARI_35_DS_DD;
-                    else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 11 &&
-                            ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.ATARI_35_SS_DD_11;
-                    else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 11 &&
-                            ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.ATARI_35_DS_DD_11;
+                    if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 18 &&
+                       imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_HD;
+                    else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 21 &&
+                            imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DMF;
+                    else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 82 && imageInfo.SectorsPerTrack == 21 &&
+                            imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DMF_82;
+                    else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 23 &&
+                            imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.XDF_35;
+                    else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 15 &&
+                            imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_HD;
+                    else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 10 &&
+                            imageInfo.SectorSize == 1024) imageInfo.MediaType = MediaType.ACORN_35_DS_HD;
+                    else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 77 && imageInfo.SectorsPerTrack == 8 &&
+                            imageInfo.SectorSize == 1024) imageInfo.MediaType = MediaType.NEC_525_HD;
+                    else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 9 &&
+                            imageInfo.SectorSize == 1024) imageInfo.MediaType = MediaType.SHARP_525_9;
+                    else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 10 &&
+                            imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.ATARI_35_SS_DD;
+                    else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 10 &&
+                            imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.ATARI_35_DS_DD;
+                    else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 11 &&
+                            imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.ATARI_35_SS_DD_11;
+                    else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 11 &&
+                            imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.ATARI_35_DS_DD_11;
                     break;
                 default:
-                    ImageInfo.MediaType = MediaType.Unknown;
+                    imageInfo.MediaType = MediaType.Unknown;
                     break;
             }
 
-            ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
 
-            DicConsole.VerboseWriteLine("IMD image contains a disk of type {0}", ImageInfo.MediaType);
-            if(!string.IsNullOrEmpty(ImageInfo.Comments))
-                DicConsole.VerboseWriteLine("IMD comments: {0}", ImageInfo.Comments);
+            DicConsole.VerboseWriteLine("IMD image contains a disk of type {0}", imageInfo.MediaType);
+            if(!string.IsNullOrEmpty(imageInfo.Comments))
+                DicConsole.VerboseWriteLine("IMD comments: {0}", imageInfo.Comments);
 
             /*
             FileStream debugFs = new FileStream("debug.img", FileMode.CreateNew, FileAccess.Write);
@@ -321,17 +324,17 @@ namespace DiscImageChef.DiscImages
             return true;
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             return null;
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
@@ -342,7 +345,7 @@ namespace DiscImageChef.DiscImages
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
@@ -353,22 +356,22 @@ namespace DiscImageChef.DiscImages
             return null;
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return null;
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
             return ReadSectors(sectorAddress, 1);
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
             MemoryStream buffer = new MemoryStream();
@@ -378,67 +381,67 @@ namespace DiscImageChef.DiscImages
             return buffer.ToArray();
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
diff --git a/DiscImageChef.DiscImages/IMediaImage.cs b/DiscImageChef.DiscImages/IMediaImage.cs
new file mode 100644
index 00000000..e1af5952
--- /dev/null
+++ b/DiscImageChef.DiscImages/IMediaImage.cs
@@ -0,0 +1,253 @@
+// /***************************************************************************
+// The Disc Image Chef
+// ----------------------------------------------------------------------------
+//
+// Filename       : IMediaImage.cs
+// Author(s)      : Natalia Portillo 
+//
+// Component      : Disc image plugins.
+//
+// --[ Description ] ----------------------------------------------------------
+//
+//     Defines interface to be implemented by disc image plugins.
+//
+// --[ License ] --------------------------------------------------------------
+//
+//     This library is free software; you can redistribute it and/or modify
+//     it under the terms of the GNU Lesser General Public License as
+//     published by the Free Software Foundation; either version 2.1 of the
+//     License, or (at your option) any later version.
+//
+//     This library is distributed in the hope that it will be useful, but
+//     WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//     Lesser General Public License for more details.
+//
+//     You should have received a copy of the GNU Lesser General Public
+//     License along with this library; if not, see .
+//
+// ----------------------------------------------------------------------------
+// Copyright © 2011-2018 Natalia Portillo
+// ****************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.Serialization;
+using DiscImageChef.CommonTypes;
+using DiscImageChef.Filters;
+
+namespace DiscImageChef.DiscImages
+{
+    /// 
+    ///     Abstract class to implement disk image reading plugins.
+    /// 
+    public interface IMediaImage
+    {
+        /// Image information
+        ImageInfo Info { get; }
+        /// Plugin name.
+        string Name { get; }
+        /// Plugin UUID.
+        Guid Id { get; }
+        /// 
+        ///     Gets the image format.
+        /// 
+        /// The image format.
+        string ImageFormat { get; }
+        /// 
+        ///     Gets an array partitions. Typically only useful for optical disc
+        ///     images where each track and index means a different partition, as
+        ///     reads can be relative to them.
+        /// 
+        /// The partitions.
+        List Partitions { get; }
+        /// 
+        ///     Gets the disc track extents (start, length).
+        /// 
+        /// The track extents.
+        List Tracks { get; }
+        /// 
+        ///     Gets the sessions (optical discs only).
+        /// 
+        /// The sessions.
+        List Sessions { get; }
+
+        /// 
+        ///     Identifies the image.
+        /// 
+        /// true, if image was identified, false otherwise.
+        /// Image filter.
+        bool IdentifyImage(IFilter imageFilter);
+
+        /// 
+        ///     Opens the image.
+        /// 
+        /// true, if image was opened, false otherwise.
+        /// Image filter.
+        bool OpenImage(IFilter imageFilter);
+
+        /// 
+        ///     Reads a disk tag.
+        /// 
+        /// Disk tag
+        /// Tag type to read.
+        byte[] ReadDiskTag(MediaTagType tag);
+
+        /// 
+        ///     Reads a sector's user data.
+        /// 
+        /// The sector's user data.
+        /// Sector address (LBA).
+        byte[] ReadSector(ulong sectorAddress);
+
+        /// 
+        ///     Reads a sector's tag.
+        /// 
+        /// The sector's tag.
+        /// Sector address (LBA).
+        /// Tag type.
+        byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag);
+
+        /// 
+        ///     Reads a sector's user data, relative to track.
+        /// 
+        /// The sector's user data.
+        /// Sector address (relative LBA).
+        /// Track.
+        byte[] ReadSector(ulong sectorAddress, uint track);
+
+        /// 
+        ///     Reads a sector's tag, relative to track.
+        /// 
+        /// The sector's tag.
+        /// Sector address (relative LBA).
+        /// Track.
+        /// Tag type.
+        byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag);
+
+        /// 
+        ///     Reads user data from several sectors.
+        /// 
+        /// The sectors user data.
+        /// Starting sector address (LBA).
+        /// How many sectors to read.
+        byte[] ReadSectors(ulong sectorAddress, uint length);
+
+        /// 
+        ///     Reads tag from several sectors.
+        /// 
+        /// The sectors tag.
+        /// Starting sector address (LBA).
+        /// How many sectors to read.
+        /// Tag type.
+        byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag);
+
+        /// 
+        ///     Reads user data from several sectors, relative to track.
+        /// 
+        /// The sectors user data.
+        /// Starting sector address (relative LBA).
+        /// How many sectors to read.
+        /// Track.
+        byte[] ReadSectors(ulong sectorAddress, uint length, uint track);
+
+        /// 
+        ///     Reads tag from several sectors, relative to track.
+        /// 
+        /// The sectors tag.
+        /// Starting sector address (relative LBA).
+        /// How many sectors to read.
+        /// Track.
+        /// Tag type.
+        byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag);
+
+        /// 
+        ///     Reads a complete sector (user data + all tags).
+        /// 
+        /// The complete sector. Format depends on disk type.
+        /// Sector address (LBA).
+        byte[] ReadSectorLong(ulong sectorAddress);
+
+        /// 
+        ///     Reads a complete sector (user data + all tags), relative to track.
+        /// 
+        /// The complete sector. Format depends on disk type.
+        /// Sector address (relative LBA).
+        /// Track.
+        byte[] ReadSectorLong(ulong sectorAddress, uint track);
+
+        /// 
+        ///     Reads several complete sector (user data + all tags).
+        /// 
+        /// The complete sectors. Format depends on disk type.
+        /// Starting sector address (LBA).
+        /// How many sectors to read.
+        byte[] ReadSectorsLong(ulong sectorAddress, uint length);
+
+        /// 
+        ///     Reads several complete sector (user data + all tags), relative to track.
+        /// 
+        /// The complete sectors. Format depends on disk type.
+        /// Starting sector address (relative LBA).
+        /// How many sectors to read.
+        /// Track.
+        byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track);
+
+        /// 
+        ///     Gets the disc track extents for a specified session.
+        /// 
+        /// The track exents for that session.
+        /// Session.
+        List GetSessionTracks(Session session);
+
+        /// 
+        ///     Gets the disc track extents for a specified session.
+        /// 
+        /// The track exents for that session.
+        /// Session.
+        List GetSessionTracks(ushort session);
+
+        /// 
+        ///     Verifies a sector.
+        /// 
+        /// True if correct, false if incorrect, null if uncheckable.
+        /// Sector address (LBA).
+        bool? VerifySector(ulong sectorAddress);
+
+        /// 
+        ///     Verifies a sector, relative to track.
+        /// 
+        /// True if correct, false if incorrect, null if uncheckable.
+        /// Sector address (relative LBA).
+        /// Track.
+        bool? VerifySector(ulong sectorAddress, uint track);
+
+        /// 
+        ///     Verifies several sectors.
+        /// 
+        /// True if all are correct, false if any is incorrect, null if any is uncheckable.
+        /// Starting sector address (LBA).
+        /// How many sectors to read.
+        /// List of incorrect sectors
+        /// List of uncheckable sectors
+        bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas, out List unknownLbas);
+
+        /// 
+        ///     Verifies several sectors, relative to track.
+        /// 
+        /// True if all are correct, false if any is incorrect, null if any is uncheckable.
+        /// Starting sector address (relative LBA).
+        /// How many sectors to read.
+        /// Track.
+        /// List of incorrect sectors
+        /// List of uncheckable sectors
+        bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+                            out List unknownLbas);
+
+        /// 
+        ///     Verifies media image internal checksum.
+        /// 
+        /// True if correct, false if incorrect, null if there is no internal checksum available
+        bool? VerifyMediaImage();
+    }
+}
\ No newline at end of file
diff --git a/DiscImageChef.DiscImages/ImagePlugin.cs b/DiscImageChef.DiscImages/ImagePlugin.cs
deleted file mode 100644
index d1092649..00000000
--- a/DiscImageChef.DiscImages/ImagePlugin.cs
+++ /dev/null
@@ -1,729 +0,0 @@
-// /***************************************************************************
-// The Disc Image Chef
-// ----------------------------------------------------------------------------
-//
-// Filename       : ImagePlugin.cs
-// Author(s)      : Natalia Portillo 
-//
-// Component      : Disc image plugins.
-//
-// --[ Description ] ----------------------------------------------------------
-//
-//     Defines methods to be used by disc image plugins and several constants.
-//
-// --[ License ] --------------------------------------------------------------
-//
-//     This library is free software; you can redistribute it and/or modify
-//     it under the terms of the GNU Lesser General Public License as
-//     published by the Free Software Foundation; either version 2.1 of the
-//     License, or (at your option) any later version.
-//
-//     This library is distributed in the hope that it will be useful, but
-//     WITHOUT ANY WARRANTY; without even the implied warranty of
-//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-//     Lesser General Public License for more details.
-//
-//     You should have received a copy of the GNU Lesser General Public
-//     License along with this library; if not, see .
-//
-// ----------------------------------------------------------------------------
-// Copyright © 2011-2018 Natalia Portillo
-// ****************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using System.Runtime.Serialization;
-using DiscImageChef.CommonTypes;
-using DiscImageChef.Filters;
-
-namespace DiscImageChef.DiscImages
-{
-    /// 
-    ///     Abstract class to implement disk image reading plugins.
-    /// 
-    public abstract class ImagePlugin
-    {
-        // CD flags bitmask
-
-        /// Track is quadraphonic.
-        public const byte CdFlagsFourChannel = 0x20;
-        /// Track is non-audio (data).
-        public const byte CdFlagsDataTrack = 0x10;
-        /// Track is copy protected.
-        public const byte CdFlagsCopyPrevent = 0x08;
-        /// Track has pre-emphasis.
-        public const byte CdFlagsPreEmphasis = 0x04;
-        /// Image information
-        public ImageInfo ImageInfo;
-        /// Plugin name.
-        public string Name;
-        /// Plugin UUID.
-        public Guid PluginUuid;
-
-        // Image information functions
-
-        /// 
-        ///     Gets the image format.
-        /// 
-        /// The image format.
-        public abstract string ImageFormat { get; }
-
-        // Partitioning functions
-
-        /// 
-        ///     Gets an array partitions. Typically only useful for optical disc
-        ///     images where each track and index means a different partition, as
-        ///     reads can be relative to them.
-        /// 
-        /// The partitions.
-        public abstract List Partitions { get; }
-
-        /// 
-        ///     Gets the disc track extents (start, length).
-        /// 
-        /// The track extents.
-        public abstract List Tracks { get; }
-
-        /// 
-        ///     Gets the sessions (optical discs only).
-        /// 
-        /// The sessions.
-        public abstract List Sessions { get; }
-
-        // Basic image handling functions
-
-        /// 
-        ///     Identifies the image.
-        /// 
-        /// true, if image was identified, false otherwise.
-        /// Image filter.
-        public abstract bool IdentifyImage(Filter imageFilter);
-
-        /// 
-        ///     Opens the image.
-        /// 
-        /// true, if image was opened, false otherwise.
-        /// Image filter.
-        public abstract bool OpenImage(Filter imageFilter);
-
-        // Image reading functions
-
-        /// 
-        ///     Reads a disk tag.
-        /// 
-        /// Disk tag
-        /// Tag type to read.
-        public abstract byte[] ReadDiskTag(MediaTagType tag);
-
-        /// 
-        ///     Reads a sector's user data.
-        /// 
-        /// The sector's user data.
-        /// Sector address (LBA).
-        public abstract byte[] ReadSector(ulong sectorAddress);
-
-        /// 
-        ///     Reads a sector's tag.
-        /// 
-        /// The sector's tag.
-        /// Sector address (LBA).
-        /// Tag type.
-        public abstract byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag);
-
-        /// 
-        ///     Reads a sector's user data, relative to track.
-        /// 
-        /// The sector's user data.
-        /// Sector address (relative LBA).
-        /// Track.
-        public abstract byte[] ReadSector(ulong sectorAddress, uint track);
-
-        /// 
-        ///     Reads a sector's tag, relative to track.
-        /// 
-        /// The sector's tag.
-        /// Sector address (relative LBA).
-        /// Track.
-        /// Tag type.
-        public abstract byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag);
-
-        /// 
-        ///     Reads user data from several sectors.
-        /// 
-        /// The sectors user data.
-        /// Starting sector address (LBA).
-        /// How many sectors to read.
-        public abstract byte[] ReadSectors(ulong sectorAddress, uint length);
-
-        /// 
-        ///     Reads tag from several sectors.
-        /// 
-        /// The sectors tag.
-        /// Starting sector address (LBA).
-        /// How many sectors to read.
-        /// Tag type.
-        public abstract byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag);
-
-        /// 
-        ///     Reads user data from several sectors, relative to track.
-        /// 
-        /// The sectors user data.
-        /// Starting sector address (relative LBA).
-        /// How many sectors to read.
-        /// Track.
-        public abstract byte[] ReadSectors(ulong sectorAddress, uint length, uint track);
-
-        /// 
-        ///     Reads tag from several sectors, relative to track.
-        /// 
-        /// The sectors tag.
-        /// Starting sector address (relative LBA).
-        /// How many sectors to read.
-        /// Track.
-        /// Tag type.
-        public abstract byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag);
-
-        /// 
-        ///     Reads a complete sector (user data + all tags).
-        /// 
-        /// The complete sector. Format depends on disk type.
-        /// Sector address (LBA).
-        public abstract byte[] ReadSectorLong(ulong sectorAddress);
-
-        /// 
-        ///     Reads a complete sector (user data + all tags), relative to track.
-        /// 
-        /// The complete sector. Format depends on disk type.
-        /// Sector address (relative LBA).
-        /// Track.
-        public abstract byte[] ReadSectorLong(ulong sectorAddress, uint track);
-
-        /// 
-        ///     Reads several complete sector (user data + all tags).
-        /// 
-        /// The complete sectors. Format depends on disk type.
-        /// Starting sector address (LBA).
-        /// How many sectors to read.
-        public abstract byte[] ReadSectorsLong(ulong sectorAddress, uint length);
-
-        /// 
-        ///     Reads several complete sector (user data + all tags), relative to track.
-        /// 
-        /// The complete sectors. Format depends on disk type.
-        /// Starting sector address (relative LBA).
-        /// How many sectors to read.
-        /// Track.
-        public abstract byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track);
-
-        /// 
-        ///     Gets the disc track extents for a specified session.
-        /// 
-        /// The track exents for that session.
-        /// Session.
-        public abstract List GetSessionTracks(Session session);
-
-        /// 
-        ///     Gets the disc track extents for a specified session.
-        /// 
-        /// The track exents for that session.
-        /// Session.
-        public abstract List GetSessionTracks(ushort session);
-
-        /// 
-        ///     Verifies a sector.
-        /// 
-        /// True if correct, false if incorrect, null if uncheckable.
-        /// Sector address (LBA).
-        public abstract bool? VerifySector(ulong sectorAddress);
-
-        /// 
-        ///     Verifies a sector, relative to track.
-        /// 
-        /// True if correct, false if incorrect, null if uncheckable.
-        /// Sector address (relative LBA).
-        /// Track.
-        public abstract bool? VerifySector(ulong sectorAddress, uint track);
-
-        /// 
-        ///     Verifies several sectors.
-        /// 
-        /// True if all are correct, false if any is incorrect, null if any is uncheckable.
-        /// Starting sector address (LBA).
-        /// How many sectors to read.
-        /// List of incorrect sectors
-        /// List of uncheckable sectors
-        public abstract bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
-                                            out List unknownLbas);
-
-        /// 
-        ///     Verifies several sectors, relative to track.
-        /// 
-        /// True if all are correct, false if any is incorrect, null if any is uncheckable.
-        /// Starting sector address (relative LBA).
-        /// How many sectors to read.
-        /// Track.
-        /// List of incorrect sectors
-        /// List of uncheckable sectors
-        public abstract bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
-                                            out List unknownLbas);
-
-        /// 
-        ///     Verifies media image internal checksum.
-        /// 
-        /// True if correct, false if incorrect, null if there is no internal checksum available
-        public abstract bool? VerifyMediaImage();
-    }
-
-    /// 
-    ///     Track (as partitioning element) types.
-    /// 
-    public enum TrackType
-    {
-        /// Audio track
-        Audio,
-        /// Data track (not any of the below defined ones)
-        Data,
-        /// Data track, compact disc mode 1
-        CdMode1,
-        /// Data track, compact disc mode 2, formless
-        CdMode2Formless,
-        /// Data track, compact disc mode 2, form 1
-        CdMode2Form1,
-        /// Data track, compact disc mode 2, form 2
-        CdMode2Form2
-    }
-
-    /// 
-    ///     Track defining structure.
-    /// 
-    public struct Track
-    {
-        /// Track number, 1-started
-        public uint TrackSequence;
-        /// Partition type
-        public TrackType TrackType;
-        /// Track starting sector
-        public ulong TrackStartSector;
-        /// Track ending sector
-        public ulong TrackEndSector;
-        /// Track pre-gap
-        public ulong TrackPregap;
-        /// Session this track belongs to
-        public ushort TrackSession;
-        /// Information that does not find space in this struct
-        public string TrackDescription;
-        /// Indexes, 00 to 99 and sector offset
-        public Dictionary Indexes;
-        /// Which filter stores this track
-        public Filter TrackFilter;
-        /// Which file stores this track
-        public string TrackFile;
-        /// Starting at which byte is this track stored
-        public ulong TrackFileOffset;
-        /// What kind of file is storing this track
-        public string TrackFileType;
-        /// How many main channel / user data bytes are per sector in this track
-        public int TrackBytesPerSector;
-        /// How many main channel bytes per sector are in the file with this track
-        public int TrackRawBytesPerSector;
-        /// Which filter stores this track's subchannel
-        public Filter TrackSubchannelFilter;
-        /// Which file stores this track's subchannel
-        public string TrackSubchannelFile;
-        /// Starting at which byte are this track's subchannel stored
-        public ulong TrackSubchannelOffset;
-        /// Type of subchannel stored for this track
-        public TrackSubchannelType TrackSubchannelType;
-    }
-
-    /// 
-    ///     Type of subchannel in track
-    /// 
-    public enum TrackSubchannelType
-    {
-        /// 
-        ///     Track does not has subchannel dumped, or it's not a CD
-        /// 
-        None,
-        /// 
-        ///     Subchannel is packed and error corrected
-        /// 
-        Packed,
-        /// 
-        ///     Subchannel is interleaved
-        /// 
-        Raw,
-        /// 
-        ///     Subchannel is packed and comes interleaved with main channel in same file
-        /// 
-        PackedInterleaved,
-        /// 
-        ///     Subchannel is interleaved and comes interleaved with main channel in same file
-        /// 
-        RawInterleaved,
-        /// 
-        ///     Only Q subchannel is stored as 16 bytes
-        /// 
-        Q16,
-        /// 
-        ///     Only Q subchannel is stored as 16 bytes and comes interleaved with main channel in same file
-        /// 
-        Q16Interleaved
-    }
-
-    /// 
-    ///     Session defining structure.
-    /// 
-    public struct Session
-    {
-        /// Session number, 1-started
-        public ushort SessionSequence;
-        /// First track present on this session
-        public uint StartTrack;
-        /// Last track present on this session
-        public uint EndTrack;
-        /// First sector present on this session
-        public ulong StartSector;
-        /// Last sector present on this session
-        public ulong EndSector;
-    }
-
-    /// 
-    ///     Metadata present for each sector (aka, "tag").
-    /// 
-    public enum SectorTagType
-    {
-        /// Apple's GCR sector tags, 12 bytes
-        AppleSectorTag,
-        /// Sync frame from CD sector, 12 bytes
-        CdSectorSync,
-        /// CD sector header, 4 bytes
-        CdSectorHeader,
-        /// CD mode 2 sector subheader
-        CdSectorSubHeader,
-        /// CD sector EDC, 4 bytes
-        CdSectorEdc,
-        /// CD sector ECC P, 172 bytes
-        CdSectorEccP,
-        /// CD sector ECC Q, 104 bytes
-        CdSectorEccQ,
-        /// CD sector ECC (P and Q), 276 bytes
-        CdSectorEcc,
-        /// CD sector subchannel, 96 bytes
-        CdSectorSubchannel,
-        /// CD track ISRC, string, 12 bytes
-        CdTrackIsrc,
-        /// CD track text, string, 13 bytes
-        CdTrackText,
-        /// CD track flags, 1 byte
-        CdTrackFlags,
-        /// DVD sector copyright information
-        DvdCmi,
-        /// Floppy address mark (contents depend on underlying floppy format)
-        FloppyAddressMark
-    }
-
-    /// 
-    ///     Metadata present for each media.
-    /// 
-    public enum MediaTagType
-    {
-        /// CD table of contents
-        CD_TOC,
-        /// CD session information
-        CD_SessionInfo,
-        /// CD full table of contents
-        CD_FullTOC,
-        /// CD PMA
-        CD_PMA,
-        /// CD Adress-Time-In-Pregroove
-        CD_ATIP,
-        /// CD-Text
-        CD_TEXT,
-        /// CD Media Catalogue Number
-        CD_MCN,
-        /// DVD/HD DVD Physical Format Information
-        DVD_PFI,
-        /// DVD Lead-in Copyright Management Information
-        DVD_CMI,
-        /// DVD disc key
-        DVD_DiscKey,
-        /// DVD/HD DVD Burst Cutting Area
-        DVD_BCA,
-        /// DVD/HD DVD Lead-in Disc Manufacturer Information
-        DVD_DMI,
-        /// Media identifier
-        DVD_MediaIdentifier,
-        /// Media key block
-        DVD_MKB,
-        /// DVD-RAM/HD DVD-RAM DDS information
-        DVDRAM_DDS,
-        /// DVD-RAM/HD DVD-RAM Medium status
-        DVDRAM_MediumStatus,
-        /// DVD-RAM/HD DVD-RAM Spare area information
-        DVDRAM_SpareArea,
-        /// DVD-R/-RW/HD DVD-R RMD in last border-out
-        DVDR_RMD,
-        /// Pre-recorded information from DVD-R/-RW lead-in
-        DVDR_PreRecordedInfo,
-        /// DVD-R/-RW/HD DVD-R media identifier
-        DVDR_MediaIdentifier,
-        /// DVD-R/-RW/HD DVD-R physical format information
-        DVDR_PFI,
-        /// ADIP information
-        DVD_ADIP,
-        /// HD DVD Lead-in copyright protection information
-        HDDVD_CPI,
-        /// HD DVD-R Medium Status
-        HDDVD_MediumStatus,
-        /// DVD+/-R DL Layer capacity
-        DVDDL_LayerCapacity,
-        /// DVD-R DL Middle Zone start address
-        DVDDL_MiddleZoneAddress,
-        /// DVD-R DL Jump Interval Size
-        DVDDL_JumpIntervalSize,
-        /// DVD-R DL Start LBA of the manual layer jump
-        DVDDL_ManualLayerJumpLBA,
-        /// Blu-ray Disc Information
-        BD_DI,
-        /// Blu-ray Burst Cutting Area
-        BD_BCA,
-        /// Blu-ray Disc Definition Structure
-        BD_DDS,
-        /// Blu-ray Cartridge Status
-        BD_CartridgeStatus,
-        /// Blu-ray Status of Spare Area
-        BD_SpareArea,
-        /// AACS volume identifier
-        AACS_VolumeIdentifier,
-        /// AACS pre-recorded media serial number
-        AACS_SerialNumber,
-        /// AACS media identifier
-        AACS_MediaIdentifier,
-        /// Lead-in AACS media key block
-        AACS_MKB,
-        /// AACS data keys
-        AACS_DataKeys,
-        /// LBA extents flagged for bus encryption by AACS
-        AACS_LBAExtents,
-        /// CPRM media key block in Lead-in
-        AACS_CPRM_MKB,
-        /// Recognized layer formats in hybrid discs
-        Hybrid_RecognizedLayers,
-        /// Disc write protection status
-        MMC_WriteProtection,
-        /// Disc standard information
-        MMC_DiscInformation,
-        /// Disc track resources information
-        MMC_TrackResourcesInformation,
-        /// BD-R Pseudo-overwrite information
-        MMC_POWResourcesInformation,
-        /// SCSI INQUIRY response
-        SCSI_INQUIRY,
-        /// SCSI MODE PAGE 2Ah
-        SCSI_MODEPAGE_2A,
-        /// ATA IDENTIFY DEVICE response
-        ATA_IDENTIFY,
-        /// ATA IDENTIFY PACKET DEVICE response
-        ATAPI_IDENTIFY,
-        /// PCMCIA/CardBus Card Information Structure
-        PCMCIA_CIS,
-        /// SecureDigital CID
-        SD_CID,
-        /// SecureDigital CSD
-        SD_CSD,
-        /// SecureDigital SCR
-        SD_SCR,
-        /// SecureDigital OCR
-        SD_OCR,
-        /// MultiMediaCard CID
-        MMC_CID,
-        /// MultiMediaCard CSD
-        MMC_CSD,
-        /// MultiMediaCard OCR
-        MMC_OCR,
-        /// MultiMediaCard Extended CSD
-        MMC_ExtendedCSD,
-        /// Xbox Security Sector
-        Xbox_SecuritySector,
-        /// 
-        ///     On floppy disks, data in last cylinder usually in a different format that contains duplication or
-        ///     manufacturing information
-        /// 
-        Floppy_LeadOut
-    }
-
-    /// 
-    ///     Enumeration of media types defined in CICM metadata
-    /// 
-    public enum XmlMediaType
-    {
-        /// 
-        ///     Purely optical discs
-        /// 
-        OpticalDisc,
-        /// 
-        ///     Media that is physically block-based or abstracted like that
-        /// 
-        BlockMedia,
-        /// 
-        ///     Media that can be accessed by-byte or by-bit, like chips
-        /// 
-        LinearMedia,
-        /// 
-        ///     Media that can only store data when it is modulated to audio
-        /// 
-        AudioMedia
-    }
-
-    /// 
-    ///     Feature is supported by image but not implemented yet.
-    /// 
-    [Serializable]
-    public class FeatureSupportedButNotImplementedImageException : Exception
-    {
-        /// 
-        ///     Feature is supported by image but not implemented yet.
-        /// 
-        /// Message.
-        /// Inner.
-        public FeatureSupportedButNotImplementedImageException(string message, Exception inner) :
-            base(message, inner) { }
-
-        /// 
-        ///     Feature is supported by image but not implemented yet.
-        /// 
-        /// Message.
-        public FeatureSupportedButNotImplementedImageException(string message) : base(message) { }
-
-        /// 
-        ///     Feature is supported by image but not implemented yet.
-        /// 
-        /// Info.
-        /// Context.
-        protected FeatureSupportedButNotImplementedImageException(SerializationInfo info, StreamingContext context)
-        {
-            if(info == null) throw new ArgumentNullException(nameof(info));
-        }
-    }
-
-    /// 
-    ///     Feature is not supported by image.
-    /// 
-    [Serializable]
-    public class FeatureUnsupportedImageException : Exception
-    {
-        /// 
-        ///     Feature is not supported by image.
-        /// 
-        /// Message.
-        /// Inner.
-        public FeatureUnsupportedImageException(string message, Exception inner) : base(message, inner) { }
-
-        /// 
-        ///     Feature is not supported by image.
-        /// 
-        /// Message.
-        public FeatureUnsupportedImageException(string message) : base(message) { }
-
-        /// 
-        ///     Feature is not supported by image.
-        /// 
-        /// Info.
-        /// Context.
-        protected FeatureUnsupportedImageException(SerializationInfo info, StreamingContext context)
-        {
-            if(info == null) throw new ArgumentNullException(nameof(info));
-        }
-    }
-
-    /// 
-    ///     Feature is supported by image but not present on it.
-    /// 
-    [Serializable]
-    public class FeatureNotPresentImageException : Exception
-    {
-        /// 
-        ///     Feature is supported by image but not present on it.
-        /// 
-        /// Message.
-        /// Inner.
-        public FeatureNotPresentImageException(string message, Exception inner) : base(message, inner) { }
-
-        /// 
-        ///     Feature is supported by image but not present on it.
-        /// 
-        /// Message.
-        public FeatureNotPresentImageException(string message) : base(message) { }
-
-        /// 
-        ///     Feature is supported by image but not present on it.
-        /// 
-        /// Info.
-        /// Context.
-        protected FeatureNotPresentImageException(SerializationInfo info, StreamingContext context)
-        {
-            if(info == null) throw new ArgumentNullException(nameof(info));
-        }
-    }
-
-    /// 
-    ///     Feature is supported by image but not by the disc it represents.
-    /// 
-    [Serializable]
-    public class FeaturedNotSupportedByDiscImageException : Exception
-    {
-        /// 
-        ///     Feature is supported by image but not by the disc it represents.
-        /// 
-        /// Message.
-        /// Inner.
-        public FeaturedNotSupportedByDiscImageException(string message, Exception inner) : base(message, inner) { }
-
-        /// 
-        ///     Feature is supported by image but not by the disc it represents.
-        /// 
-        /// Message.
-        public FeaturedNotSupportedByDiscImageException(string message) : base(message) { }
-
-        /// 
-        ///     Feature is supported by image but not by the disc it represents.
-        /// 
-        /// Info.
-        /// Context.
-        protected FeaturedNotSupportedByDiscImageException(SerializationInfo info, StreamingContext context)
-        {
-            if(info == null) throw new ArgumentNullException(nameof(info));
-        }
-    }
-
-    /// 
-    ///     Corrupt, incorrect or unhandled feature found on image
-    /// 
-    [Serializable]
-    public class ImageNotSupportedException : Exception
-    {
-        /// 
-        ///     Corrupt, incorrect or unhandled feature found on image
-        /// 
-        /// Message.
-        /// Inner.
-        public ImageNotSupportedException(string message, Exception inner) : base(message, inner) { }
-
-        /// 
-        ///     Corrupt, incorrect or unhandled feature found on image
-        /// 
-        /// Message.
-        public ImageNotSupportedException(string message) : base(message) { }
-
-        /// 
-        ///     Corrupt, incorrect or unhandled feature found on image
-        /// 
-        /// Info.
-        /// Context.
-        protected ImageNotSupportedException(SerializationInfo info, StreamingContext context)
-        {
-            if(info == null) throw new ArgumentNullException(nameof(info));
-        }
-    }
-}
\ No newline at end of file
diff --git a/DiscImageChef.DiscImages/KryoFlux.cs b/DiscImageChef.DiscImages/KryoFlux.cs
index ab045dd6..cda4c5c9 100644
--- a/DiscImageChef.DiscImages/KryoFlux.cs
+++ b/DiscImageChef.DiscImages/KryoFlux.cs
@@ -44,7 +44,7 @@ using DiscImageChef.Filters;
 namespace DiscImageChef.DiscImages
 {
     [SuppressMessage("ReSharper", "InconsistentNaming")]
-    public class KryoFlux : ImagePlugin
+    public class KryoFlux : IMediaImage
     {
         const string hostDate = "host_date";
         const string hostTime = "host_time";
@@ -58,13 +58,16 @@ namespace DiscImageChef.DiscImages
         const string kfIck = "ick";
 
         // TODO: These variables have been made public so create-sidecar can access to this information until I define an API >4.0
-        public SortedDictionary tracks;
+        public SortedDictionary tracks;
+        public ImageInfo imageInfo;
+        public virtual ImageInfo Info => imageInfo;
+
+        public virtual string Name => "KryoFlux STREAM";
+        public virtual Guid Id => new Guid("4DBC95E4-93EE-4F7A-9492-919887E60EFE");
 
         public KryoFlux()
         {
-            Name = "KryoFlux STREAM";
-            PluginUuid = new Guid("4DBC95E4-93EE-4F7A-9492-919887E60EFE");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -89,7 +92,7 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             OobBlock header = new OobBlock();
             Stream stream = imageFilter.GetDataForkStream();
@@ -119,7 +122,7 @@ namespace DiscImageChef.DiscImages
                    footer.blockId == BlockIds.Oob && footer.blockType == OobTypes.EOF && footer.length == 0x0D0D;
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             OobBlock header = new OobBlock();
             Stream stream = imageFilter.GetDataForkStream();
@@ -150,7 +153,7 @@ namespace DiscImageChef.DiscImages
                footer.length != 0x0D0D) return false;
 
             // TODO: This is supposing NoFilter, shouldn't
-            tracks = new SortedDictionary();
+            tracks = new SortedDictionary();
             byte step = 1;
             byte heads = 2;
             bool topHead = false;
@@ -199,8 +202,8 @@ namespace DiscImageChef.DiscImages
                 trackFilter.Open(trackfile);
                 if(!trackFilter.IsOpened()) throw new IOException("Could not open KryoFlux track file.");
 
-                ImageInfo.CreationTime = DateTime.MaxValue;
-                ImageInfo.LastModificationTime = DateTime.MinValue;
+                imageInfo.CreationTime = DateTime.MaxValue;
+                imageInfo.LastModificationTime = DateTime.MinValue;
 
                 Stream trackStream = trackFilter.GetDataForkStream();
                 while(trackStream.Position < trackStream.Length)
@@ -260,10 +263,10 @@ namespace DiscImageChef.DiscImages
                                                                DateTimeStyles.AssumeLocal, out blockTime);
                                         break;
                                     case kfName:
-                                        ImageInfo.Application = kvp[1];
+                                        imageInfo.Application = kvp[1];
                                         break;
                                     case kfVersion:
-                                        ImageInfo.ApplicationVersion = kvp[1];
+                                        imageInfo.ApplicationVersion = kvp[1];
                                         break;
                                 }
                             }
@@ -274,10 +277,9 @@ namespace DiscImageChef.DiscImages
                                                                        blockTime.Hour, blockTime.Minute,
                                                                        blockTime.Second);
                                 DicConsole.DebugWriteLine("KryoFlux plugin", "Found timestamp: {0}", blockTimestamp);
-                                if(blockTimestamp < ImageInfo.CreationTime)
-                                    ImageInfo.CreationTime = blockTimestamp;
-                                if(blockTimestamp > ImageInfo.LastModificationTime)
-                                    ImageInfo.LastModificationTime = blockTimestamp;
+                                if(blockTimestamp < Info.CreationTime) imageInfo.CreationTime = blockTimestamp;
+                                if(blockTimestamp > Info.LastModificationTime)
+                                    imageInfo.LastModificationTime = blockTimestamp;
                             }
 
                             break;
@@ -304,121 +306,121 @@ namespace DiscImageChef.DiscImages
                 tracks.Add(t, trackFilter);
             }
 
-            ImageInfo.Heads = heads;
-            ImageInfo.Cylinders = (uint)(tracks.Count / heads);
+            imageInfo.Heads = heads;
+            imageInfo.Cylinders = (uint)(tracks.Count / heads);
 
             throw new NotImplementedException("Flux decoding is not yet implemented.");
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new NotImplementedException("Flux decoding is not yet implemented.");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
             return ReadSectors(sectorAddress, 1);
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             throw new NotImplementedException("Flux decoding is not yet implemented.");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
             throw new NotImplementedException("Flux decoding is not yet implemented.");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             throw new NotImplementedException("Flux decoding is not yet implemented.");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             throw new NotImplementedException("Flux decoding is not yet implemented.");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             throw new NotImplementedException("Flux decoding is not yet implemented.");
         }
 
-        public override string ImageFormat => "KryoFlux STREAM";
+        public virtual string ImageFormat => "KryoFlux STREAM";
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             throw new NotImplementedException("Flux decoding is not yet implemented.");
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             throw new NotImplementedException("Flux decoding is not yet implemented.");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List Partitions =>
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List Sessions =>
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
diff --git a/DiscImageChef.DiscImages/MaxiDisk.cs b/DiscImageChef.DiscImages/MaxiDisk.cs
index c5c78ee6..5b8f029b 100644
--- a/DiscImageChef.DiscImages/MaxiDisk.cs
+++ b/DiscImageChef.DiscImages/MaxiDisk.cs
@@ -40,16 +40,15 @@ using DiscImageChef.Filters;
 
 namespace DiscImageChef.DiscImages
 {
-    public class MaxiDisk : ImagePlugin
+    public class MaxiDisk : IMediaImage
     {
         /// Disk image file
-        Filter hdkImageFilter;
+        IFilter hdkImageFilter;
+        ImageInfo imageInfo;
 
         public MaxiDisk()
         {
-            Name = "MAXI Disk image";
-            PluginUuid = new Guid("D27D924A-7034-466E-ADE1-B81EF37E469E");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -72,18 +71,23 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "MAXI Disk";
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Partitions =>
+        public virtual string Name => "MAXI Disk image";
+        public virtual Guid Id => new Guid("D27D924A-7034-466E-ADE1-B81EF37E469E");
+
+        public virtual string ImageFormat => "MAXI Disk";
+
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Sessions =>
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
 
@@ -128,7 +132,7 @@ namespace DiscImageChef.DiscImages
             return expectedFileSize == stream.Length;
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
 
@@ -162,84 +166,84 @@ namespace DiscImageChef.DiscImages
 
             if(expectedFileSize != stream.Length) return false;
 
-            ImageInfo.Cylinders = tmpHeader.cylinders;
-            ImageInfo.Heads = tmpHeader.heads;
-            ImageInfo.SectorsPerTrack = tmpHeader.sectorsPerTrack;
-            ImageInfo.Sectors = (ulong)(tmpHeader.heads * tmpHeader.cylinders * tmpHeader.sectorsPerTrack);
-            ImageInfo.SectorSize = (uint)(128 << tmpHeader.bytesPerSector);
+            imageInfo.Cylinders = tmpHeader.cylinders;
+            imageInfo.Heads = tmpHeader.heads;
+            imageInfo.SectorsPerTrack = tmpHeader.sectorsPerTrack;
+            imageInfo.Sectors = (ulong)(tmpHeader.heads * tmpHeader.cylinders * tmpHeader.sectorsPerTrack);
+            imageInfo.SectorSize = (uint)(128 << tmpHeader.bytesPerSector);
 
             hdkImageFilter = imageFilter;
 
-            ImageInfo.ImageSize = (ulong)(stream.Length - 8);
-            ImageInfo.CreationTime = imageFilter.GetCreationTime();
-            ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+            imageInfo.ImageSize = (ulong)(stream.Length - 8);
+            imageInfo.CreationTime = imageFilter.GetCreationTime();
+            imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
 
-            if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 15 &&
-               ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DOS_525_HD;
-            else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 16 &&
-                    ImageInfo.SectorSize == 256) ImageInfo.MediaType = MediaType.ACORN_525_DS_DD;
-            else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 16 &&
-                    ImageInfo.SectorSize == 256) ImageInfo.MediaType = MediaType.ACORN_525_SS_DD_80;
-            else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 10 &&
-                    ImageInfo.SectorSize == 256) ImageInfo.MediaType = MediaType.ACORN_525_SS_SD_80;
-            else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 77 && ImageInfo.SectorsPerTrack == 8 &&
-                    ImageInfo.SectorSize == 1024) ImageInfo.MediaType = MediaType.NEC_525_HD;
-            else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 40 && ImageInfo.SectorsPerTrack == 8 &&
-                    ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DOS_525_SS_DD_8;
-            else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 40 && ImageInfo.SectorsPerTrack == 9 &&
-                    ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DOS_525_SS_DD_9;
-            else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 40 && ImageInfo.SectorsPerTrack == 8 &&
-                    ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DOS_525_DS_DD_8;
-            else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 40 && ImageInfo.SectorsPerTrack == 9 &&
-                    ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DOS_525_DS_DD_9;
-            else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 40 && ImageInfo.SectorsPerTrack == 18 &&
-                    ImageInfo.SectorSize == 128) ImageInfo.MediaType = MediaType.ATARI_525_SD;
-            else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 40 && ImageInfo.SectorsPerTrack == 26 &&
-                    ImageInfo.SectorSize == 128) ImageInfo.MediaType = MediaType.ATARI_525_ED;
-            else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 40 && ImageInfo.SectorsPerTrack == 18 &&
-                    ImageInfo.SectorSize == 256) ImageInfo.MediaType = MediaType.ATARI_525_DD;
-            else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 36 &&
-                    ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DOS_35_ED;
-            else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 18 &&
-                    ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DOS_35_HD;
-            else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 21 &&
-                    ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DMF;
-            else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 82 && ImageInfo.SectorsPerTrack == 21 &&
-                    ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DMF_82;
-            else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 77 && ImageInfo.SectorsPerTrack == 8 &&
-                    ImageInfo.SectorSize == 1024) ImageInfo.MediaType = MediaType.NEC_35_HD_8;
-            else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 15 &&
-                    ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.NEC_35_HD_15;
-            else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 9 &&
-                    ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DOS_35_DS_DD_9;
-            else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 8 &&
-                    ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DOS_35_DS_DD_8;
-            else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 9 &&
-                    ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DOS_35_SS_DD_9;
-            else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 8 &&
-                    ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.DOS_35_SS_DD_8;
-            else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 5 &&
-                    ImageInfo.SectorSize == 1024) ImageInfo.MediaType = MediaType.ACORN_35_DS_DD;
-            else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 70 && ImageInfo.SectorsPerTrack == 9 &&
-                    ImageInfo.SectorSize == 512) ImageInfo.MediaType = MediaType.Apricot_35;
-            else ImageInfo.MediaType = MediaType.Unknown;
+            if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 15 &&
+               imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_HD;
+            else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 16 &&
+                    imageInfo.SectorSize == 256) imageInfo.MediaType = MediaType.ACORN_525_DS_DD;
+            else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 16 &&
+                    imageInfo.SectorSize == 256) imageInfo.MediaType = MediaType.ACORN_525_SS_DD_80;
+            else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 10 &&
+                    imageInfo.SectorSize == 256) imageInfo.MediaType = MediaType.ACORN_525_SS_SD_80;
+            else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 77 && imageInfo.SectorsPerTrack == 8 &&
+                    imageInfo.SectorSize == 1024) imageInfo.MediaType = MediaType.NEC_525_HD;
+            else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 8 &&
+                    imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_SS_DD_8;
+            else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 9 &&
+                    imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_SS_DD_9;
+            else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 8 &&
+                    imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_DS_DD_8;
+            else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 9 &&
+                    imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_DS_DD_9;
+            else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 18 &&
+                    imageInfo.SectorSize == 128) imageInfo.MediaType = MediaType.ATARI_525_SD;
+            else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 26 &&
+                    imageInfo.SectorSize == 128) imageInfo.MediaType = MediaType.ATARI_525_ED;
+            else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 18 &&
+                    imageInfo.SectorSize == 256) imageInfo.MediaType = MediaType.ATARI_525_DD;
+            else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 36 &&
+                    imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_ED;
+            else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 18 &&
+                    imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_HD;
+            else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 21 &&
+                    imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DMF;
+            else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 82 && imageInfo.SectorsPerTrack == 21 &&
+                    imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DMF_82;
+            else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 77 && imageInfo.SectorsPerTrack == 8 &&
+                    imageInfo.SectorSize == 1024) imageInfo.MediaType = MediaType.NEC_35_HD_8;
+            else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 15 &&
+                    imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.NEC_35_HD_15;
+            else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 9 &&
+                    imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_DS_DD_9;
+            else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 8 &&
+                    imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_DS_DD_8;
+            else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 9 &&
+                    imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_SS_DD_9;
+            else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 8 &&
+                    imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_SS_DD_8;
+            else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 5 &&
+                    imageInfo.SectorSize == 1024) imageInfo.MediaType = MediaType.ACORN_35_DS_DD;
+            else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 70 && imageInfo.SectorsPerTrack == 9 &&
+                    imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.Apricot_35;
+            else imageInfo.MediaType = MediaType.Unknown;
 
-            ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
 
             return true;
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             return null;
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
@@ -250,7 +254,7 @@ namespace DiscImageChef.DiscImages
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
@@ -261,94 +265,94 @@ namespace DiscImageChef.DiscImages
             return null;
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return null;
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
             return ReadSectors(sectorAddress, 1);
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
-            byte[] buffer = new byte[length * ImageInfo.SectorSize];
+            byte[] buffer = new byte[length * imageInfo.SectorSize];
 
             Stream stream = hdkImageFilter.GetDataForkStream();
-            stream.Seek((long)(8 + sectorAddress * ImageInfo.SectorSize), SeekOrigin.Begin);
-            stream.Read(buffer, 0, (int)(length * ImageInfo.SectorSize));
+            stream.Seek((long)(8 + sectorAddress * imageInfo.SectorSize), SeekOrigin.Begin);
+            stream.Read(buffer, 0, (int)(length * imageInfo.SectorSize));
 
             return buffer;
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
diff --git a/DiscImageChef.DiscImages/NDIF.cs b/DiscImageChef.DiscImages/NDIF.cs
index 4a221bae..daf301e8 100644
--- a/DiscImageChef.DiscImages/NDIF.cs
+++ b/DiscImageChef.DiscImages/NDIF.cs
@@ -49,7 +49,7 @@ namespace DiscImageChef.DiscImages
     // TODO: Check checksum
     // TODO: Implement segments
     // TODO: Implement compression
-    public class Ndif : ImagePlugin
+    public class Ndif : IMediaImage
     {
         /// 
         ///     Resource OSType for NDIF is "bcem"
@@ -87,6 +87,7 @@ namespace DiscImageChef.DiscImages
         uint currentChunkCacheSize;
 
         ChunkHeader header;
+        ImageInfo imageInfo;
 
         Stream imageStream;
 
@@ -94,9 +95,7 @@ namespace DiscImageChef.DiscImages
 
         public Ndif()
         {
-            Name = "Apple New Disk Image Format";
-            PluginUuid = new Guid("5A7FF7D8-491E-458D-8674-5B5EADBECC24");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -121,18 +120,23 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "Apple New Disk Image Format";
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Partitions =>
+        public virtual string Name => "Apple New Disk Image Format";
+        public virtual Guid Id => new Guid("5A7FF7D8-491E-458D-8674-5B5EADBECC24");
+
+        public virtual string ImageFormat => "Apple New Disk Image Format";
+
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Sessions =>
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             if(!imageFilter.HasResourceFork() || imageFilter.GetResourceForkLength() == 0) return false;
 
@@ -150,7 +154,7 @@ namespace DiscImageChef.DiscImages
             return false;
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             if(!imageFilter.HasResourceFork() || imageFilter.GetResourceForkLength() == 0) return false;
 
@@ -171,7 +175,7 @@ namespace DiscImageChef.DiscImages
             }
             catch(InvalidCastException) { return false; }
 
-            ImageInfo.Sectors = 0;
+            imageInfo.Sectors = 0;
             foreach(byte[] bcem in bcems.Select(id => rsrc.GetResource(NDIF_RESOURCEID)))
             {
                 if(bcem.Length < 128) return false;
@@ -224,7 +228,7 @@ namespace DiscImageChef.DiscImages
                     if(bChnk.type == CHUNK_TYPE_END) break;
 
                     bChnk.offset += header.dataOffset;
-                    bChnk.sector += (uint)ImageInfo.Sectors;
+                    bChnk.sector += (uint)imageInfo.Sectors;
 
                     // TODO: Handle compressed chunks
                     switch(bChnk.type)
@@ -251,29 +255,29 @@ namespace DiscImageChef.DiscImages
                     chunks.Add(bChnk.sector, bChnk);
                 }
 
-                ImageInfo.Sectors += header.sectors;
+                imageInfo.Sectors += header.sectors;
             }
 
             if(header.segmented > 0) throw new ImageNotSupportedException("Segmented images are not yet supported.");
 
             if(header.encrypted > 0) throw new ImageNotSupportedException("Encrypted images are not yet supported.");
 
-            switch(ImageInfo.Sectors)
+            switch(imageInfo.Sectors)
             {
                 case 1440:
-                    ImageInfo.MediaType = MediaType.DOS_35_DS_DD_9;
+                    imageInfo.MediaType = MediaType.DOS_35_DS_DD_9;
                     break;
                 case 1600:
-                    ImageInfo.MediaType = MediaType.AppleSonyDS;
+                    imageInfo.MediaType = MediaType.AppleSonyDS;
                     break;
                 case 2880:
-                    ImageInfo.MediaType = MediaType.DOS_35_HD;
+                    imageInfo.MediaType = MediaType.DOS_35_HD;
                     break;
                 case 3360:
-                    ImageInfo.MediaType = MediaType.DMF;
+                    imageInfo.MediaType = MediaType.DMF;
                     break;
                 default:
-                    ImageInfo.MediaType = MediaType.GENERIC_HDD;
+                    imageInfo.MediaType = MediaType.GENERIC_HDD;
                     break;
             }
 
@@ -310,17 +314,17 @@ namespace DiscImageChef.DiscImages
 
                     if(dev != null) pre = $"{version.PreReleaseVersion}";
 
-                    ImageInfo.ApplicationVersion = $"{major}{minor}{release}{dev}{pre}";
-                    ImageInfo.Application = version.VersionString;
-                    ImageInfo.Comments = version.VersionMessage;
+                    imageInfo.ApplicationVersion = $"{major}{minor}{release}{dev}{pre}";
+                    imageInfo.Application = version.VersionString;
+                    imageInfo.Comments = version.VersionMessage;
 
-                    if(version.MajorVersion == 3) ImageInfo.Application = "ShrinkWrapâ„¢";
-                    else if(version.MajorVersion == 6) ImageInfo.Application = "DiskCopy";
+                    if(version.MajorVersion == 3) imageInfo.Application = "ShrinkWrapâ„¢";
+                    else if(version.MajorVersion == 6) imageInfo.Application = "DiskCopy";
                 }
             }
 
-            DicConsole.DebugWriteLine("NDIF plugin", "Image application = {0} version {1}", ImageInfo.Application,
-                                      ImageInfo.ApplicationVersion);
+            DicConsole.DebugWriteLine("NDIF plugin", "Image application = {0} version {1}", imageInfo.Application,
+                                      imageInfo.ApplicationVersion);
 
             sectorCache = new Dictionary();
             chunkCache = new Dictionary();
@@ -328,51 +332,51 @@ namespace DiscImageChef.DiscImages
             imageStream = imageFilter.GetDataForkStream();
             buffersize = header.maxSectorsPerChunk * SECTOR_SIZE;
 
-            ImageInfo.CreationTime = imageFilter.GetCreationTime();
-            ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
-            ImageInfo.MediaTitle = StringHandlers.PascalToString(header.name, Encoding.GetEncoding("macintosh"));
-            ImageInfo.SectorSize = SECTOR_SIZE;
-            ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
-            ImageInfo.ImageSize = ImageInfo.Sectors * SECTOR_SIZE;
-            ImageInfo.ApplicationVersion = "6";
-            ImageInfo.Application = "Apple DiskCopy";
+            imageInfo.CreationTime = imageFilter.GetCreationTime();
+            imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+            imageInfo.MediaTitle = StringHandlers.PascalToString(header.name, Encoding.GetEncoding("macintosh"));
+            imageInfo.SectorSize = SECTOR_SIZE;
+            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+            imageInfo.ImageSize = imageInfo.Sectors * SECTOR_SIZE;
+            imageInfo.ApplicationVersion = "6";
+            imageInfo.Application = "Apple DiskCopy";
 
-            switch(ImageInfo.MediaType)
+            switch(imageInfo.MediaType)
             {
                 case MediaType.AppleSonyDS:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 10;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 10;
                     break;
                 case MediaType.DOS_35_DS_DD_9:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 9;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 9;
                     break;
                 case MediaType.DOS_35_HD:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 18;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 18;
                     break;
                 case MediaType.DMF:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 21;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 21;
                     break;
                 default:
-                    ImageInfo.MediaType = MediaType.GENERIC_HDD;
-                    ImageInfo.Cylinders = (uint)(ImageInfo.Sectors / 16 / 63);
-                    ImageInfo.Heads = 16;
-                    ImageInfo.SectorsPerTrack = 63;
+                    imageInfo.MediaType = MediaType.GENERIC_HDD;
+                    imageInfo.Cylinders = (uint)(imageInfo.Sectors / 16 / 63);
+                    imageInfo.Heads = 16;
+                    imageInfo.SectorsPerTrack = 63;
                     break;
             }
 
             return true;
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress),
                                                       $"Sector address {sectorAddress} not found");
 
@@ -460,13 +464,13 @@ namespace DiscImageChef.DiscImages
             throw new ImageNotSupportedException($"Unsupported chunk type 0x{currentChunk.type:X8} found");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress),
                                                       $"Sector address {sectorAddress} not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
             MemoryStream ms = new MemoryStream();
@@ -480,98 +484,98 @@ namespace DiscImageChef.DiscImages
             return ms.ToArray();
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             return null;
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
             unknownLbas = new List();
-            for(ulong i = 0; i < ImageInfo.Sectors; i++) unknownLbas.Add(i);
+            for(ulong i = 0; i < imageInfo.Sectors; i++) unknownLbas.Add(i);
 
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return null;
         }
diff --git a/DiscImageChef.DiscImages/NHDr0.cs b/DiscImageChef.DiscImages/NHDr0.cs
index c0330f85..c8c9c824 100644
--- a/DiscImageChef.DiscImages/NHDr0.cs
+++ b/DiscImageChef.DiscImages/NHDr0.cs
@@ -43,19 +43,18 @@ using DiscImageChef.Filters;
 namespace DiscImageChef.DiscImages
 {
     // Info from http://www.geocities.jp/t98next/nhdr0.txt
-    public class Nhdr0 : ImagePlugin
+    public class Nhdr0 : IMediaImage
     {
         readonly byte[] signature =
             {0x54, 0x39, 0x38, 0x48, 0x44, 0x44, 0x49, 0x4D, 0x41, 0x47, 0x45, 0x2E, 0x52, 0x30, 0x00};
+        ImageInfo imageInfo;
 
         Nhdr0Header nhdhdr;
-        Filter nhdImageFilter;
+        IFilter nhdImageFilter;
 
         public Nhdr0()
         {
-            Name = "T98-Next NHD r0 Disk Image";
-            PluginUuid = new Guid("6ECACD0A-8F4D-4465-8815-AEA000D370E3");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -80,18 +79,22 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "NHDr0 disk image";
+        public virtual string Name => "T98-Next NHD r0 Disk Image";
+        public virtual Guid Id => new Guid("6ECACD0A-8F4D-4465-8815-AEA000D370E3");
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Partitions =>
+        public virtual string ImageFormat => "NHDr0 disk image";
+
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Sessions =>
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -125,7 +128,7 @@ namespace DiscImageChef.DiscImages
             return true;
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -143,141 +146,141 @@ namespace DiscImageChef.DiscImages
             nhdhdr = (Nhdr0Header)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(Nhdr0Header));
             handle.Free();
 
-            ImageInfo.MediaType = MediaType.GENERIC_HDD;
+            imageInfo.MediaType = MediaType.GENERIC_HDD;
 
-            ImageInfo.ImageSize = (ulong)(stream.Length - nhdhdr.dwHeadSize);
-            ImageInfo.CreationTime = imageFilter.GetCreationTime();
-            ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
-            ImageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
-            ImageInfo.Sectors = (ulong)(nhdhdr.dwCylinder * nhdhdr.wHead * nhdhdr.wSect);
-            ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
-            ImageInfo.SectorSize = (uint)nhdhdr.wSectLen;
-            ImageInfo.Cylinders = (uint)nhdhdr.dwCylinder;
-            ImageInfo.Heads = (uint)nhdhdr.wHead;
-            ImageInfo.SectorsPerTrack = (uint)nhdhdr.wSect;
-            ImageInfo.Comments = StringHandlers.CToString(nhdhdr.szComment, shiftjis);
+            imageInfo.ImageSize = (ulong)(stream.Length - nhdhdr.dwHeadSize);
+            imageInfo.CreationTime = imageFilter.GetCreationTime();
+            imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+            imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
+            imageInfo.Sectors = (ulong)(nhdhdr.dwCylinder * nhdhdr.wHead * nhdhdr.wSect);
+            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+            imageInfo.SectorSize = (uint)nhdhdr.wSectLen;
+            imageInfo.Cylinders = (uint)nhdhdr.dwCylinder;
+            imageInfo.Heads = (uint)nhdhdr.wHead;
+            imageInfo.SectorsPerTrack = (uint)nhdhdr.wSect;
+            imageInfo.Comments = StringHandlers.CToString(nhdhdr.szComment, shiftjis);
 
             nhdImageFilter = imageFilter;
 
             return true;
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
             return ReadSectors(sectorAddress, 1);
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
-            byte[] buffer = new byte[length * ImageInfo.SectorSize];
+            byte[] buffer = new byte[length * imageInfo.SectorSize];
 
             Stream stream = nhdImageFilter.GetDataForkStream();
 
-            stream.Seek((long)((ulong)nhdhdr.dwHeadSize + sectorAddress * ImageInfo.SectorSize), SeekOrigin.Begin);
+            stream.Seek((long)((ulong)nhdhdr.dwHeadSize + sectorAddress * imageInfo.SectorSize), SeekOrigin.Begin);
 
-            stream.Read(buffer, 0, (int)(length * ImageInfo.SectorSize));
+            stream.Read(buffer, 0, (int)(length * imageInfo.SectorSize));
 
             return buffer;
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             return null;
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
             unknownLbas = new List();
-            for(ulong i = 0; i < ImageInfo.Sectors; i++) unknownLbas.Add(i);
+            for(ulong i = 0; i < imageInfo.Sectors; i++) unknownLbas.Add(i);
 
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return null;
         }
diff --git a/DiscImageChef.DiscImages/Nero.cs b/DiscImageChef.DiscImages/Nero.cs
index 56dd889c..32ec8115 100644
--- a/DiscImageChef.DiscImages/Nero.cs
+++ b/DiscImageChef.DiscImages/Nero.cs
@@ -48,7 +48,7 @@ namespace DiscImageChef.DiscImages
 {
     [SuppressMessage("ReSharper", "NotAccessedField.Local")]
     [SuppressMessage("ReSharper", "CollectionNeverQueried.Local")]
-    public class Nero : ImagePlugin
+    public class Nero : IMediaImage
     {
         // "NERO"
         const uint NERO_FOOTER_V1 = 0x4E45524F;
@@ -98,6 +98,8 @@ namespace DiscImageChef.DiscImages
         List imagePartitions;
         List imageSessions;
         Stream imageStream;
+        ImageInfo imageInfo;
+        public virtual ImageInfo Info => imageInfo;
 
         List imageTracks;
         NeroCdText neroCdtxt;
@@ -107,7 +109,7 @@ namespace DiscImageChef.DiscImages
         NeroV2Dao neroDaov2;
         NeroDiscInformation neroDiscInfo;
 
-        Filter neroFilter;
+        IFilter neroFilter;
         NeroMediaType neroMediaTyp;
         NeroReloChunk neroRelo;
         Dictionary neroSessions;
@@ -119,12 +121,13 @@ namespace DiscImageChef.DiscImages
         Dictionary trackIsrCs;
         byte[] upc;
 
+        public virtual string Name => "Nero Burning ROM image";
+        public virtual Guid Id => new Guid("D160F9FF-5941-43FC-B037-AD81DD141F05");
+
         public Nero()
         {
-            Name = "Nero Burning ROM image";
-            PluginUuid = new Guid("D160F9FF-5941-43FC-B037-AD81DD141F05");
             imageNewFormat = false;
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List()
@@ -137,7 +140,7 @@ namespace DiscImageChef.DiscImages
         }
 
         // Due to .cue format, this method must parse whole file, ignoring errors (those will be thrown by OpenImage()).
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             imageStream = imageFilter.GetDataForkStream();
             BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;
@@ -168,7 +171,7 @@ namespace DiscImageChef.DiscImages
             return footerV1.ChunkId == NERO_FOOTER_V1 && footerV1.FirstChunkOffset < (ulong)imageStream.Length;
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             try
             {
@@ -218,9 +221,9 @@ namespace DiscImageChef.DiscImages
                 imageTracks = new List();
                 trackIsrCs = new Dictionary();
 
-                ImageInfo.MediaType = MediaType.CD;
-                ImageInfo.Sectors = 0;
-                ImageInfo.SectorSize = 0;
+                imageInfo.MediaType = MediaType.CD;
+                imageInfo.Sectors = 0;
+                imageInfo.SectorSize = 0;
 
                 while(parsing)
                 {
@@ -341,11 +344,11 @@ namespace DiscImageChef.DiscImages
                             neroDaov1.LastTrack = tmpbuffer[21];
                             neroDaov1.Tracks = new List();
 
-                            if(!ImageInfo.ReadableMediaTags.Contains(MediaTagType.CD_MCN))
-                                ImageInfo.ReadableMediaTags.Add(MediaTagType.CD_MCN);
+                            if(!imageInfo.ReadableMediaTags.Contains(MediaTagType.CD_MCN))
+                                imageInfo.ReadableMediaTags.Add(MediaTagType.CD_MCN);
 
-                            if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdTrackIsrc))
-                                ImageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackIsrc);
+                            if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdTrackIsrc))
+                                imageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackIsrc);
 
                             DicConsole.DebugWriteLine("Nero plugin", "neroDAOV1.ChunkSizeLe = {0} bytes",
                                                       neroDaov1.ChunkSizeLe);
@@ -390,7 +393,7 @@ namespace DiscImageChef.DiscImages
 
                                 neroDaov1.Tracks.Add(entry);
 
-                                if(entry.SectorSize > ImageInfo.SectorSize) ImageInfo.SectorSize = entry.SectorSize;
+                                if(entry.SectorSize > imageInfo.SectorSize) imageInfo.SectorSize = entry.SectorSize;
 
                                 trackIsrCs.Add(currenttrack, entry.Isrc);
                                 if(currenttrack == 1) entry.Index0 = entry.Index1;
@@ -403,7 +406,7 @@ namespace DiscImageChef.DiscImages
                                     Mode = entry.Mode,
                                     Offset = entry.Index0,
                                     SectorSize = entry.SectorSize,
-                                    StartLba = ImageInfo.Sectors,
+                                    StartLba = imageInfo.Sectors,
                                     Index0 = entry.Index0,
                                     Index1 = entry.Index1,
                                     Sequence = currenttrack
@@ -411,7 +414,7 @@ namespace DiscImageChef.DiscImages
                                 neroTrack.Sectors = neroTrack.Length / entry.SectorSize;
                                 neroTracks.Add(currenttrack, neroTrack);
 
-                                ImageInfo.Sectors += neroTrack.Sectors;
+                                imageInfo.Sectors += neroTrack.Sectors;
 
                                 currenttrack++;
                             }
@@ -435,11 +438,11 @@ namespace DiscImageChef.DiscImages
                             neroDaov2.LastTrack = tmpbuffer[21];
                             neroDaov2.Tracks = new List();
 
-                            if(!ImageInfo.ReadableMediaTags.Contains(MediaTagType.CD_MCN))
-                                ImageInfo.ReadableMediaTags.Add(MediaTagType.CD_MCN);
+                            if(!imageInfo.ReadableMediaTags.Contains(MediaTagType.CD_MCN))
+                                imageInfo.ReadableMediaTags.Add(MediaTagType.CD_MCN);
 
-                            if(!ImageInfo.ReadableSectorTags.Contains(SectorTagType.CdTrackIsrc))
-                                ImageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackIsrc);
+                            if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdTrackIsrc))
+                                imageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackIsrc);
 
                             upc = neroDaov2.Upc;
 
@@ -484,7 +487,7 @@ namespace DiscImageChef.DiscImages
 
                                 neroDaov2.Tracks.Add(entry);
 
-                                if(entry.SectorSize > ImageInfo.SectorSize) ImageInfo.SectorSize = entry.SectorSize;
+                                if(entry.SectorSize > imageInfo.SectorSize) imageInfo.SectorSize = entry.SectorSize;
 
                                 trackIsrCs.Add(currenttrack, entry.Isrc);
 
@@ -498,7 +501,7 @@ namespace DiscImageChef.DiscImages
                                     Mode = entry.Mode,
                                     Offset = entry.Index0,
                                     SectorSize = entry.SectorSize,
-                                    StartLba = ImageInfo.Sectors,
+                                    StartLba = imageInfo.Sectors,
                                     Index0 = entry.Index0,
                                     Index1 = entry.Index1,
                                     Sequence = currenttrack
@@ -506,7 +509,7 @@ namespace DiscImageChef.DiscImages
                                 neroTrack.Sectors = neroTrack.Length / entry.SectorSize;
                                 neroTracks.Add(currenttrack, neroTrack);
 
-                                ImageInfo.Sectors += neroTrack.Sectors;
+                                imageInfo.Sectors += neroTrack.Sectors;
 
                                 currenttrack++;
                             }
@@ -596,8 +599,8 @@ namespace DiscImageChef.DiscImages
 
                                 neroTaov1.Tracks.Add(entry);
 
-                                if(NeroTrackModeToBytesPerSector((DaoMode)entry.Mode) > ImageInfo.SectorSize)
-                                    ImageInfo.SectorSize = NeroTrackModeToBytesPerSector((DaoMode)entry.Mode);
+                                if(NeroTrackModeToBytesPerSector((DaoMode)entry.Mode) > imageInfo.SectorSize)
+                                    imageInfo.SectorSize = NeroTrackModeToBytesPerSector((DaoMode)entry.Mode);
 
                                 NeroTrack neroTrack = new NeroTrack
                                 {
@@ -607,7 +610,7 @@ namespace DiscImageChef.DiscImages
                                     Mode = entry.Mode,
                                     Offset = entry.Offset,
                                     SectorSize = NeroTrackModeToBytesPerSector((DaoMode)entry.Mode),
-                                    StartLba = ImageInfo.Sectors,
+                                    StartLba = imageInfo.Sectors,
                                     Index0 = entry.Offset,
                                     Index1 = entry.Offset,
                                     Sequence = currenttrack
@@ -616,7 +619,7 @@ namespace DiscImageChef.DiscImages
                                     neroTrack.Length / NeroTrackModeToBytesPerSector((DaoMode)entry.Mode);
                                 neroTracks.Add(currenttrack, neroTrack);
 
-                                ImageInfo.Sectors += neroTrack.Sectors;
+                                imageInfo.Sectors += neroTrack.Sectors;
 
                                 currenttrack++;
                             }
@@ -664,8 +667,8 @@ namespace DiscImageChef.DiscImages
 
                                 neroTaov2.Tracks.Add(entry);
 
-                                if(NeroTrackModeToBytesPerSector((DaoMode)entry.Mode) > ImageInfo.SectorSize)
-                                    ImageInfo.SectorSize = NeroTrackModeToBytesPerSector((DaoMode)entry.Mode);
+                                if(NeroTrackModeToBytesPerSector((DaoMode)entry.Mode) > imageInfo.SectorSize)
+                                    imageInfo.SectorSize = NeroTrackModeToBytesPerSector((DaoMode)entry.Mode);
 
                                 NeroTrack neroTrack = new NeroTrack
                                 {
@@ -678,13 +681,13 @@ namespace DiscImageChef.DiscImages
                                 neroTrack.Sectors =
                                     neroTrack.Length / NeroTrackModeToBytesPerSector((DaoMode)entry.Mode);
                                 neroTrack.SectorSize = NeroTrackModeToBytesPerSector((DaoMode)entry.Mode);
-                                neroTrack.StartLba = ImageInfo.Sectors;
+                                neroTrack.StartLba = imageInfo.Sectors;
                                 neroTrack.Index0 = entry.Offset;
                                 neroTrack.Index1 = entry.Offset;
                                 neroTrack.Sequence = currenttrack;
                                 neroTracks.Add(currenttrack, neroTrack);
 
-                                ImageInfo.Sectors += neroTrack.Sectors;
+                                imageInfo.Sectors += neroTrack.Sectors;
 
                                 currenttrack++;
                             }
@@ -722,7 +725,7 @@ namespace DiscImageChef.DiscImages
                             DicConsole.DebugWriteLine("Nero plugin", "\tMedia type is {0} ({1})",
                                                       (NeroMediaTypes)neroMediaTyp.Type, neroMediaTyp.Type);
 
-                            ImageInfo.MediaType = NeroMediaTypeToMediaType((NeroMediaTypes)neroMediaTyp.Type);
+                            imageInfo.MediaType = NeroMediaTypeToMediaType((NeroMediaTypes)neroMediaTyp.Type);
 
                             break;
                         }
@@ -788,37 +791,37 @@ namespace DiscImageChef.DiscImages
                     }
                 }
 
-                ImageInfo.HasPartitions = true;
-                ImageInfo.HasSessions = true;
-                ImageInfo.Creator = null;
-                ImageInfo.CreationTime = imageFilter.GetCreationTime();
-                ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
-                ImageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
-                ImageInfo.Comments = null;
-                ImageInfo.MediaManufacturer = null;
-                ImageInfo.MediaModel = null;
-                ImageInfo.MediaSerialNumber = null;
-                ImageInfo.MediaBarcode = null;
-                ImageInfo.MediaPartNumber = null;
-                ImageInfo.DriveManufacturer = null;
-                ImageInfo.DriveModel = null;
-                ImageInfo.DriveSerialNumber = null;
-                ImageInfo.DriveFirmwareRevision = null;
-                ImageInfo.MediaSequence = 0;
-                ImageInfo.LastMediaSequence = 0;
+                imageInfo.HasPartitions = true;
+                imageInfo.HasSessions = true;
+                imageInfo.Creator = null;
+                imageInfo.CreationTime = imageFilter.GetCreationTime();
+                imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+                imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
+                imageInfo.Comments = null;
+                imageInfo.MediaManufacturer = null;
+                imageInfo.MediaModel = null;
+                imageInfo.MediaSerialNumber = null;
+                imageInfo.MediaBarcode = null;
+                imageInfo.MediaPartNumber = null;
+                imageInfo.DriveManufacturer = null;
+                imageInfo.DriveModel = null;
+                imageInfo.DriveSerialNumber = null;
+                imageInfo.DriveFirmwareRevision = null;
+                imageInfo.MediaSequence = 0;
+                imageInfo.LastMediaSequence = 0;
                 if(imageNewFormat)
                 {
-                    ImageInfo.ImageSize = footerV2.FirstChunkOffset;
-                    ImageInfo.Version = "Nero Burning ROM >= 5.5";
-                    ImageInfo.Application = "Nero Burning ROM";
-                    ImageInfo.ApplicationVersion = ">= 5.5";
+                    imageInfo.ImageSize = footerV2.FirstChunkOffset;
+                    imageInfo.Version = "Nero Burning ROM >= 5.5";
+                    imageInfo.Application = "Nero Burning ROM";
+                    imageInfo.ApplicationVersion = ">= 5.5";
                 }
                 else
                 {
-                    ImageInfo.ImageSize = footerV1.FirstChunkOffset;
-                    ImageInfo.Version = "Nero Burning ROM <= 5.0";
-                    ImageInfo.Application = "Nero Burning ROM";
-                    ImageInfo.ApplicationVersion = "<= 5.0";
+                    imageInfo.ImageSize = footerV1.FirstChunkOffset;
+                    imageInfo.Version = "Nero Burning ROM <= 5.0";
+                    imageInfo.Application = "Nero Burning ROM";
+                    imageInfo.ApplicationVersion = "<= 5.0";
                 }
 
                 if(neroSessions.Count == 0) neroSessions.Add(1, currenttrack);
@@ -982,7 +985,7 @@ namespace DiscImageChef.DiscImages
 
                 neroFilter = imageFilter;
 
-                if(ImageInfo.MediaType == MediaType.Unknown || ImageInfo.MediaType == MediaType.CD)
+                if(imageInfo.MediaType == MediaType.Unknown || imageInfo.MediaType == MediaType.CD)
                 {
                     bool data = false;
                     bool mode2 = false;
@@ -1019,16 +1022,16 @@ namespace DiscImageChef.DiscImages
                         }
                     }
 
-                    if(!data && !firstdata) ImageInfo.MediaType = MediaType.CDDA;
+                    if(!data && !firstdata) imageInfo.MediaType = MediaType.CDDA;
                     else if(firstaudio && data && imageSessions.Count > 1 && mode2)
-                        ImageInfo.MediaType = MediaType.CDPLUS;
-                    else if(firstdata && audio || mode2) ImageInfo.MediaType = MediaType.CDROMXA;
-                    else if(!audio) ImageInfo.MediaType = MediaType.CDROM;
-                    else ImageInfo.MediaType = MediaType.CD;
+                        imageInfo.MediaType = MediaType.CDPLUS;
+                    else if(firstdata && audio || mode2) imageInfo.MediaType = MediaType.CDROMXA;
+                    else if(!audio) imageInfo.MediaType = MediaType.CDROM;
+                    else imageInfo.MediaType = MediaType.CD;
                 }
 
-                ImageInfo.XmlMediaType = XmlMediaType.OpticalDisc;
-                DicConsole.VerboseWriteLine("Nero image contains a disc of type {0}", ImageInfo.MediaType);
+                imageInfo.XmlMediaType = XmlMediaType.OpticalDisc;
+                DicConsole.VerboseWriteLine("Nero image contains a disc of type {0}", imageInfo.MediaType);
 
                 return true;
             }
@@ -1039,7 +1042,7 @@ namespace DiscImageChef.DiscImages
             }
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             switch(tag)
             {
@@ -1050,27 +1053,27 @@ namespace DiscImageChef.DiscImages
             }
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
             return ReadSectors(sectorAddress, 1);
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             return ReadSectorsTag(sectorAddress, 1, tag);
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             return ReadSectors(sectorAddress, 1, track);
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             return ReadSectorsTag(sectorAddress, 1, track, tag);
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
             foreach(KeyValuePair kvp in from kvp in offsetmap
                                                      where sectorAddress >= kvp.Value
@@ -1084,7 +1087,7 @@ namespace DiscImageChef.DiscImages
             throw new ArgumentOutOfRangeException(nameof(sectorAddress), $"Sector address {sectorAddress} not found");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             foreach(KeyValuePair kvp in from kvp in offsetmap
                                                      where sectorAddress >= kvp.Value
@@ -1098,7 +1101,7 @@ namespace DiscImageChef.DiscImages
             throw new ArgumentOutOfRangeException(nameof(sectorAddress), $"Sector address {sectorAddress} not found");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             if(!neroTracks.TryGetValue(track, out NeroTrack dicTrack))
                 throw new ArgumentOutOfRangeException(nameof(track), "Track not found");
@@ -1193,7 +1196,7 @@ namespace DiscImageChef.DiscImages
             return buffer;
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             if(!neroTracks.TryGetValue(track, out NeroTrack dicTrack))
                 throw new ArgumentOutOfRangeException(nameof(track), "Track not found");
@@ -1416,17 +1419,17 @@ namespace DiscImageChef.DiscImages
             return buffer;
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             return ReadSectorsLong(sectorAddress, 1);
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             return ReadSectorsLong(sectorAddress, 1, track);
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             foreach(KeyValuePair kvp in from kvp in offsetmap
                                                      where sectorAddress >= kvp.Value
@@ -1440,7 +1443,7 @@ namespace DiscImageChef.DiscImages
             throw new ArgumentOutOfRangeException(nameof(sectorAddress), $"Sector address {sectorAddress} not found");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             if(!neroTracks.TryGetValue(track, out NeroTrack dicTrack))
                 throw new ArgumentOutOfRangeException(nameof(track), "Track not found");
@@ -1513,37 +1516,37 @@ namespace DiscImageChef.DiscImages
             return buffer;
         }
 
-        public override string ImageFormat => "Nero Burning ROM";
+        public virtual string ImageFormat => "Nero Burning ROM";
 
-        public override List Partitions => imagePartitions;
+        public virtual List Partitions => imagePartitions;
 
-        public override List Tracks => imageTracks;
+        public virtual List Tracks => imageTracks;
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             return GetSessionTracks(session.SessionSequence);
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             return imageTracks.Where(track => track.TrackSession == session).ToList();
         }
 
-        public override List Sessions => imageSessions;
+        public virtual List Sessions => imageSessions;
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             byte[] buffer = ReadSectorLong(sectorAddress);
             return CdChecksums.CheckCdSector(buffer);
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             byte[] buffer = ReadSectorLong(sectorAddress, track);
             return CdChecksums.CheckCdSector(buffer);
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             byte[] buffer = ReadSectorsLong(sectorAddress, length);
@@ -1573,7 +1576,7 @@ namespace DiscImageChef.DiscImages
             return failingLbas.Count <= 0;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             byte[] buffer = ReadSectorsLong(sectorAddress, length, track);
@@ -1603,7 +1606,7 @@ namespace DiscImageChef.DiscImages
             return failingLbas.Count <= 0;
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return null;
         }
diff --git a/DiscImageChef.DiscImages/Parallels.cs b/DiscImageChef.DiscImages/Parallels.cs
index 0f5de89c..de0f0c6e 100644
--- a/DiscImageChef.DiscImages/Parallels.cs
+++ b/DiscImageChef.DiscImages/Parallels.cs
@@ -41,7 +41,7 @@ using DiscImageChef.Filters;
 
 namespace DiscImageChef.DiscImages
 {
-    public class Parallels : ImagePlugin
+    public class Parallels : IMediaImage
     {
         const uint PARALLELS_VERSION = 2;
 
@@ -62,6 +62,7 @@ namespace DiscImageChef.DiscImages
         bool empty;
 
         bool extended;
+        ImageInfo imageInfo;
         Stream imageStream;
         ParallelsHeader pHdr;
 
@@ -69,9 +70,7 @@ namespace DiscImageChef.DiscImages
 
         public Parallels()
         {
-            Name = "Parallels disk image";
-            PluginUuid = new Guid("E314DE35-C103-48A3-AD36-990F68523C46");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -96,18 +95,22 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "Parallels";
+        public virtual string Name => "Parallels disk image";
+        public virtual Guid Id => new Guid("E314DE35-C103-48A3-AD36-990F68523C46");
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Partitions =>
+        public virtual string ImageFormat => "Parallels";
+
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Sessions =>
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -125,7 +128,7 @@ namespace DiscImageChef.DiscImages
             return parallelsMagic.SequenceEqual(pHdr.magic) || parallelsExtMagic.SequenceEqual(pHdr.magic);
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -169,25 +172,25 @@ namespace DiscImageChef.DiscImages
 
             empty = (pHdr.flags & PARALLELS_EMPTY) == PARALLELS_EMPTY;
 
-            ImageInfo.CreationTime = imageFilter.GetCreationTime();
-            ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
-            ImageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
-            ImageInfo.Sectors = pHdr.sectors;
-            ImageInfo.SectorSize = 512;
-            ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
-            ImageInfo.MediaType = MediaType.GENERIC_HDD;
-            ImageInfo.ImageSize = pHdr.sectors * 512;
-            ImageInfo.Cylinders = pHdr.cylinders;
-            ImageInfo.Heads = pHdr.heads;
-            ImageInfo.SectorsPerTrack = (uint)(ImageInfo.Sectors / ImageInfo.Cylinders / ImageInfo.Heads);
+            imageInfo.CreationTime = imageFilter.GetCreationTime();
+            imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+            imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
+            imageInfo.Sectors = pHdr.sectors;
+            imageInfo.SectorSize = 512;
+            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+            imageInfo.MediaType = MediaType.GENERIC_HDD;
+            imageInfo.ImageSize = pHdr.sectors * 512;
+            imageInfo.Cylinders = pHdr.cylinders;
+            imageInfo.Heads = pHdr.heads;
+            imageInfo.SectorsPerTrack = (uint)(imageInfo.Sectors / imageInfo.Cylinders / imageInfo.Heads);
             imageStream = stream;
 
             return true;
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress),
                                                       $"Sector address {sectorAddress} not found");
 
@@ -219,13 +222,13 @@ namespace DiscImageChef.DiscImages
             return sector;
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress),
                                                       $"Sector address {sectorAddress} not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
             if(empty) return new byte[512 * length];
@@ -241,98 +244,98 @@ namespace DiscImageChef.DiscImages
             return ms.ToArray();
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             return null;
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
             unknownLbas = new List();
-            for(ulong i = 0; i < ImageInfo.Sectors; i++) unknownLbas.Add(i);
+            for(ulong i = 0; i < imageInfo.Sectors; i++) unknownLbas.Add(i);
 
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return null;
         }
diff --git a/DiscImageChef.DiscImages/PartClone.cs b/DiscImageChef.DiscImages/PartClone.cs
index 968a5c10..be64238b 100644
--- a/DiscImageChef.DiscImages/PartClone.cs
+++ b/DiscImageChef.DiscImages/PartClone.cs
@@ -42,7 +42,7 @@ using Extents;
 
 namespace DiscImageChef.DiscImages
 {
-    public class PartClone : ImagePlugin
+    public class PartClone : IMediaImage
     {
         const int CRC_SIZE = 4;
 
@@ -58,6 +58,7 @@ namespace DiscImageChef.DiscImages
 
         ExtentsULong extents;
         Dictionary extentsOff;
+        ImageInfo imageInfo;
         Stream imageStream;
 
         PartCloneHeader pHdr;
@@ -66,9 +67,7 @@ namespace DiscImageChef.DiscImages
 
         public PartClone()
         {
-            Name = "PartClone disk image";
-            PluginUuid = new Guid("AB1D7518-B548-4099-A4E2-C29C53DDE0C3");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -92,18 +91,22 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "PartClone";
+        public virtual string Name => "PartClone disk image";
+        public virtual Guid Id => new Guid("AB1D7518-B548-4099-A4E2-C29C53DDE0C3");
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Partitions =>
+        public virtual string ImageFormat => "PartClone";
+
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Sessions =>
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -128,7 +131,7 @@ namespace DiscImageChef.DiscImages
             return partCloneMagic.SequenceEqual(pHdr.magic) && biTmAgIc.SequenceEqual(bitmagic);
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -203,14 +206,14 @@ namespace DiscImageChef.DiscImages
 
             sectorCache = new Dictionary();
 
-            ImageInfo.CreationTime = imageFilter.GetCreationTime();
-            ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
-            ImageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
-            ImageInfo.Sectors = pHdr.totalBlocks;
-            ImageInfo.SectorSize = pHdr.blockSize;
-            ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
-            ImageInfo.MediaType = MediaType.GENERIC_HDD;
-            ImageInfo.ImageSize = (ulong)(stream.Length - (4096 + 0x40 + (long)pHdr.totalBlocks));
+            imageInfo.CreationTime = imageFilter.GetCreationTime();
+            imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+            imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
+            imageInfo.Sectors = pHdr.totalBlocks;
+            imageInfo.SectorSize = pHdr.blockSize;
+            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+            imageInfo.MediaType = MediaType.GENERIC_HDD;
+            imageInfo.ImageSize = (ulong)(stream.Length - (4096 + 0x40 + (long)pHdr.totalBlocks));
             imageStream = stream;
 
             return true;
@@ -223,9 +226,9 @@ namespace DiscImageChef.DiscImages
             return extentStartingOffset + (sectorAddress - extentStart);
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress),
                                                       $"Sector address {sectorAddress} not found");
 
@@ -246,13 +249,13 @@ namespace DiscImageChef.DiscImages
             return sector;
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress),
                                                       $"Sector address {sectorAddress} not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
             MemoryStream ms = new MemoryStream();
@@ -276,99 +279,99 @@ namespace DiscImageChef.DiscImages
             return ms.ToArray();
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             return null;
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
             unknownLbas = new List();
-            for(ulong i = 0; i < ImageInfo.Sectors; i++) unknownLbas.Add(i);
+            for(ulong i = 0; i < imageInfo.Sectors; i++) unknownLbas.Add(i);
 
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
         // TODO: All blocks contain a CRC32 that's incompatible with current implementation. Need to check for compatibility.
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return null;
         }
diff --git a/DiscImageChef.DiscImages/Partimage.cs b/DiscImageChef.DiscImages/Partimage.cs
index 64ed1ed3..f118ad36 100644
--- a/DiscImageChef.DiscImages/Partimage.cs
+++ b/DiscImageChef.DiscImages/Partimage.cs
@@ -44,7 +44,7 @@ using Extents;
 
 namespace DiscImageChef.DiscImages
 {
-    public class Partimage : ImagePlugin
+    public class Partimage : IMediaImage
     {
         const int MAX_DESCRIPTION = 4096;
         const int MAX_HOSTNAMESIZE = 128;
@@ -88,15 +88,14 @@ namespace DiscImageChef.DiscImages
 
         ExtentsULong extents;
         Dictionary extentsOff;
+        ImageInfo imageInfo;
         Stream imageStream;
 
         Dictionary sectorCache;
 
         public Partimage()
         {
-            Name = "Partimage disk image";
-            PluginUuid = new Guid("AAFDB99D-2B77-49EA-831C-C9BB58C68C95");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -120,18 +119,23 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "Partimage";
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Partitions =>
+        public virtual string Name => "Partimage disk image";
+        public virtual Guid Id => new Guid("AAFDB99D-2B77-49EA-831C-C9BB58C68C95");
+
+        public virtual string ImageFormat => "Partimage";
+
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Sessions =>
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -149,7 +153,7 @@ namespace DiscImageChef.DiscImages
             return partimageMagic.SequenceEqual(cVolumeHeader.magic);
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -386,16 +390,16 @@ namespace DiscImageChef.DiscImages
 
             sectorCache = new Dictionary();
 
-            ImageInfo.CreationTime = dateCreate;
-            ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
-            ImageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
-            ImageInfo.Sectors = localHeader.qwBlocksCount + 1;
-            ImageInfo.SectorSize = (uint)localHeader.qwBlockSize;
-            ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
-            ImageInfo.MediaType = MediaType.GENERIC_HDD;
-            ImageInfo.Version = StringHandlers.CToString(cMainHeader.szVersion);
-            ImageInfo.Comments = StringHandlers.CToString(cMainHeader.szPartDescription);
-            ImageInfo.ImageSize =
+            imageInfo.CreationTime = dateCreate;
+            imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+            imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
+            imageInfo.Sectors = localHeader.qwBlocksCount + 1;
+            imageInfo.SectorSize = (uint)localHeader.qwBlockSize;
+            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+            imageInfo.MediaType = MediaType.GENERIC_HDD;
+            imageInfo.Version = StringHandlers.CToString(cMainHeader.szVersion);
+            imageInfo.Comments = StringHandlers.CToString(cMainHeader.szPartDescription);
+            imageInfo.ImageSize =
                 (ulong)(stream.Length - (dataOff + Marshal.SizeOf(typeof(CMainTail)) + MAGIC_BEGIN_TAIL.Length));
             imageStream = stream;
 
@@ -409,14 +413,14 @@ namespace DiscImageChef.DiscImages
             return extentStartingOffset + (sectorAddress - extentStart);
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress),
                                                       $"Sector address {sectorAddress} not found");
 
             if((bitmap[sectorAddress / 8] & (1 << (int)(sectorAddress % 8))) == 0)
-                return new byte[ImageInfo.SectorSize];
+                return new byte[imageInfo.SectorSize];
 
             if(sectorCache.TryGetValue(sectorAddress, out byte[] sector)) return sector;
 
@@ -426,14 +430,14 @@ namespace DiscImageChef.DiscImages
             // Start of data +
             long imageOff = dataOff +
                             // How many stored bytes to skip
-                            (long)(blockOff * ImageInfo.SectorSize) +
+                            (long)(blockOff * imageInfo.SectorSize) +
                             // How many bytes of CRC blocks to skip
-                            (long)(blockOff / (CHECK_FREQUENCY / ImageInfo.SectorSize)) *
+                            (long)(blockOff / (CHECK_FREQUENCY / imageInfo.SectorSize)) *
                             Marshal.SizeOf(typeof(CCheck));
 
-            sector = new byte[ImageInfo.SectorSize];
+            sector = new byte[imageInfo.SectorSize];
             imageStream.Seek(imageOff, SeekOrigin.Begin);
-            imageStream.Read(sector, 0, (int)ImageInfo.SectorSize);
+            imageStream.Read(sector, 0, (int)imageInfo.SectorSize);
 
             if(sectorCache.Count > MAX_CACHED_SECTORS)
             {
@@ -446,13 +450,13 @@ namespace DiscImageChef.DiscImages
             return sector;
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress),
                                                       $"Sector address {sectorAddress} not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
             MemoryStream ms = new MemoryStream();
@@ -465,7 +469,7 @@ namespace DiscImageChef.DiscImages
                     break;
                 }
 
-            if(allEmpty) return new byte[ImageInfo.SectorSize * length];
+            if(allEmpty) return new byte[imageInfo.SectorSize * length];
 
             for(uint i = 0; i < length; i++)
             {
@@ -476,99 +480,99 @@ namespace DiscImageChef.DiscImages
             return ms.ToArray();
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             return null;
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
             unknownLbas = new List();
-            for(ulong i = 0; i < ImageInfo.Sectors; i++) unknownLbas.Add(i);
+            for(ulong i = 0; i < imageInfo.Sectors; i++) unknownLbas.Add(i);
 
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
         // TODO: All blocks contain a CRC32 that's incompatible with current implementation. Need to check for compatibility.
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return null;
         }
diff --git a/DiscImageChef.DiscImages/QCOW.cs b/DiscImageChef.DiscImages/QCOW.cs
index 07a6d315..e1c4dbd0 100644
--- a/DiscImageChef.DiscImages/QCOW.cs
+++ b/DiscImageChef.DiscImages/QCOW.cs
@@ -42,7 +42,7 @@ using SharpCompress.Compressors.Deflate;
 
 namespace DiscImageChef.DiscImages
 {
-    public class Qcow : ImagePlugin
+    public class Qcow : IMediaImage
     {
         /// 
         ///     Magic number: 'Q', 'F', 'I', 0xFB
@@ -59,6 +59,7 @@ namespace DiscImageChef.DiscImages
         Dictionary clusterCache;
         int clusterSectors;
         int clusterSize;
+        ImageInfo imageInfo;
 
         Stream imageStream;
 
@@ -79,9 +80,7 @@ namespace DiscImageChef.DiscImages
 
         public Qcow()
         {
-            Name = "QEMU Copy-On-Write disk image";
-            PluginUuid = new Guid("A5C35765-9FE2-469D-BBBF-ACDEBDB7B954");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -106,18 +105,23 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "QEMU Copy-On-Write";
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Partitions =>
+        public virtual string Name => "QEMU Copy-On-Write disk image";
+        public virtual Guid Id => new Guid("A5C35765-9FE2-469D-BBBF-ACDEBDB7B954");
+
+        public virtual string ImageFormat => "QEMU Copy-On-Write";
+
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Sessions =>
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -131,7 +135,7 @@ namespace DiscImageChef.DiscImages
             return qHdr.magic == QCOW_MAGIC && qHdr.version == QCOW_VERSION;
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -187,7 +191,7 @@ namespace DiscImageChef.DiscImages
             DicConsole.DebugWriteLine("QCOW plugin", "qHdr.clusterSectors = {0}", clusterSectors);
             DicConsole.DebugWriteLine("QCOW plugin", "qHdr.l1Size = {0}", l1Size);
             DicConsole.DebugWriteLine("QCOW plugin", "qHdr.l2Size = {0}", l2Size);
-            DicConsole.DebugWriteLine("QCOW plugin", "qHdr.sectors = {0}", ImageInfo.Sectors);
+            DicConsole.DebugWriteLine("QCOW plugin", "qHdr.sectors = {0}", imageInfo.Sectors);
 
             BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;
 
@@ -235,27 +239,27 @@ namespace DiscImageChef.DiscImages
             l2TableCache = new Dictionary();
             clusterCache = new Dictionary();
 
-            ImageInfo.CreationTime = imageFilter.GetCreationTime();
-            ImageInfo.LastModificationTime = qHdr.mtime > 0
-                                                      ? DateHandlers.UnixUnsignedToDateTime(qHdr.mtime)
-                                                      : imageFilter.GetLastWriteTime();
-            ImageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
-            ImageInfo.Sectors = qHdr.size / 512;
-            ImageInfo.SectorSize = 512;
-            ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
-            ImageInfo.MediaType = MediaType.GENERIC_HDD;
-            ImageInfo.ImageSize = qHdr.size;
+            imageInfo.CreationTime = imageFilter.GetCreationTime();
+            imageInfo.LastModificationTime = qHdr.mtime > 0
+                                                 ? DateHandlers.UnixUnsignedToDateTime(qHdr.mtime)
+                                                 : imageFilter.GetLastWriteTime();
+            imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
+            imageInfo.Sectors = qHdr.size / 512;
+            imageInfo.SectorSize = 512;
+            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+            imageInfo.MediaType = MediaType.GENERIC_HDD;
+            imageInfo.ImageSize = qHdr.size;
 
-            ImageInfo.Cylinders = (uint)(ImageInfo.Sectors / 16 / 63);
-            ImageInfo.Heads = 16;
-            ImageInfo.SectorsPerTrack = 63;
+            imageInfo.Cylinders = (uint)(imageInfo.Sectors / 16 / 63);
+            imageInfo.Heads = 16;
+            imageInfo.SectorsPerTrack = 63;
 
             return true;
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress),
                                                       $"Sector address {sectorAddress} not found");
 
@@ -345,13 +349,13 @@ namespace DiscImageChef.DiscImages
             return sector;
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress),
                                                       $"Sector address {sectorAddress} not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
             MemoryStream ms = new MemoryStream();
@@ -365,98 +369,98 @@ namespace DiscImageChef.DiscImages
             return ms.ToArray();
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             return null;
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
             unknownLbas = new List();
-            for(ulong i = 0; i < ImageInfo.Sectors; i++) unknownLbas.Add(i);
+            for(ulong i = 0; i < imageInfo.Sectors; i++) unknownLbas.Add(i);
 
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return null;
         }
diff --git a/DiscImageChef.DiscImages/QCOW2.cs b/DiscImageChef.DiscImages/QCOW2.cs
index f33162e9..e24cffb4 100644
--- a/DiscImageChef.DiscImages/QCOW2.cs
+++ b/DiscImageChef.DiscImages/QCOW2.cs
@@ -42,7 +42,7 @@ using SharpCompress.Compressors.Deflate;
 
 namespace DiscImageChef.DiscImages
 {
-    public class Qcow2 : ImagePlugin
+    public class Qcow2 : IMediaImage
     {
         /// 
         ///     Magic number: 'Q', 'F', 'I', 0xFB
@@ -74,6 +74,7 @@ namespace DiscImageChef.DiscImages
         Dictionary clusterCache;
         int clusterSectors;
         int clusterSize;
+        ImageInfo imageInfo;
 
         Stream imageStream;
 
@@ -94,9 +95,7 @@ namespace DiscImageChef.DiscImages
 
         public Qcow2()
         {
-            Name = "QEMU Copy-On-Write disk image v2";
-            PluginUuid = new Guid("F20107CB-95B3-4398-894B-975261F1E8C5");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -121,18 +120,23 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "QEMU Copy-On-Write";
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Partitions =>
+        public virtual string Name => "QEMU Copy-On-Write disk image v2";
+        public virtual Guid Id => new Guid("F20107CB-95B3-4398-894B-975261F1E8C5");
+
+        public virtual string ImageFormat => "QEMU Copy-On-Write";
+
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Sessions =>
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -149,7 +153,7 @@ namespace DiscImageChef.DiscImages
             return qHdr.magic == QCOW_MAGIC && (qHdr.version == QCOW_VERSION2 || qHdr.version == QCOW_VERSION3);
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -217,7 +221,7 @@ namespace DiscImageChef.DiscImages
             DicConsole.DebugWriteLine("QCOW plugin", "qHdr.clusterSectors = {0}", clusterSectors);
             DicConsole.DebugWriteLine("QCOW plugin", "qHdr.qHdr.l1_size = {0}", qHdr.l1_size);
             DicConsole.DebugWriteLine("QCOW plugin", "qHdr.l2Size = {0}", l2Size);
-            DicConsole.DebugWriteLine("QCOW plugin", "qHdr.sectors = {0}", ImageInfo.Sectors);
+            DicConsole.DebugWriteLine("QCOW plugin", "qHdr.sectors = {0}", imageInfo.Sectors);
 
             BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;
 
@@ -266,26 +270,26 @@ namespace DiscImageChef.DiscImages
             l2TableCache = new Dictionary();
             clusterCache = new Dictionary();
 
-            ImageInfo.CreationTime = imageFilter.GetCreationTime();
-            ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
-            ImageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
-            ImageInfo.Sectors = qHdr.size / 512;
-            ImageInfo.SectorSize = 512;
-            ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
-            ImageInfo.MediaType = MediaType.GENERIC_HDD;
-            ImageInfo.ImageSize = qHdr.size;
-            ImageInfo.Version = $"{qHdr.version}";
+            imageInfo.CreationTime = imageFilter.GetCreationTime();
+            imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+            imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
+            imageInfo.Sectors = qHdr.size / 512;
+            imageInfo.SectorSize = 512;
+            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+            imageInfo.MediaType = MediaType.GENERIC_HDD;
+            imageInfo.ImageSize = qHdr.size;
+            imageInfo.Version = $"{qHdr.version}";
 
-            ImageInfo.Cylinders = (uint)(ImageInfo.Sectors / 16 / 63);
-            ImageInfo.Heads = 16;
-            ImageInfo.SectorsPerTrack = 63;
+            imageInfo.Cylinders = (uint)(imageInfo.Sectors / 16 / 63);
+            imageInfo.Heads = 16;
+            imageInfo.SectorsPerTrack = 63;
 
             return true;
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress),
                                                       $"Sector address {sectorAddress} not found");
 
@@ -376,13 +380,13 @@ namespace DiscImageChef.DiscImages
             return sector;
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress),
                                                       $"Sector address {sectorAddress} not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
             MemoryStream ms = new MemoryStream();
@@ -396,98 +400,98 @@ namespace DiscImageChef.DiscImages
             return ms.ToArray();
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             return null;
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
             unknownLbas = new List();
-            for(ulong i = 0; i < ImageInfo.Sectors; i++) unknownLbas.Add(i);
+            for(ulong i = 0; i < imageInfo.Sectors; i++) unknownLbas.Add(i);
 
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return null;
         }
diff --git a/DiscImageChef.DiscImages/QED.cs b/DiscImageChef.DiscImages/QED.cs
index 2a964895..3d391668 100644
--- a/DiscImageChef.DiscImages/QED.cs
+++ b/DiscImageChef.DiscImages/QED.cs
@@ -40,7 +40,7 @@ using DiscImageChef.Filters;
 
 namespace DiscImageChef.DiscImages
 {
-    public class Qed : ImagePlugin
+    public class Qed : IMediaImage
     {
         /// 
         ///     Magic number: 'Q', 'E', 'D', 0x00
@@ -72,6 +72,7 @@ namespace DiscImageChef.DiscImages
         int clusterBits;
         Dictionary clusterCache;
         uint clusterSectors;
+        ImageInfo imageInfo;
 
         Stream imageStream;
 
@@ -91,43 +92,48 @@ namespace DiscImageChef.DiscImages
 
         public Qed()
         {
-            Name = "QEMU Enhanced Disk image";
-            PluginUuid = new Guid("B9DBB155-A69A-4C10-BF91-96BF431B9BB6");
-            ImageInfo = new ImageInfo();
-            ImageInfo.ReadableSectorTags = new List();
-            ImageInfo.ReadableMediaTags = new List();
-            ImageInfo.HasPartitions = false;
-            ImageInfo.HasSessions = false;
-            ImageInfo.Version = "1";
-            ImageInfo.Application = "QEMU";
-            ImageInfo.ApplicationVersion = null;
-            ImageInfo.Creator = null;
-            ImageInfo.Comments = null;
-            ImageInfo.MediaManufacturer = null;
-            ImageInfo.MediaModel = null;
-            ImageInfo.MediaSerialNumber = null;
-            ImageInfo.MediaBarcode = null;
-            ImageInfo.MediaPartNumber = null;
-            ImageInfo.MediaSequence = 0;
-            ImageInfo.LastMediaSequence = 0;
-            ImageInfo.DriveManufacturer = null;
-            ImageInfo.DriveModel = null;
-            ImageInfo.DriveSerialNumber = null;
-            ImageInfo.DriveFirmwareRevision = null;
+            imageInfo = new ImageInfo
+            {
+                ReadableSectorTags = new List(),
+                ReadableMediaTags = new List(),
+                HasPartitions = false,
+                HasSessions = false,
+                Version = "1",
+                Application = "QEMU",
+                ApplicationVersion = null,
+                Creator = null,
+                Comments = null,
+                MediaManufacturer = null,
+                MediaModel = null,
+                MediaSerialNumber = null,
+                MediaBarcode = null,
+                MediaPartNumber = null,
+                MediaSequence = 0,
+                LastMediaSequence = 0,
+                DriveManufacturer = null,
+                DriveModel = null,
+                DriveSerialNumber = null,
+                DriveFirmwareRevision = null
+            };
         }
 
-        public override string ImageFormat => "QEMU Enhanced Disk";
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Partitions =>
+        public virtual string Name => "QEMU Enhanced Disk image";
+        public virtual Guid Id => new Guid("B9DBB155-A69A-4C10-BF91-96BF431B9BB6");
+
+        public virtual string ImageFormat => "QEMU Enhanced Disk";
+
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Sessions =>
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -145,7 +151,7 @@ namespace DiscImageChef.DiscImages
             return qHdr.magic == QED_MAGIC;
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -243,25 +249,25 @@ namespace DiscImageChef.DiscImages
             l2TableCache = new Dictionary();
             clusterCache = new Dictionary();
 
-            ImageInfo.CreationTime = imageFilter.GetCreationTime();
-            ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
-            ImageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
-            ImageInfo.Sectors = qHdr.image_size / 512;
-            ImageInfo.SectorSize = 512;
-            ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
-            ImageInfo.MediaType = MediaType.GENERIC_HDD;
-            ImageInfo.ImageSize = qHdr.image_size;
+            imageInfo.CreationTime = imageFilter.GetCreationTime();
+            imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+            imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
+            imageInfo.Sectors = qHdr.image_size / 512;
+            imageInfo.SectorSize = 512;
+            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+            imageInfo.MediaType = MediaType.GENERIC_HDD;
+            imageInfo.ImageSize = qHdr.image_size;
 
-            ImageInfo.Cylinders = (uint)(ImageInfo.Sectors / 16 / 63);
-            ImageInfo.Heads = 16;
-            ImageInfo.SectorsPerTrack = 63;
+            imageInfo.Cylinders = (uint)(imageInfo.Sectors / 16 / 63);
+            imageInfo.Heads = 16;
+            imageInfo.SectorsPerTrack = 63;
 
             return true;
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress),
                                                       $"Sector address {sectorAddress} not found");
 
@@ -322,13 +328,13 @@ namespace DiscImageChef.DiscImages
             return sector;
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress),
                                                       $"Sector address {sectorAddress} not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
             MemoryStream ms = new MemoryStream();
@@ -382,98 +388,98 @@ namespace DiscImageChef.DiscImages
             return cnt;
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             return null;
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
             unknownLbas = new List();
-            for(ulong i = 0; i < ImageInfo.Sectors; i++) unknownLbas.Add(i);
+            for(ulong i = 0; i < imageInfo.Sectors; i++) unknownLbas.Add(i);
 
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return null;
         }
diff --git a/DiscImageChef.DiscImages/RayDIM.cs b/DiscImageChef.DiscImages/RayDIM.cs
index da489bd1..74fb0b01 100644
--- a/DiscImageChef.DiscImages/RayDIM.cs
+++ b/DiscImageChef.DiscImages/RayDIM.cs
@@ -42,19 +42,18 @@ using DiscImageChef.Filters;
 
 namespace DiscImageChef.DiscImages
 {
-    public class RayDim : ImagePlugin
+    public class RayDim : IMediaImage
     {
         const string REGEX_SIGNATURE =
                 @"Disk IMage VER (?\d).(?\d) Copyright \(C\) (?\d{4}) Ray Arachelian, All Rights Reserved\."
             ;
 
         MemoryStream disk;
+        ImageInfo imageInfo;
 
         public RayDim()
         {
-            Name = "Ray Arachelian's Disk IMage";
-            PluginUuid = new Guid("F541F4E7-C1E3-4A2D-B07F-D863E87AB961");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -77,18 +76,22 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "Ray Arachelian's Disk IMage";
+        public virtual string Name => "Ray Arachelian's Disk IMage";
+        public virtual Guid Id => new Guid("F541F4E7-C1E3-4A2D-B07F-D863E87AB961");
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Partitions =>
+        public virtual string ImageFormat => "Ray Arachelian's Disk IMage";
+
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Sessions =>
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
 
@@ -121,7 +124,7 @@ namespace DiscImageChef.DiscImages
             return sm.Success;
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
 
@@ -143,92 +146,92 @@ namespace DiscImageChef.DiscImages
 
             if(!sm.Success) return false;
 
-            ImageInfo.ApplicationVersion = $"{sm.Groups["major"].Value}.{sm.Groups["minor"].Value}";
+            imageInfo.ApplicationVersion = $"{sm.Groups["major"].Value}.{sm.Groups["minor"].Value}";
 
-            ImageInfo.Cylinders = (uint)(header.cylinders + 1);
-            ImageInfo.Heads = (uint)(header.heads + 1);
-            ImageInfo.SectorsPerTrack = header.sectorsPerTrack;
-            ImageInfo.Sectors = ImageInfo.Cylinders * ImageInfo.Heads * ImageInfo.SectorsPerTrack;
-            ImageInfo.SectorSize = 512;
+            imageInfo.Cylinders = (uint)(header.cylinders + 1);
+            imageInfo.Heads = (uint)(header.heads + 1);
+            imageInfo.SectorsPerTrack = header.sectorsPerTrack;
+            imageInfo.Sectors = imageInfo.Cylinders * imageInfo.Heads * imageInfo.SectorsPerTrack;
+            imageInfo.SectorSize = 512;
 
-            byte[] sectors = new byte[ImageInfo.SectorsPerTrack * ImageInfo.SectorSize];
+            byte[] sectors = new byte[imageInfo.SectorsPerTrack * imageInfo.SectorSize];
             disk = new MemoryStream();
 
-            for(int i = 0; i < ImageInfo.SectorsPerTrack * ImageInfo.SectorSize; i++)
+            for(int i = 0; i < imageInfo.SectorsPerTrack * imageInfo.SectorSize; i++)
             {
                 stream.Read(sectors, 0, sectors.Length);
-                stream.Seek(ImageInfo.SectorsPerTrack, SeekOrigin.Current);
+                stream.Seek(imageInfo.SectorsPerTrack, SeekOrigin.Current);
                 disk.Write(sectors, 0, sectors.Length);
             }
 
             switch(header.diskType)
             {
                 case RayDiskTypes.Md2hd:
-                    if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 15)
-                        ImageInfo.MediaType = MediaType.DOS_525_HD;
+                    if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 15)
+                        imageInfo.MediaType = MediaType.DOS_525_HD;
                     else goto case RayDiskTypes.Md2dd;
                     break;
                 case RayDiskTypes.Md2dd:
-                    if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 40 && ImageInfo.SectorsPerTrack == 8)
-                        ImageInfo.MediaType = MediaType.DOS_525_SS_DD_8;
-                    else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 40 && ImageInfo.SectorsPerTrack == 9)
-                        ImageInfo.MediaType = MediaType.DOS_525_SS_DD_9;
-                    else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 40 && ImageInfo.SectorsPerTrack == 8)
-                        ImageInfo.MediaType = MediaType.DOS_525_DS_DD_8;
-                    else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 40 && ImageInfo.SectorsPerTrack == 9)
-                        ImageInfo.MediaType = MediaType.DOS_525_DS_DD_9;
-                    else ImageInfo.MediaType = MediaType.Unknown;
+                    if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 8)
+                        imageInfo.MediaType = MediaType.DOS_525_SS_DD_8;
+                    else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 9)
+                        imageInfo.MediaType = MediaType.DOS_525_SS_DD_9;
+                    else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 8)
+                        imageInfo.MediaType = MediaType.DOS_525_DS_DD_8;
+                    else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 9)
+                        imageInfo.MediaType = MediaType.DOS_525_DS_DD_9;
+                    else imageInfo.MediaType = MediaType.Unknown;
                     break;
                 case RayDiskTypes.Mf2ed:
-                    if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 36)
-                        ImageInfo.MediaType = MediaType.DOS_35_ED;
+                    if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 36)
+                        imageInfo.MediaType = MediaType.DOS_35_ED;
                     else goto case RayDiskTypes.Mf2hd;
                     break;
                 case RayDiskTypes.Mf2hd:
-                    if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 18)
-                        ImageInfo.MediaType = MediaType.DOS_35_HD;
-                    else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 21)
-                        ImageInfo.MediaType = MediaType.DMF;
-                    else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 82 && ImageInfo.SectorsPerTrack == 21)
-                        ImageInfo.MediaType = MediaType.DMF_82;
-                    else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 15)
-                        ImageInfo.MediaType = MediaType.NEC_35_HD_15;
+                    if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 18)
+                        imageInfo.MediaType = MediaType.DOS_35_HD;
+                    else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 21)
+                        imageInfo.MediaType = MediaType.DMF;
+                    else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 82 && imageInfo.SectorsPerTrack == 21)
+                        imageInfo.MediaType = MediaType.DMF_82;
+                    else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 15)
+                        imageInfo.MediaType = MediaType.NEC_35_HD_15;
                     else goto case RayDiskTypes.Mf2dd;
                     break;
                 case RayDiskTypes.Mf2dd:
-                    if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 9)
-                        ImageInfo.MediaType = MediaType.DOS_35_DS_DD_9;
-                    else if(ImageInfo.Heads == 2 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 8)
-                        ImageInfo.MediaType = MediaType.DOS_35_DS_DD_8;
-                    else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 9)
-                        ImageInfo.MediaType = MediaType.DOS_35_SS_DD_9;
-                    else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 80 && ImageInfo.SectorsPerTrack == 8)
-                        ImageInfo.MediaType = MediaType.DOS_35_SS_DD_8;
-                    else if(ImageInfo.Heads == 1 && ImageInfo.Cylinders == 70 && ImageInfo.SectorsPerTrack == 9)
-                        ImageInfo.MediaType = MediaType.Apricot_35;
-                    else ImageInfo.MediaType = MediaType.Unknown;
+                    if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 9)
+                        imageInfo.MediaType = MediaType.DOS_35_DS_DD_9;
+                    else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 8)
+                        imageInfo.MediaType = MediaType.DOS_35_DS_DD_8;
+                    else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 9)
+                        imageInfo.MediaType = MediaType.DOS_35_SS_DD_9;
+                    else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 8)
+                        imageInfo.MediaType = MediaType.DOS_35_SS_DD_8;
+                    else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 70 && imageInfo.SectorsPerTrack == 9)
+                        imageInfo.MediaType = MediaType.Apricot_35;
+                    else imageInfo.MediaType = MediaType.Unknown;
                     break;
                 default:
-                    ImageInfo.MediaType = MediaType.Unknown;
+                    imageInfo.MediaType = MediaType.Unknown;
                     break;
             }
 
-            ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
 
             return true;
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             return null;
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
@@ -239,7 +242,7 @@ namespace DiscImageChef.DiscImages
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
@@ -250,93 +253,93 @@ namespace DiscImageChef.DiscImages
             return null;
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return null;
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
             return ReadSectors(sectorAddress, 1);
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
-            byte[] buffer = new byte[length * ImageInfo.SectorSize];
+            byte[] buffer = new byte[length * imageInfo.SectorSize];
 
-            disk.Seek((long)(sectorAddress * ImageInfo.SectorSize), SeekOrigin.Begin);
-            disk.Read(buffer, 0, (int)(length * ImageInfo.SectorSize));
+            disk.Seek((long)(sectorAddress * imageInfo.SectorSize), SeekOrigin.Begin);
+            disk.Read(buffer, 0, (int)(length * imageInfo.SectorSize));
 
             return buffer;
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
diff --git a/DiscImageChef.DiscImages/RsIde.cs b/DiscImageChef.DiscImages/RsIde.cs
index 7e37784b..ec36730a 100644
--- a/DiscImageChef.DiscImages/RsIde.cs
+++ b/DiscImageChef.DiscImages/RsIde.cs
@@ -41,19 +41,18 @@ using static DiscImageChef.Decoders.ATA.Identify;
 
 namespace DiscImageChef.DiscImages
 {
-    public class RsIde : ImagePlugin
+    public class RsIde : IMediaImage
     {
         readonly byte[] signature = {0x52, 0x53, 0x2D, 0x49, 0x44, 0x45, 0x1A};
         ushort dataOff;
         byte[] identify;
+        ImageInfo imageInfo;
 
-        Filter rsIdeImageFilter;
+        IFilter rsIdeImageFilter;
 
         public RsIde()
         {
-            Name = "RS-IDE Hard Disk Image";
-            PluginUuid = new Guid("47C3E78D-2BE2-4BA5-AA6B-FEE27C86FC65");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -78,18 +77,22 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "RS-IDE disk image";
+        public virtual string Name => "RS-IDE Hard Disk Image";
+        public virtual Guid Id => new Guid("47C3E78D-2BE2-4BA5-AA6B-FEE27C86FC65");
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Partitions =>
+        public virtual string ImageFormat => "RS-IDE disk image";
+
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Sessions =>
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -100,7 +103,7 @@ namespace DiscImageChef.DiscImages
             return magic.SequenceEqual(signature);
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -117,15 +120,15 @@ namespace DiscImageChef.DiscImages
 
             dataOff = hdr.dataOff;
 
-            ImageInfo.MediaType = MediaType.GENERIC_HDD;
-            ImageInfo.SectorSize = (uint)(hdr.flags.HasFlag(RsIdeFlags.HalfSectors) ? 256 : 512);
-            ImageInfo.ImageSize = (ulong)(stream.Length - dataOff);
-            ImageInfo.Sectors = ImageInfo.ImageSize / ImageInfo.SectorSize;
-            ImageInfo.CreationTime = imageFilter.GetCreationTime();
-            ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
-            ImageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
-            ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
-            ImageInfo.Version = $"{hdr.revision >> 8}.{hdr.revision & 0x0F}";
+            imageInfo.MediaType = MediaType.GENERIC_HDD;
+            imageInfo.SectorSize = (uint)(hdr.flags.HasFlag(RsIdeFlags.HalfSectors) ? 256 : 512);
+            imageInfo.ImageSize = (ulong)(stream.Length - dataOff);
+            imageInfo.Sectors = imageInfo.ImageSize / imageInfo.SectorSize;
+            imageInfo.CreationTime = imageFilter.GetCreationTime();
+            imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+            imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
+            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+            imageInfo.Version = $"{hdr.revision >> 8}.{hdr.revision & 0x0F}";
 
             if(!ArrayHelpers.ArrayIsNullOrEmpty(hdr.identify))
             {
@@ -135,23 +138,23 @@ namespace DiscImageChef.DiscImages
 
                 if(ataId.HasValue)
                 {
-                    ImageInfo.ReadableMediaTags.Add(MediaTagType.ATA_IDENTIFY);
-                    ImageInfo.Cylinders = ataId.Value.Cylinders;
-                    ImageInfo.Heads = ataId.Value.Heads;
-                    ImageInfo.SectorsPerTrack = ataId.Value.SectorsPerCard;
-                    ImageInfo.DriveFirmwareRevision = ataId.Value.FirmwareRevision;
-                    ImageInfo.DriveModel = ataId.Value.Model;
-                    ImageInfo.DriveSerialNumber = ataId.Value.SerialNumber;
-                    ImageInfo.MediaSerialNumber = ataId.Value.MediaSerial;
-                    ImageInfo.MediaManufacturer = ataId.Value.MediaManufacturer;
+                    imageInfo.ReadableMediaTags.Add(MediaTagType.ATA_IDENTIFY);
+                    imageInfo.Cylinders = ataId.Value.Cylinders;
+                    imageInfo.Heads = ataId.Value.Heads;
+                    imageInfo.SectorsPerTrack = ataId.Value.SectorsPerCard;
+                    imageInfo.DriveFirmwareRevision = ataId.Value.FirmwareRevision;
+                    imageInfo.DriveModel = ataId.Value.Model;
+                    imageInfo.DriveSerialNumber = ataId.Value.SerialNumber;
+                    imageInfo.MediaSerialNumber = ataId.Value.MediaSerial;
+                    imageInfo.MediaManufacturer = ataId.Value.MediaManufacturer;
                 }
             }
 
-            if(ImageInfo.Cylinders == 0 || ImageInfo.Heads == 0 || ImageInfo.SectorsPerTrack == 0)
+            if(imageInfo.Cylinders == 0 || imageInfo.Heads == 0 || imageInfo.SectorsPerTrack == 0)
             {
-                ImageInfo.Cylinders = (uint)(ImageInfo.Sectors / 16 / 63);
-                ImageInfo.Heads = 16;
-                ImageInfo.SectorsPerTrack = 63;
+                imageInfo.Cylinders = (uint)(imageInfo.Sectors / 16 / 63);
+                imageInfo.Heads = 16;
+                imageInfo.SectorsPerTrack = 63;
             }
 
             rsIdeImageFilter = imageFilter;
@@ -159,33 +162,33 @@ namespace DiscImageChef.DiscImages
             return true;
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
             return ReadSectors(sectorAddress, 1);
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
-            byte[] buffer = new byte[length * ImageInfo.SectorSize];
+            byte[] buffer = new byte[length * imageInfo.SectorSize];
 
             Stream stream = rsIdeImageFilter.GetDataForkStream();
 
-            stream.Seek((long)(dataOff + sectorAddress * ImageInfo.SectorSize), SeekOrigin.Begin);
+            stream.Seek((long)(dataOff + sectorAddress * imageInfo.SectorSize), SeekOrigin.Begin);
 
-            stream.Read(buffer, 0, (int)(length * ImageInfo.SectorSize));
+            stream.Read(buffer, 0, (int)(length * imageInfo.SectorSize));
 
             return buffer;
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
-            if(!ImageInfo.ReadableMediaTags.Contains(tag) || tag != MediaTagType.ATA_IDENTIFY)
+            if(!imageInfo.ReadableMediaTags.Contains(tag) || tag != MediaTagType.ATA_IDENTIFY)
                 throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
             byte[] buffer = new byte[512];
@@ -193,93 +196,93 @@ namespace DiscImageChef.DiscImages
             return buffer;
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             return null;
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
             unknownLbas = new List();
-            for(ulong i = 0; i < ImageInfo.Sectors; i++) unknownLbas.Add(i);
+            for(ulong i = 0; i < imageInfo.Sectors; i++) unknownLbas.Add(i);
 
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return null;
         }
diff --git a/DiscImageChef.DiscImages/SaveDskF.cs b/DiscImageChef.DiscImages/SaveDskF.cs
index 8f51427b..10700e9e 100644
--- a/DiscImageChef.DiscImages/SaveDskF.cs
+++ b/DiscImageChef.DiscImages/SaveDskF.cs
@@ -41,7 +41,7 @@ using DiscImageChef.Filters;
 
 namespace DiscImageChef.DiscImages
 {
-    public class SaveDskF : ImagePlugin
+    public class SaveDskF : IMediaImage
     {
         const ushort SDF_MAGIC_OLD = 0x58AA;
         const ushort SDF_MAGIC = 0x59AA;
@@ -50,12 +50,11 @@ namespace DiscImageChef.DiscImages
         byte[] decodedDisk;
 
         SaveDskFHeader header;
+        ImageInfo imageInfo;
 
         public SaveDskF()
         {
-            Name = "IBM SaveDskF";
-            PluginUuid = new Guid("288CE058-1A51-4034-8C45-5A256CAE1461");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -80,18 +79,22 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "IBM SaveDskF";
+        public virtual string Name => "IBM SaveDskF";
+        public virtual Guid Id => new Guid("288CE058-1A51-4034-8C45-5A256CAE1461");
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Partitions =>
+        public virtual string ImageFormat => "IBM SaveDskF";
+
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Sessions =>
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -111,7 +114,7 @@ namespace DiscImageChef.DiscImages
                    header.commentOffset < stream.Length && header.dataOffset < stream.Length;
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -150,7 +153,7 @@ namespace DiscImageChef.DiscImages
             byte[] cmt = new byte[header.dataOffset - header.commentOffset];
             stream.Seek(header.commentOffset, SeekOrigin.Begin);
             stream.Read(cmt, 0, cmt.Length);
-            if(cmt.Length > 1) ImageInfo.Comments = StringHandlers.CToString(cmt, Encoding.GetEncoding("ibm437"));
+            if(cmt.Length > 1) imageInfo.Comments = StringHandlers.CToString(cmt, Encoding.GetEncoding("ibm437"));
 
             calculatedChk = 0;
             stream.Seek(0, SeekOrigin.Begin);
@@ -166,15 +169,15 @@ namespace DiscImageChef.DiscImages
             DicConsole.DebugWriteLine("SaveDskF plugin", "Calculated checksum = 0x{0:X8}, {1}", calculatedChk,
                                       calculatedChk == header.checksum);
 
-            ImageInfo.Application = "SaveDskF";
-            ImageInfo.CreationTime = imageFilter.GetCreationTime();
-            ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
-            ImageInfo.MediaTitle = imageFilter.GetFilename();
-            ImageInfo.ImageSize = (ulong)(stream.Length - header.dataOffset);
-            ImageInfo.Sectors = (ulong)(header.sectorsPerTrack * header.heads * header.cylinders);
-            ImageInfo.SectorSize = header.sectorSize;
+            imageInfo.Application = "SaveDskF";
+            imageInfo.CreationTime = imageFilter.GetCreationTime();
+            imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+            imageInfo.MediaTitle = imageFilter.GetFilename();
+            imageInfo.ImageSize = (ulong)(stream.Length - header.dataOffset);
+            imageInfo.Sectors = (ulong)(header.sectorsPerTrack * header.heads * header.cylinders);
+            imageInfo.SectorSize = header.sectorSize;
 
-            ImageInfo.MediaType = MediaType.Unknown;
+            imageInfo.MediaType = MediaType.Unknown;
             switch(header.cylinders)
             {
                 case 40:
@@ -184,10 +187,10 @@ namespace DiscImageChef.DiscImages
                             switch(header.sectorsPerTrack)
                             {
                                 case 8:
-                                    ImageInfo.MediaType = MediaType.DOS_525_SS_DD_8;
+                                    imageInfo.MediaType = MediaType.DOS_525_SS_DD_8;
                                     break;
                                 case 9:
-                                    ImageInfo.MediaType = MediaType.DOS_525_SS_DD_9;
+                                    imageInfo.MediaType = MediaType.DOS_525_SS_DD_9;
                                     break;
                             }
 
@@ -196,10 +199,10 @@ namespace DiscImageChef.DiscImages
                             switch(header.sectorsPerTrack)
                             {
                                 case 8:
-                                    ImageInfo.MediaType = MediaType.DOS_525_DS_DD_8;
+                                    imageInfo.MediaType = MediaType.DOS_525_DS_DD_8;
                                     break;
                                 case 9:
-                                    ImageInfo.MediaType = MediaType.DOS_525_DS_DD_9;
+                                    imageInfo.MediaType = MediaType.DOS_525_DS_DD_9;
                                     break;
                             }
 
@@ -214,7 +217,7 @@ namespace DiscImageChef.DiscImages
                             switch(header.sectorsPerTrack)
                             {
                                 case 9:
-                                    ImageInfo.MediaType = MediaType.Apricot_35;
+                                    imageInfo.MediaType = MediaType.Apricot_35;
                                     break;
                             }
 
@@ -229,10 +232,10 @@ namespace DiscImageChef.DiscImages
                             switch(header.sectorsPerTrack)
                             {
                                 case 8:
-                                    ImageInfo.MediaType = MediaType.DOS_35_SS_DD_8;
+                                    imageInfo.MediaType = MediaType.DOS_35_SS_DD_8;
                                     break;
                                 case 9:
-                                    ImageInfo.MediaType = MediaType.DOS_35_SS_DD_9;
+                                    imageInfo.MediaType = MediaType.DOS_35_SS_DD_9;
                                     break;
                             }
 
@@ -241,22 +244,22 @@ namespace DiscImageChef.DiscImages
                             switch(header.sectorsPerTrack)
                             {
                                 case 8:
-                                    ImageInfo.MediaType = MediaType.DOS_35_DS_DD_8;
+                                    imageInfo.MediaType = MediaType.DOS_35_DS_DD_8;
                                     break;
                                 case 9:
-                                    ImageInfo.MediaType = MediaType.DOS_35_DS_DD_9;
+                                    imageInfo.MediaType = MediaType.DOS_35_DS_DD_9;
                                     break;
                                 case 15:
-                                    ImageInfo.MediaType = MediaType.DOS_525_HD;
+                                    imageInfo.MediaType = MediaType.DOS_525_HD;
                                     break;
                                 case 18:
-                                    ImageInfo.MediaType = MediaType.DOS_35_HD;
+                                    imageInfo.MediaType = MediaType.DOS_35_HD;
                                     break;
                                 case 23:
-                                    ImageInfo.MediaType = MediaType.XDF_35;
+                                    imageInfo.MediaType = MediaType.XDF_35;
                                     break;
                                 case 36:
-                                    ImageInfo.MediaType = MediaType.DOS_35_ED;
+                                    imageInfo.MediaType = MediaType.DOS_35_ED;
                                     break;
                             }
 
@@ -265,15 +268,15 @@ namespace DiscImageChef.DiscImages
 
                     break;
                 default:
-                    ImageInfo.MediaType = MediaType.Unknown;
+                    imageInfo.MediaType = MediaType.Unknown;
                     break;
             }
 
-            ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
 
-            DicConsole.VerboseWriteLine("SaveDskF image contains a disk of type {0}", ImageInfo.MediaType);
-            if(!string.IsNullOrEmpty(ImageInfo.Comments))
-                DicConsole.VerboseWriteLine("SaveDskF comments: {0}", ImageInfo.Comments);
+            DicConsole.VerboseWriteLine("SaveDskF image contains a disk of type {0}", imageInfo.MediaType);
+            if(!string.IsNullOrEmpty(imageInfo.Comments))
+                DicConsole.VerboseWriteLine("SaveDskF comments: {0}", imageInfo.Comments);
 
             // TODO: Support compressed images
             if(header.magic == SDF_MAGIC_COMPRESSED)
@@ -282,27 +285,27 @@ namespace DiscImageChef.DiscImages
 
             // SaveDskF only ommits ending clusters, leaving no gaps behind, so reading all data we have...
             stream.Seek(header.dataOffset, SeekOrigin.Begin);
-            decodedDisk = new byte[ImageInfo.Sectors * ImageInfo.SectorSize];
+            decodedDisk = new byte[imageInfo.Sectors * imageInfo.SectorSize];
             stream.Read(decodedDisk, 0, (int)(stream.Length - header.dataOffset));
 
-            ImageInfo.Cylinders = header.cylinders;
-            ImageInfo.Heads = header.heads;
-            ImageInfo.SectorsPerTrack = header.sectorsPerTrack;
+            imageInfo.Cylinders = header.cylinders;
+            imageInfo.Heads = header.heads;
+            imageInfo.SectorsPerTrack = header.sectorsPerTrack;
 
             return true;
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             return null;
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
@@ -313,7 +316,7 @@ namespace DiscImageChef.DiscImages
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
@@ -324,93 +327,93 @@ namespace DiscImageChef.DiscImages
             return null;
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return calculatedChk == header.checksum;
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
             return ReadSectors(sectorAddress, 1);
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
-            byte[] buffer = new byte[length * ImageInfo.SectorSize];
+            byte[] buffer = new byte[length * imageInfo.SectorSize];
 
-            Array.Copy(decodedDisk, (int)sectorAddress * ImageInfo.SectorSize, buffer, 0,
-                       length * ImageInfo.SectorSize);
+            Array.Copy(decodedDisk, (int)sectorAddress * imageInfo.SectorSize, buffer, 0,
+                       length * imageInfo.SectorSize);
 
             return buffer;
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
diff --git a/DiscImageChef.DiscImages/ImageInfo.cs b/DiscImageChef.DiscImages/Structs.cs
similarity index 64%
rename from DiscImageChef.DiscImages/ImageInfo.cs
rename to DiscImageChef.DiscImages/Structs.cs
index 9e64aa42..9e7301cb 100644
--- a/DiscImageChef.DiscImages/ImageInfo.cs
+++ b/DiscImageChef.DiscImages/Structs.cs
@@ -1,15 +1,15 @@
-// /***************************************************************************
+// /***************************************************************************
 // The Disc Image Chef
 // ----------------------------------------------------------------------------
 //
-// Filename       : ImageInfo.cs
+// Filename       : IMediaImage.cs
 // Author(s)      : Natalia Portillo 
 //
 // Component      : Disc image plugins.
 //
 // --[ Description ] ----------------------------------------------------------
 //
-//     Defines a common structure with information about a disk image.
+//     Defines structures to be used by disc image plugins.
 //
 // --[ License ] --------------------------------------------------------------
 //
@@ -33,6 +33,7 @@
 using System;
 using System.Collections.Generic;
 using DiscImageChef.CommonTypes;
+using DiscImageChef.Filters;
 
 namespace DiscImageChef.DiscImages
 {
@@ -105,4 +106,64 @@ namespace DiscImageChef.DiscImages
         /// Sectors per track of the media represented by the image (for variable image, the smallest)
         public uint SectorsPerTrack;
     }
+
+    /// 
+    ///     Session defining structure.
+    /// 
+    public struct Session
+    {
+        /// Session number, 1-started
+        public ushort SessionSequence;
+        /// First track present on this session
+        public uint StartTrack;
+        /// Last track present on this session
+        public uint EndTrack;
+        /// First sector present on this session
+        public ulong StartSector;
+        /// Last sector present on this session
+        public ulong EndSector;
+    }
+
+    /// 
+    ///     Track defining structure.
+    /// 
+    public struct Track
+    {
+        /// Track number, 1-started
+        public uint TrackSequence;
+        /// Partition type
+        public TrackType TrackType;
+        /// Track starting sector
+        public ulong TrackStartSector;
+        /// Track ending sector
+        public ulong TrackEndSector;
+        /// Track pre-gap
+        public ulong TrackPregap;
+        /// Session this track belongs to
+        public ushort TrackSession;
+        /// Information that does not find space in this struct
+        public string TrackDescription;
+        /// Indexes, 00 to 99 and sector offset
+        public Dictionary Indexes;
+        /// Which filter stores this track
+        public IFilter TrackFilter;
+        /// Which file stores this track
+        public string TrackFile;
+        /// Starting at which byte is this track stored
+        public ulong TrackFileOffset;
+        /// What kind of file is storing this track
+        public string TrackFileType;
+        /// How many main channel / user data bytes are per sector in this track
+        public int TrackBytesPerSector;
+        /// How many main channel bytes per sector are in the file with this track
+        public int TrackRawBytesPerSector;
+        /// Which filter stores this track's subchannel
+        public IFilter TrackSubchannelFilter;
+        /// Which file stores this track's subchannel
+        public string TrackSubchannelFile;
+        /// Starting at which byte are this track's subchannel stored
+        public ulong TrackSubchannelOffset;
+        /// Type of subchannel stored for this track
+        public TrackSubchannelType TrackSubchannelType;
+    }
 }
\ No newline at end of file
diff --git a/DiscImageChef.DiscImages/SuperCardPro.cs b/DiscImageChef.DiscImages/SuperCardPro.cs
index db0f7ebe..624923c3 100644
--- a/DiscImageChef.DiscImages/SuperCardPro.cs
+++ b/DiscImageChef.DiscImages/SuperCardPro.cs
@@ -42,7 +42,7 @@ using DiscImageChef.Filters;
 
 namespace DiscImageChef.DiscImages
 {
-    public class SuperCardPro : ImagePlugin
+    public class SuperCardPro : IMediaImage
     {
         public enum ScpDiskType : byte
         {
@@ -115,14 +115,13 @@ namespace DiscImageChef.DiscImages
 
         // TODO: These variables have been made public so create-sidecar can access to this information until I define an API >4.0
         public ScpHeader Header;
+        ImageInfo imageInfo;
         Stream scpStream;
         public Dictionary ScpTracks;
 
         public SuperCardPro()
         {
-            Name = "SuperCardPro";
-            PluginUuid = new Guid("C5D3182E-1D45-4767-A205-E6E5C83444DC");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -147,18 +146,23 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "SuperCardPro";
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Partitions =>
+        public virtual string Name => "SuperCardPro";
+        public virtual Guid Id => new Guid("C5D3182E-1D45-4767-A205-E6E5C83444DC");
+
+        public virtual string ImageFormat => "SuperCardPro";
+
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Sessions =>
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             Header = new ScpHeader();
             Stream stream = imageFilter.GetDataForkStream();
@@ -176,7 +180,7 @@ namespace DiscImageChef.DiscImages
             return scpSignature.SequenceEqual(Header.signature);
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             Header = new ScpHeader();
             scpStream = imageFilter.GetDataForkStream();
@@ -304,45 +308,44 @@ namespace DiscImageChef.DiscImages
                         DicConsole.DebugWriteLine("SuperCardPro plugin", "footer.signature = \"{0}\"",
                                                   StringHandlers.CToString(BitConverter.GetBytes(footer.signature)));
 
-                        ImageInfo.DriveManufacturer = ReadPStringUtf8(scpStream, footer.manufacturerOffset);
-                        ImageInfo.DriveModel = ReadPStringUtf8(scpStream, footer.modelOffset);
-                        ImageInfo.DriveSerialNumber = ReadPStringUtf8(scpStream, footer.serialOffset);
-                        ImageInfo.Creator = ReadPStringUtf8(scpStream, footer.creatorOffset);
-                        ImageInfo.Application = ReadPStringUtf8(scpStream, footer.applicationOffset);
-                        ImageInfo.Comments = ReadPStringUtf8(scpStream, footer.commentsOffset);
+                        imageInfo.DriveManufacturer = ReadPStringUtf8(scpStream, footer.manufacturerOffset);
+                        imageInfo.DriveModel = ReadPStringUtf8(scpStream, footer.modelOffset);
+                        imageInfo.DriveSerialNumber = ReadPStringUtf8(scpStream, footer.serialOffset);
+                        imageInfo.Creator = ReadPStringUtf8(scpStream, footer.creatorOffset);
+                        imageInfo.Application = ReadPStringUtf8(scpStream, footer.applicationOffset);
+                        imageInfo.Comments = ReadPStringUtf8(scpStream, footer.commentsOffset);
 
                         DicConsole.DebugWriteLine("SuperCardPro plugin", "ImageInfo.driveManufacturer = \"{0}\"",
-                                                  ImageInfo.DriveManufacturer);
+                                                  imageInfo.DriveManufacturer);
                         DicConsole.DebugWriteLine("SuperCardPro plugin", "ImageInfo.driveModel = \"{0}\"",
-                                                  ImageInfo.DriveModel);
+                                                  imageInfo.DriveModel);
                         DicConsole.DebugWriteLine("SuperCardPro plugin", "ImageInfo.driveSerialNumber = \"{0}\"",
-                                                  ImageInfo.DriveSerialNumber);
+                                                  imageInfo.DriveSerialNumber);
                         DicConsole.DebugWriteLine("SuperCardPro plugin", "ImageInfo.imageCreator = \"{0}\"",
-                                                  ImageInfo.Creator);
+                                                  imageInfo.Creator);
                         DicConsole.DebugWriteLine("SuperCardPro plugin", "ImageInfo.imageApplication = \"{0}\"",
-                                                  ImageInfo.Application);
+                                                  imageInfo.Application);
                         DicConsole.DebugWriteLine("SuperCardPro plugin", "ImageInfo.imageComments = \"{0}\"",
-                                                  ImageInfo.Comments);
+                                                  imageInfo.Comments);
 
-                        ImageInfo.CreationTime = footer.creationTime != 0
-                                                          ? DateHandlers.UnixToDateTime(footer.creationTime)
-                                                          : imageFilter.GetCreationTime();
+                        imageInfo.CreationTime = footer.creationTime != 0
+                                                     ? DateHandlers.UnixToDateTime(footer.creationTime)
+                                                     : imageFilter.GetCreationTime();
 
-                        ImageInfo.LastModificationTime =
-                            footer.modificationTime != 0
-                                ? DateHandlers.UnixToDateTime(footer.modificationTime)
-                                : imageFilter.GetLastWriteTime();
+                        imageInfo.LastModificationTime = footer.modificationTime != 0
+                                                             ? DateHandlers.UnixToDateTime(footer.modificationTime)
+                                                             : imageFilter.GetLastWriteTime();
 
                         DicConsole.DebugWriteLine("SuperCardPro plugin", "ImageInfo.imageCreationTime = {0}",
-                                                  ImageInfo.CreationTime);
+                                                  imageInfo.CreationTime);
                         DicConsole.DebugWriteLine("SuperCardPro plugin", "ImageInfo.imageLastModificationTime = {0}",
-                                                  ImageInfo.LastModificationTime);
+                                                  imageInfo.LastModificationTime);
 
-                        ImageInfo.ApplicationVersion =
+                        imageInfo.ApplicationVersion =
                             $"{(footer.applicationVersion & 0xF0) >> 4}.{footer.applicationVersion & 0xF}";
-                        ImageInfo.DriveFirmwareRevision =
+                        imageInfo.DriveFirmwareRevision =
                             $"{(footer.firmwareVersion & 0xF0) >> 4}.{footer.firmwareVersion & 0xF}";
-                        ImageInfo.Version = $"{(footer.imageVersion & 0xF0) >> 4}.{footer.imageVersion & 0xF}";
+                        imageInfo.Version = $"{(footer.imageVersion & 0xF0) >> 4}.{footer.imageVersion & 0xF}";
 
                         break;
                     }
@@ -352,11 +355,11 @@ namespace DiscImageChef.DiscImages
             }
             else
             {
-                ImageInfo.Application = "SuperCardPro";
-                ImageInfo.ApplicationVersion = $"{(Header.version & 0xF0) >> 4}.{Header.version & 0xF}";
-                ImageInfo.CreationTime = imageFilter.GetCreationTime();
-                ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
-                ImageInfo.Version = "1.5";
+                imageInfo.Application = "SuperCardPro";
+                imageInfo.ApplicationVersion = $"{(Header.version & 0xF0) >> 4}.{Header.version & 0xF}";
+                imageInfo.CreationTime = imageFilter.GetCreationTime();
+                imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+                imageInfo.Version = "1.5";
             }
 
             throw new NotImplementedException("Flux decoding is not yet implemented.");
@@ -379,58 +382,58 @@ namespace DiscImageChef.DiscImages
             return Encoding.UTF8.GetString(str);
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new NotImplementedException("Flux decoding is not yet implemented.");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
             return ReadSectors(sectorAddress, 1);
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             throw new NotImplementedException("Flux decoding is not yet implemented.");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
             throw new NotImplementedException("Flux decoding is not yet implemented.");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             throw new NotImplementedException("Flux decoding is not yet implemented.");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             throw new NotImplementedException("Flux decoding is not yet implemented.");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             throw new NotImplementedException("Flux decoding is not yet implemented.");
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             throw new NotImplementedException("Flux decoding is not yet implemented.");
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             throw new NotImplementedException("Flux decoding is not yet implemented.");
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             if(Header.flags.HasFlag(ScpFlags.Writable)) return null;
 
@@ -445,47 +448,47 @@ namespace DiscImageChef.DiscImages
             return Header.checksum == sum;
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
diff --git a/DiscImageChef.DiscImages/T98.cs b/DiscImageChef.DiscImages/T98.cs
index 16dd7bad..3a99b134 100644
--- a/DiscImageChef.DiscImages/T98.cs
+++ b/DiscImageChef.DiscImages/T98.cs
@@ -39,15 +39,14 @@ using DiscImageChef.Filters;
 
 namespace DiscImageChef.DiscImages
 {
-    public class T98 : ImagePlugin
+    public class T98 : IMediaImage
     {
-        Filter t98ImageFilter;
+        ImageInfo imageInfo;
+        IFilter t98ImageFilter;
 
         public T98()
         {
-            Name = "T98 Hard Disk Image";
-            PluginUuid = new Guid("0410003E-6E7B-40E6-9328-BA5651ADF6B7");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -72,18 +71,22 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "T98 disk image";
+        public virtual string Name => "T98 Hard Disk Image";
+        public virtual Guid Id => new Guid("0410003E-6E7B-40E6-9328-BA5651ADF6B7");
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Partitions =>
+        public virtual string ImageFormat => "T98 disk image";
+
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Sessions =>
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -104,7 +107,7 @@ namespace DiscImageChef.DiscImages
             return stream.Length == cylinders * 8 * 33 * 256 + 256;
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -118,140 +121,140 @@ namespace DiscImageChef.DiscImages
 
             int cylinders = BitConverter.ToInt32(hdrB, 0);
 
-            ImageInfo.MediaType = MediaType.GENERIC_HDD;
+            imageInfo.MediaType = MediaType.GENERIC_HDD;
 
-            ImageInfo.ImageSize = (ulong)(stream.Length - 256);
-            ImageInfo.CreationTime = imageFilter.GetCreationTime();
-            ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
-            ImageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
-            ImageInfo.Sectors = (ulong)(stream.Length / 256 - 1);
-            ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
-            ImageInfo.SectorSize = 256;
-            ImageInfo.Cylinders = (uint)cylinders;
-            ImageInfo.Heads = 8;
-            ImageInfo.SectorsPerTrack = 33;
+            imageInfo.ImageSize = (ulong)(stream.Length - 256);
+            imageInfo.CreationTime = imageFilter.GetCreationTime();
+            imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+            imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
+            imageInfo.Sectors = (ulong)(stream.Length / 256 - 1);
+            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+            imageInfo.SectorSize = 256;
+            imageInfo.Cylinders = (uint)cylinders;
+            imageInfo.Heads = 8;
+            imageInfo.SectorsPerTrack = 33;
 
             t98ImageFilter = imageFilter;
 
             return true;
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
             return ReadSectors(sectorAddress, 1);
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
-            byte[] buffer = new byte[length * ImageInfo.SectorSize];
+            byte[] buffer = new byte[length * imageInfo.SectorSize];
 
             Stream stream = t98ImageFilter.GetDataForkStream();
 
-            stream.Seek((long)(256 + sectorAddress * ImageInfo.SectorSize), SeekOrigin.Begin);
+            stream.Seek((long)(256 + sectorAddress * imageInfo.SectorSize), SeekOrigin.Begin);
 
-            stream.Read(buffer, 0, (int)(length * ImageInfo.SectorSize));
+            stream.Read(buffer, 0, (int)(length * imageInfo.SectorSize));
 
             return buffer;
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             return null;
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
             unknownLbas = new List();
-            for(ulong i = 0; i < ImageInfo.Sectors; i++) unknownLbas.Add(i);
+            for(ulong i = 0; i < imageInfo.Sectors; i++) unknownLbas.Add(i);
 
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return null;
         }
diff --git a/DiscImageChef.DiscImages/TeleDisk.cs b/DiscImageChef.DiscImages/TeleDisk.cs
index d4a4b451..f01b76d3 100644
--- a/DiscImageChef.DiscImages/TeleDisk.cs
+++ b/DiscImageChef.DiscImages/TeleDisk.cs
@@ -47,7 +47,7 @@ namespace DiscImageChef.DiscImages
 {
     // Created following notes from Dave Dunfield
     // http://www.classiccmp.org/dunfield/img54306/td0notes.txt
-    public class TeleDisk : ImagePlugin
+    public class TeleDisk : IMediaImage
     {
         // "TD" as little endian uint.
         const ushort TD_MAGIC = 0x4454;
@@ -113,6 +113,7 @@ namespace DiscImageChef.DiscImages
         TeleDiskCommentBlockHeader commentHeader;
 
         TeleDiskHeader header;
+        ImageInfo imageInfo;
         Stream inStream;
         byte[] leadOut;
         // Cylinder by head, sector data matrix
@@ -123,9 +124,7 @@ namespace DiscImageChef.DiscImages
 
         public TeleDisk()
         {
-            Name = "Sydex TeleDisk";
-            PluginUuid = new Guid("0240B7B1-E959-4CDC-B0BD-386D6E467B88");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -150,18 +149,23 @@ namespace DiscImageChef.DiscImages
             sectorsWhereCrcHasFailed = new List();
         }
 
-        public override string ImageFormat => "Sydex TeleDisk";
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Partitions =>
+        public virtual string Name => "Sydex TeleDisk";
+        public virtual Guid Id => new Guid("0240B7B1-E959-4CDC-B0BD-386D6E467B88");
+
+        public virtual string ImageFormat => "Sydex TeleDisk";
+
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Sessions =>
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             header = new TeleDiskHeader();
             byte[] headerBytes = new byte[12];
@@ -217,7 +221,7 @@ namespace DiscImageChef.DiscImages
                    header.DriveType == DRIVE_TYPE_8_INCH;
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             header = new TeleDiskHeader();
             byte[] headerBytes = new byte[12];
@@ -242,9 +246,9 @@ namespace DiscImageChef.DiscImages
             header.Sides = headerBytes[9];
             header.Crc = BitConverter.ToUInt16(headerBytes, 10);
 
-            ImageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
-            ImageInfo.Version = $"{(header.Version & 0xF0) >> 4}.{header.Version & 0x0F}";
-            ImageInfo.Application = ImageInfo.Version;
+            imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
+            imageInfo.Version = $"{(header.Version & 0xF0) >> 4}.{header.Version & 0x0F}";
+            imageInfo.Application = imageInfo.Version;
 
             byte[] headerBytesForCrc = new byte[10];
             Array.Copy(headerBytes, headerBytesForCrc, 10);
@@ -303,7 +307,7 @@ namespace DiscImageChef.DiscImages
 
             stream.Seek(12, SeekOrigin.Begin);
 
-            ImageInfo.CreationTime = DateTime.MinValue;
+            imageInfo.CreationTime = DateTime.MinValue;
 
             if((header.Stepping & COMMENT_BLOCK_PRESENT) == COMMENT_BLOCK_PRESENT)
             {
@@ -348,35 +352,34 @@ namespace DiscImageChef.DiscImages
                     // Replace NULLs, used by TeleDisk as newline markers, with UNIX newline marker
                     if(commentBlock[i] == 0x00) commentBlock[i] = 0x0A;
 
-                ImageInfo.Comments = Encoding.ASCII.GetString(commentBlock);
+                imageInfo.Comments = Encoding.ASCII.GetString(commentBlock);
 
                 DicConsole.DebugWriteLine("TeleDisk plugin", "Comment");
-                DicConsole.DebugWriteLine("TeleDisk plugin", "{0}", ImageInfo.Comments);
+                DicConsole.DebugWriteLine("TeleDisk plugin", "{0}", imageInfo.Comments);
 
-                ImageInfo.CreationTime = new DateTime(commentHeader.Year + 1900, commentHeader.Month + 1,
-                                                           commentHeader.Day, commentHeader.Hour, commentHeader.Minute,
-                                                           commentHeader.Second, DateTimeKind.Unspecified);
+                imageInfo.CreationTime = new DateTime(commentHeader.Year + 1900, commentHeader.Month + 1,
+                                                      commentHeader.Day, commentHeader.Hour, commentHeader.Minute,
+                                                      commentHeader.Second, DateTimeKind.Unspecified);
             }
 
-            if(ImageInfo.CreationTime == DateTime.MinValue)
-                ImageInfo.CreationTime = imageFilter.GetCreationTime();
-            ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+            if(imageInfo.CreationTime == DateTime.MinValue) imageInfo.CreationTime = imageFilter.GetCreationTime();
+            imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
 
-            DicConsole.DebugWriteLine("TeleDisk plugin", "Image created on {0}", ImageInfo.CreationTime);
-            DicConsole.DebugWriteLine("TeleDisk plugin", "Image modified on {0}", ImageInfo.LastModificationTime);
+            DicConsole.DebugWriteLine("TeleDisk plugin", "Image created on {0}", imageInfo.CreationTime);
+            DicConsole.DebugWriteLine("TeleDisk plugin", "Image modified on {0}", imageInfo.LastModificationTime);
 
             DicConsole.DebugWriteLine("TeleDisk plugin", "Parsing image");
 
             totalDiskSize = 0;
-            ImageInfo.ImageSize = 0;
+            imageInfo.ImageSize = 0;
 
             int totalCylinders = -1;
             int totalHeads = -1;
             int maxSector = -1;
             int totalSectors = 0;
             long currentPos = stream.Position;
-            ImageInfo.SectorSize = uint.MaxValue;
-            ImageInfo.SectorsPerTrack = uint.MaxValue;
+            imageInfo.SectorSize = uint.MaxValue;
+            imageInfo.SectorsPerTrack = uint.MaxValue;
 
             // Count cylinders
             while(true)
@@ -421,8 +424,8 @@ namespace DiscImageChef.DiscImages
                         stream.Read(data, 0, teleDiskData.DataSize);
                     }
 
-                    if(128 << teleDiskSector.SectorSize < ImageInfo.SectorSize)
-                        ImageInfo.SectorSize = (uint)(128 << teleDiskSector.SectorSize);
+                    if(128 << teleDiskSector.SectorSize < imageInfo.SectorSize)
+                        imageInfo.SectorSize = (uint)(128 << teleDiskSector.SectorSize);
 
                     totalSectors++;
                 }
@@ -436,8 +439,8 @@ namespace DiscImageChef.DiscImages
 
             bool hasLeadOutOnHead0 = false;
             bool hasLeadOutOnHead1 = false;
-            ImageInfo.Cylinders = (ushort)totalCylinders;
-            ImageInfo.Heads = (byte)totalHeads;
+            imageInfo.Cylinders = (ushort)totalCylinders;
+            imageInfo.Heads = (byte)totalHeads;
 
             // Count sectors per track
             stream.Seek(currentPos, SeekOrigin.Begin);
@@ -454,14 +457,14 @@ namespace DiscImageChef.DiscImages
                 if(teleDiskTrack.Sectors == 0xFF) // End of disk image
                     break;
 
-                if(teleDiskTrack.Sectors < ImageInfo.SectorsPerTrack)
+                if(teleDiskTrack.Sectors < imageInfo.SectorsPerTrack)
                     if(teleDiskTrack.Cylinder + 1 == totalCylinders)
                     {
                         hasLeadOutOnHead0 |= teleDiskTrack.Head == 0;
                         hasLeadOutOnHead1 |= teleDiskTrack.Head == 1;
-                        if(ImageInfo.Cylinders == totalCylinders) ImageInfo.Cylinders--;
+                        if(imageInfo.Cylinders == totalCylinders) imageInfo.Cylinders--;
                     }
-                    else ImageInfo.SectorsPerTrack = teleDiskTrack.Sectors;
+                    else imageInfo.SectorsPerTrack = teleDiskTrack.Sectors;
                 for(byte processedSectors = 0; processedSectors < teleDiskTrack.Sectors; processedSectors++)
                 {
                     TeleDiskSectorHeader teleDiskSector = new TeleDiskSectorHeader();
@@ -566,8 +569,8 @@ namespace DiscImageChef.DiscImages
                     DicConsole.DebugWriteLine("TeleDisk plugin", "\t\tSector CRC (plus headers): 0x{0:X2}",
                                               teleDiskSector.Crc);
 
-                    uint lba = (uint)(teleDiskSector.Cylinder * header.Sides * ImageInfo.SectorsPerTrack +
-                                      teleDiskSector.Head * ImageInfo.SectorsPerTrack +
+                    uint lba = (uint)(teleDiskSector.Cylinder * header.Sides * imageInfo.SectorsPerTrack +
+                                      teleDiskSector.Head * imageInfo.SectorsPerTrack +
                                       (teleDiskSector.SectorNumber - 1));
                     if((teleDiskSector.Flags & FLAGS_SECTOR_DATALESS) != FLAGS_SECTOR_DATALESS &&
                        (teleDiskSector.Flags & FLAGS_SECTOR_SKIPPED) != FLAGS_SECTOR_SKIPPED)
@@ -575,7 +578,7 @@ namespace DiscImageChef.DiscImages
                         stream.Read(dataSizeBytes, 0, 2);
                         teleDiskData.DataSize = BitConverter.ToUInt16(dataSizeBytes, 0);
                         teleDiskData.DataSize--; // Sydex decided to including dataEncoding byte as part of it
-                        ImageInfo.ImageSize += teleDiskData.DataSize;
+                        imageInfo.ImageSize += teleDiskData.DataSize;
                         teleDiskData.DataEncoding = (byte)stream.ReadByte();
                         byte[] data = new byte[teleDiskData.DataSize];
                         stream.Read(data, 0, teleDiskData.DataSize);
@@ -636,17 +639,17 @@ namespace DiscImageChef.DiscImages
             if(leadOutMs.Length != 0)
             {
                 leadOut = leadOutMs.ToArray();
-                ImageInfo.ReadableMediaTags.Add(MediaTagType.Floppy_LeadOut);
+                imageInfo.ReadableMediaTags.Add(MediaTagType.Floppy_LeadOut);
             }
 
-            ImageInfo.Sectors = ImageInfo.Cylinders * ImageInfo.Heads * ImageInfo.SectorsPerTrack;
-            ImageInfo.MediaType = DecodeTeleDiskDiskType();
+            imageInfo.Sectors = imageInfo.Cylinders * imageInfo.Heads * imageInfo.SectorsPerTrack;
+            imageInfo.MediaType = DecodeTeleDiskDiskType();
 
-            ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
 
-            DicConsole.VerboseWriteLine("TeleDisk image contains a disk of type {0}", ImageInfo.MediaType);
-            if(!string.IsNullOrEmpty(ImageInfo.Comments))
-                DicConsole.VerboseWriteLine("TeleDisk comments: {0}", ImageInfo.Comments);
+            DicConsole.VerboseWriteLine("TeleDisk image contains a disk of type {0}", imageInfo.MediaType);
+            if(!string.IsNullOrEmpty(imageInfo.Comments))
+                DicConsole.VerboseWriteLine("TeleDisk comments: {0}", imageInfo.Comments);
 
             inStream.Dispose();
             stream.Dispose();
@@ -661,7 +664,7 @@ namespace DiscImageChef.DiscImages
             return true;
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
             (ushort cylinder, byte head, byte sector) = LbaToChs(sectorAddress);
 
@@ -677,18 +680,18 @@ namespace DiscImageChef.DiscImages
             return sectorsData[cylinder][head][sector];
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
             MemoryStream buffer = new MemoryStream();
             for(uint i = 0; i < length; i++)
             {
-                byte[] sector = ReadSector(sectorAddress + i) ?? new byte[ImageInfo.SectorSize];
+                byte[] sector = ReadSector(sectorAddress + i) ?? new byte[imageInfo.SectorSize];
                 buffer.Write(sector, 0, sector.Length);
             }
 
@@ -697,34 +700,34 @@ namespace DiscImageChef.DiscImages
 
         (ushort cylinder, byte head, byte sector) LbaToChs(ulong lba)
         {
-            ushort cylinder = (ushort)(lba / (ImageInfo.Heads * ImageInfo.SectorsPerTrack));
-            byte head = (byte)(lba / ImageInfo.SectorsPerTrack % ImageInfo.Heads);
-            byte sector = (byte)(lba % ImageInfo.SectorsPerTrack + 1);
+            ushort cylinder = (ushort)(lba / (imageInfo.Heads * imageInfo.SectorsPerTrack));
+            byte head = (byte)(lba / imageInfo.SectorsPerTrack % imageInfo.Heads);
+            byte sector = (byte)(lba % imageInfo.SectorsPerTrack + 1);
 
             return (cylinder, head, sector);
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             return ReadSectors(sectorAddress, 1);
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             return ReadSectors(sectorAddress, length);
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             return !sectorsWhereCrcHasFailed.Contains(sectorAddress);
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
@@ -736,7 +739,7 @@ namespace DiscImageChef.DiscImages
             return failingLbas.Count <= 0;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
@@ -747,7 +750,7 @@ namespace DiscImageChef.DiscImages
             return null;
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return aDiskCrcHasFailed;
         }
@@ -891,7 +894,7 @@ namespace DiscImageChef.DiscImages
                         case 163840:
                         {
                             // Acorn disk uses 256 bytes/sector
-                            return ImageInfo.SectorSize == 256
+                            return imageInfo.SectorSize == 256
                                        ? MediaType.ACORN_525_SS_DD_40
                                        : MediaType.DOS_525_SS_DD_8;
                             // DOS disks use 512 bytes/sector
@@ -899,13 +902,13 @@ namespace DiscImageChef.DiscImages
                         case 184320:
                         {
                             // Atari disk uses 256 bytes/sector
-                            return ImageInfo.SectorSize == 256 ? MediaType.ATARI_525_DD : MediaType.DOS_525_SS_DD_9;
+                            return imageInfo.SectorSize == 256 ? MediaType.ATARI_525_DD : MediaType.DOS_525_SS_DD_9;
                             // DOS disks use 512 bytes/sector
                         }
                         case 327680:
                         {
                             // Acorn disk uses 256 bytes/sector
-                            return ImageInfo.SectorSize == 256
+                            return imageInfo.SectorSize == 256
                                        ? MediaType.ACORN_525_SS_DD_80
                                        : MediaType.DOS_525_DS_DD_8;
                             // DOS disks use 512 bytes/sector
@@ -986,7 +989,7 @@ namespace DiscImageChef.DiscImages
                         case 512512:
                         {
                             // DEC disk uses 256 bytes/sector
-                            return ImageInfo.SectorSize == 256 ? MediaType.RX02 : MediaType.ECMA_59;
+                            return imageInfo.SectorSize == 256 ? MediaType.RX02 : MediaType.ECMA_59;
                             // ECMA disks use 128 bytes/sector
                         }
                         case 1261568: return MediaType.NEC_8_DD;
@@ -1010,7 +1013,7 @@ namespace DiscImageChef.DiscImages
             }
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             if(tag != MediaTagType.Floppy_LeadOut)
                 throw new FeatureUnsupportedImageException("Feature not supported by image format");
@@ -1020,52 +1023,52 @@ namespace DiscImageChef.DiscImages
             throw new FeatureNotPresentImageException("Lead-out not present in disk image");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
diff --git a/DiscImageChef.DiscImages/UDIF.cs b/DiscImageChef.DiscImages/UDIF.cs
index 43df4af2..d743a327 100644
--- a/DiscImageChef.DiscImages/UDIF.cs
+++ b/DiscImageChef.DiscImages/UDIF.cs
@@ -49,7 +49,7 @@ using Version = Resources.Version;
 
 namespace DiscImageChef.DiscImages
 {
-    public class Udif : ImagePlugin
+    public class Udif : IMediaImage
     {
         const uint UDIF_SIGNATURE = 0x6B6F6C79;
         const uint CHUNK_SIGNATURE = 0x6D697368;
@@ -82,6 +82,7 @@ namespace DiscImageChef.DiscImages
         uint currentChunkCacheSize;
 
         UdifFooter footer;
+        ImageInfo imageInfo;
 
         Stream imageStream;
 
@@ -89,9 +90,7 @@ namespace DiscImageChef.DiscImages
 
         public Udif()
         {
-            Name = "Apple Universal Disk Image Format";
-            PluginUuid = new Guid("5BEB9002-CF3D-429C-8E06-9A96F49203FF");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -116,18 +115,23 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "Apple Universal Disk Image Format";
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Partitions =>
+        public virtual string Name => "Apple Universal Disk Image Format";
+        public virtual Guid Id => new Guid("5BEB9002-CF3D-429C-8E06-9A96F49203FF");
+
+        public virtual string ImageFormat => "Apple Universal Disk Image Format";
+
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Sessions =>
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
 
@@ -151,7 +155,7 @@ namespace DiscImageChef.DiscImages
             return footer.signature == UDIF_SIGNATURE;
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
 
@@ -292,7 +296,7 @@ namespace DiscImageChef.DiscImages
                     sectors = footer.sectorCount,
                     type = CHUNK_TYPE_COPY
                 };
-                ImageInfo.Sectors = footer.sectorCount;
+                imageInfo.Sectors = footer.sectorCount;
                 chunks.Add(bChnk.sector, bChnk);
                 buffersize = 2048 * SECTOR_SIZE;
                 fakeBlockChunks = true;
@@ -326,19 +330,19 @@ namespace DiscImageChef.DiscImages
 
                 if(dev != null) pre = $"{version.PreReleaseVersion}";
 
-                ImageInfo.ApplicationVersion = $"{major}{minor}{release}{dev}{pre}";
-                ImageInfo.Application = version.VersionString;
-                ImageInfo.Comments = version.VersionMessage;
+                imageInfo.ApplicationVersion = $"{major}{minor}{release}{dev}{pre}";
+                imageInfo.Application = version.VersionString;
+                imageInfo.Comments = version.VersionMessage;
 
-                if(version.MajorVersion == 3) ImageInfo.Application = "ShrinkWrapâ„¢";
-                else if(version.MajorVersion == 6) ImageInfo.Application = "DiskCopy";
+                if(version.MajorVersion == 3) imageInfo.Application = "ShrinkWrapâ„¢";
+                else if(version.MajorVersion == 6) imageInfo.Application = "DiskCopy";
             }
-            else ImageInfo.Application = "DiskCopy";
+            else imageInfo.Application = "DiskCopy";
 
-            DicConsole.DebugWriteLine("UDIF plugin", "Image application = {0} version {1}", ImageInfo.Application,
-                                      ImageInfo.ApplicationVersion);
+            DicConsole.DebugWriteLine("UDIF plugin", "Image application = {0} version {1}", imageInfo.Application,
+                                      imageInfo.ApplicationVersion);
 
-            ImageInfo.Sectors = 0;
+            imageInfo.Sectors = 0;
             if(!fakeBlockChunks)
             {
                 if(blkxList.Count == 0)
@@ -393,7 +397,7 @@ namespace DiscImageChef.DiscImages
 
                         if(bChnk.type == CHUNK_TYPE_END) break;
 
-                        ImageInfo.Sectors += bChnk.sectors;
+                        imageInfo.Sectors += bChnk.sectors;
 
                         // Chunk offset is relative
                         bChnk.sector += bHdr.sectorStart;
@@ -432,25 +436,25 @@ namespace DiscImageChef.DiscImages
             currentChunkCacheSize = 0;
             imageStream = stream;
 
-            ImageInfo.CreationTime = imageFilter.GetCreationTime();
-            ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
-            ImageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
-            ImageInfo.SectorSize = SECTOR_SIZE;
-            ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
-            ImageInfo.MediaType = MediaType.GENERIC_HDD;
-            ImageInfo.ImageSize = ImageInfo.Sectors * SECTOR_SIZE;
-            ImageInfo.Version = $"{footer.version}";
+            imageInfo.CreationTime = imageFilter.GetCreationTime();
+            imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+            imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
+            imageInfo.SectorSize = SECTOR_SIZE;
+            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+            imageInfo.MediaType = MediaType.GENERIC_HDD;
+            imageInfo.ImageSize = imageInfo.Sectors * SECTOR_SIZE;
+            imageInfo.Version = $"{footer.version}";
 
-            ImageInfo.Cylinders = (uint)(ImageInfo.Sectors / 16 / 63);
-            ImageInfo.Heads = 16;
-            ImageInfo.SectorsPerTrack = 63;
+            imageInfo.Cylinders = (uint)(imageInfo.Sectors / 16 / 63);
+            imageInfo.Heads = 16;
+            imageInfo.SectorsPerTrack = 63;
 
             return true;
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress),
                                                       $"Sector address {sectorAddress} not found");
 
@@ -564,13 +568,13 @@ namespace DiscImageChef.DiscImages
             throw new ImageNotSupportedException($"Unsupported chunk type 0x{currentChunk.type:X8} found");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress),
                                                       $"Sector address {sectorAddress} not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
             MemoryStream ms = new MemoryStream();
@@ -584,98 +588,98 @@ namespace DiscImageChef.DiscImages
             return ms.ToArray();
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             return null;
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
             unknownLbas = new List();
-            for(ulong i = 0; i < ImageInfo.Sectors; i++) unknownLbas.Add(i);
+            for(ulong i = 0; i < imageInfo.Sectors; i++) unknownLbas.Add(i);
 
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return null;
         }
diff --git a/DiscImageChef.DiscImages/UkvFdi.cs b/DiscImageChef.DiscImages/UkvFdi.cs
index 23e402c8..d0d834b3 100644
--- a/DiscImageChef.DiscImages/UkvFdi.cs
+++ b/DiscImageChef.DiscImages/UkvFdi.cs
@@ -41,18 +41,17 @@ using DiscImageChef.Filters;
 
 namespace DiscImageChef.DiscImages
 {
-    public class UkvFdi : ImagePlugin
+    public class UkvFdi : IMediaImage
     {
         readonly byte[] signature = {0x46, 0x44, 0x49};
+        ImageInfo imageInfo;
 
         // Cylinder by head, sector data matrix
         byte[][][][] sectorsData;
 
         public UkvFdi()
         {
-            Name = "Spectrum Floppy Disk Image";
-            PluginUuid = new Guid("DADFC9B2-67C1-42A3-B124-825528163FC0");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -77,18 +76,22 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "Spectrum floppy disk image";
+        public virtual string Name => "Spectrum Floppy Disk Image";
+        public virtual Guid Id => new Guid("DADFC9B2-67C1-42A3-B124-825528163FC0");
 
-        public override List Partitions =>
+        public virtual string ImageFormat => "Spectrum floppy disk image";
+
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
+            throw new FeatureUnsupportedImageException("Feature not supported by image format");
+        public virtual ImageInfo Info => imageInfo;
+
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Sessions =>
-            throw new FeatureUnsupportedImageException("Feature not supported by image format");
-
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -107,7 +110,7 @@ namespace DiscImageChef.DiscImages
             return hdr.magic.SequenceEqual(signature);
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -133,9 +136,9 @@ namespace DiscImageChef.DiscImages
             stream.Seek(hdr.descOff, SeekOrigin.Begin);
             byte[] description = new byte[hdr.dataOff - hdr.descOff];
             stream.Read(description, 0, description.Length);
-            ImageInfo.Comments = StringHandlers.CToString(description);
+            imageInfo.Comments = StringHandlers.CToString(description);
 
-            DicConsole.DebugWriteLine("UkvFdi plugin", "hdr.description = \"{0}\"", ImageInfo.Comments);
+            DicConsole.DebugWriteLine("UkvFdi plugin", "hdr.description = \"{0}\"", imageInfo.Comments);
 
             stream.Seek(0xE + hdr.addInfoLen, SeekOrigin.Begin);
 
@@ -143,8 +146,8 @@ namespace DiscImageChef.DiscImages
             uint[][][] sectorsOff = new uint[hdr.cylinders][][];
             sectorsData = new byte[hdr.cylinders][][][];
 
-            ImageInfo.Cylinders = hdr.cylinders;
-            ImageInfo.Heads = hdr.heads;
+            imageInfo.Cylinders = hdr.cylinders;
+            imageInfo.Heads = hdr.heads;
 
             // Read track descriptors
             for(ushort cyl = 0; cyl < hdr.cylinders; cyl++)
@@ -193,7 +196,7 @@ namespace DiscImageChef.DiscImages
                         sectorsOff[cyl][head][sec] = secOff + trkOff + hdr.dataOff;
                         sectorsData[cyl][head][sec] = new byte[128 << n];
 
-                        if(128 << n > ImageInfo.SectorSize) ImageInfo.SectorSize = (uint)(128 << n);
+                        if(128 << n > imageInfo.SectorSize) imageInfo.SectorSize = (uint)(128 << n);
                     }
                 }
             }
@@ -221,27 +224,27 @@ namespace DiscImageChef.DiscImages
                     else
                     {
                         sectorsData[cyl][head] = new byte[spt][];
-                        for(int i = 0; i < spt; i++) sectorsData[cyl][head][i] = new byte[ImageInfo.SectorSize];
+                        for(int i = 0; i < spt; i++) sectorsData[cyl][head][i] = new byte[imageInfo.SectorSize];
                     }
                 }
 
-                if(emptyCyl) ImageInfo.Cylinders--;
+                if(emptyCyl) imageInfo.Cylinders--;
             }
 
             // TODO: What about double sided, half track pitch compact floppies?
-            ImageInfo.MediaType = MediaType.CompactFloppy;
-            ImageInfo.ImageSize = (ulong)stream.Length - hdr.dataOff;
-            ImageInfo.CreationTime = imageFilter.GetCreationTime();
-            ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
-            ImageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
-            ImageInfo.SectorsPerTrack = (uint)spt;
-            ImageInfo.Sectors = ImageInfo.Cylinders * ImageInfo.Heads * ImageInfo.SectorsPerTrack;
-            ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+            imageInfo.MediaType = MediaType.CompactFloppy;
+            imageInfo.ImageSize = (ulong)stream.Length - hdr.dataOff;
+            imageInfo.CreationTime = imageFilter.GetCreationTime();
+            imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+            imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
+            imageInfo.SectorsPerTrack = (uint)spt;
+            imageInfo.Sectors = imageInfo.Cylinders * imageInfo.Heads * imageInfo.SectorsPerTrack;
+            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
 
             return true;
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
             (ushort cylinder, byte head, byte sector) = LbaToChs(sectorAddress);
 
@@ -257,12 +260,12 @@ namespace DiscImageChef.DiscImages
             return sectorsData[cylinder][head][sector - 1];
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
             MemoryStream buffer = new MemoryStream();
@@ -277,105 +280,105 @@ namespace DiscImageChef.DiscImages
 
         (ushort cylinder, byte head, byte sector) LbaToChs(ulong lba)
         {
-            ushort cylinder = (ushort)(lba / (ImageInfo.Heads * ImageInfo.SectorsPerTrack));
-            byte head = (byte)(lba / ImageInfo.SectorsPerTrack % ImageInfo.Heads);
-            byte sector = (byte)(lba % ImageInfo.SectorsPerTrack + 1);
+            ushort cylinder = (ushort)(lba / (imageInfo.Heads * imageInfo.SectorsPerTrack));
+            byte head = (byte)(lba / imageInfo.SectorsPerTrack % imageInfo.Heads);
+            byte sector = (byte)(lba % imageInfo.SectorsPerTrack + 1);
 
             return (cylinder, head, sector);
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             return null;
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
             unknownLbas = new List();
-            for(ulong i = 0; i < ImageInfo.Sectors; i++) unknownLbas.Add(i);
+            for(ulong i = 0; i < imageInfo.Sectors; i++) unknownLbas.Add(i);
 
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return null;
         }
diff --git a/DiscImageChef.DiscImages/VDI.cs b/DiscImageChef.DiscImages/VDI.cs
index d72a5198..0285bbda 100644
--- a/DiscImageChef.DiscImages/VDI.cs
+++ b/DiscImageChef.DiscImages/VDI.cs
@@ -40,7 +40,7 @@ using DiscImageChef.Filters;
 
 namespace DiscImageChef.DiscImages
 {
-    public class Vdi : ImagePlugin
+    public class Vdi : IMediaImage
     {
         const uint VDI_MAGIC = 0xBEDA107F;
         const uint VDI_EMPTY = 0xFFFFFFFF;
@@ -55,6 +55,7 @@ namespace DiscImageChef.DiscImages
         const uint MAX_CACHE_SIZE = 16777216;
         const uint MAX_CACHED_SECTORS = MAX_CACHE_SIZE / 512;
         uint[] ibm;
+        ImageInfo imageInfo;
         Stream imageStream;
 
         Dictionary sectorCache;
@@ -63,9 +64,7 @@ namespace DiscImageChef.DiscImages
 
         public Vdi()
         {
-            Name = "VirtualBox Disk Image";
-            PluginUuid = new Guid("E314DE35-C103-48A3-AD36-990F68523C46");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -90,18 +89,23 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "VDI";
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Partitions =>
+        public virtual string Name => "VirtualBox Disk Image";
+        public virtual Guid Id => new Guid("E314DE35-C103-48A3-AD36-990F68523C46");
+
+        public virtual string ImageFormat => "VDI";
+
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Sessions =>
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -119,7 +123,7 @@ namespace DiscImageChef.DiscImages
             return vHdr.magic == VDI_MAGIC;
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -167,49 +171,49 @@ namespace DiscImageChef.DiscImages
 
             sectorCache = new Dictionary();
 
-            ImageInfo.CreationTime = imageFilter.GetCreationTime();
-            ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
-            ImageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
-            ImageInfo.Sectors = vHdr.size / vHdr.sectorSize;
-            ImageInfo.ImageSize = vHdr.size;
-            ImageInfo.SectorSize = vHdr.sectorSize;
-            ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
-            ImageInfo.MediaType = MediaType.GENERIC_HDD;
-            ImageInfo.Comments = vHdr.description;
-            ImageInfo.Version = $"{vHdr.majorVersion}.{vHdr.minorVersion}";
+            imageInfo.CreationTime = imageFilter.GetCreationTime();
+            imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+            imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
+            imageInfo.Sectors = vHdr.size / vHdr.sectorSize;
+            imageInfo.ImageSize = vHdr.size;
+            imageInfo.SectorSize = vHdr.sectorSize;
+            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+            imageInfo.MediaType = MediaType.GENERIC_HDD;
+            imageInfo.Comments = vHdr.description;
+            imageInfo.Version = $"{vHdr.majorVersion}.{vHdr.minorVersion}";
 
             switch(vHdr.creator)
             {
                 case SUN_VDI:
-                    ImageInfo.Application = "Sun VirtualBox";
+                    imageInfo.Application = "Sun VirtualBox";
                     break;
                 case SUN_OLD_VDI:
-                    ImageInfo.Application = "Sun xVM";
+                    imageInfo.Application = "Sun xVM";
                     break;
                 case ORACLE_VDI:
-                    ImageInfo.Application = "Oracle VirtualBox";
+                    imageInfo.Application = "Oracle VirtualBox";
                     break;
                 case QEMUVDI:
-                    ImageInfo.Application = "QEMU";
+                    imageInfo.Application = "QEMU";
                     break;
                 case INNOTEK_VDI:
                 case INNOTEK_OLD_VDI:
-                    ImageInfo.Application = "innotek VirtualBox";
+                    imageInfo.Application = "innotek VirtualBox";
                     break;
             }
 
             imageStream = stream;
 
-            ImageInfo.Cylinders = vHdr.cylinders;
-            ImageInfo.Heads = vHdr.heads;
-            ImageInfo.SectorsPerTrack = vHdr.spt;
+            imageInfo.Cylinders = vHdr.cylinders;
+            imageInfo.Heads = vHdr.heads;
+            imageInfo.SectorsPerTrack = vHdr.spt;
 
             return true;
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress),
                                                       $"Sector address {sectorAddress} not found");
 
@@ -238,15 +242,15 @@ namespace DiscImageChef.DiscImages
             return sector;
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress),
                                                       $"Sector address {sectorAddress} not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length),
-                                                      $"Requested more sectors ({sectorAddress} + {length}) than available ({ImageInfo.Sectors})");
+                                                      $"Requested more sectors ({sectorAddress} + {length}) than available ({imageInfo.Sectors})");
 
             MemoryStream ms = new MemoryStream();
 
@@ -259,98 +263,98 @@ namespace DiscImageChef.DiscImages
             return ms.ToArray();
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             return null;
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
             unknownLbas = new List();
-            for(ulong i = 0; i < ImageInfo.Sectors; i++) unknownLbas.Add(i);
+            for(ulong i = 0; i < imageInfo.Sectors; i++) unknownLbas.Add(i);
 
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return null;
         }
diff --git a/DiscImageChef.DiscImages/VHD.cs b/DiscImageChef.DiscImages/VHD.cs
index 386ba639..922def17 100644
--- a/DiscImageChef.DiscImages/VHD.cs
+++ b/DiscImageChef.DiscImages/VHD.cs
@@ -50,7 +50,7 @@ namespace DiscImageChef.DiscImages
     ///     merely a sector by sector (RAW) image with a resource fork giving
     ///     information to Virtual PC itself.
     /// 
-    public class Vhd : ImagePlugin
+    public class Vhd : IMediaImage
     {
         /// 
         ///     File magic number, "conectix"
@@ -185,20 +185,19 @@ namespace DiscImageChef.DiscImages
         const uint PLATFORM_CODE_MACINTOSH_URI = 0x4D616358;
         uint bitmapSize;
         uint[] blockAllocationTable;
+        ImageInfo imageInfo;
         byte[][] locatorEntriesData;
         DateTime parentDateTime;
-        ImagePlugin parentImage;
+        IMediaImage parentImage;
         DateTime thisDateTime;
         DynamicDiskHeader thisDynamic;
-        Filter thisFilter;
+        IFilter thisFilter;
 
         HardDiskFooter thisFooter;
 
         public Vhd()
         {
-            Name = "VirtualPC";
-            PluginUuid = new Guid("8014d88f-64cd-4484-9441-7635c632958a");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -223,7 +222,12 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat
+        public virtual ImageInfo Info => imageInfo;
+
+        public virtual string Name => "VirtualPC";
+        public virtual Guid Id => new Guid("8014d88f-64cd-4484-9441-7635c632958a");
+
+        public virtual string ImageFormat
         {
             get
             {
@@ -237,16 +241,16 @@ namespace DiscImageChef.DiscImages
             }
         }
 
-        public override List Partitions =>
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Sessions =>
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             Stream imageStream = imageFilter.GetDataForkStream();
             ulong headerCookie;
@@ -269,7 +273,7 @@ namespace DiscImageChef.DiscImages
             return headerCookie == IMAGE_COOKIE || footerCookie == IMAGE_COOKIE;
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             Stream imageStream = imageFilter.GetDataForkStream();
             byte[] header = new byte[512];
@@ -387,7 +391,7 @@ namespace DiscImageChef.DiscImages
             DicConsole.DebugWriteLine("VirtualPC plugin", "footer.savedState = 0x{0:X2}", thisFooter.SavedState);
             DicConsole.DebugWriteLine("VirtualPC plugin", "footer.reserved's SHA1 = 0x{0}", sha1Ctx.End());
 
-            if(thisFooter.Version == VERSION1) ImageInfo.Version = "1.0";
+            if(thisFooter.Version == VERSION1) imageInfo.Version = "1.0";
             else
                 throw new
                     ImageNotSupportedException($"(VirtualPC plugin): Unknown image type {thisFooter.DiskType} found. Please submit a bug with an example image.");
@@ -396,28 +400,28 @@ namespace DiscImageChef.DiscImages
             {
                 case CREATOR_QEMU:
                 {
-                    ImageInfo.Application = "QEMU";
+                    imageInfo.Application = "QEMU";
                     // QEMU always set same version
-                    ImageInfo.ApplicationVersion = "Unknown";
+                    imageInfo.ApplicationVersion = "Unknown";
 
                     break;
                 }
                 case CREATOR_VIRTUAL_BOX:
                 {
-                    ImageInfo.ApplicationVersion =
+                    imageInfo.ApplicationVersion =
                         $"{(thisFooter.CreatorVersion & 0xFFFF0000) >> 16}.{thisFooter.CreatorVersion & 0x0000FFFF:D2}";
                     switch(thisFooter.CreatorHostOs)
                     {
                         case CREATOR_MACINTOSH:
                         case CREATOR_MACINTOSH_OLD:
-                            ImageInfo.Application = "VirtualBox for Mac";
+                            imageInfo.Application = "VirtualBox for Mac";
                             break;
                         case CREATOR_WINDOWS:
                             // VirtualBox uses Windows creator for any other OS
-                            ImageInfo.Application = "VirtualBox";
+                            imageInfo.Application = "VirtualBox";
                             break;
                         default:
-                            ImageInfo.Application =
+                            imageInfo.Application =
                                 $"VirtualBox for unknown OS \"{Encoding.ASCII.GetString(BigEndianBitConverter.GetBytes(thisFooter.CreatorHostOs))}\"";
                             break;
                     }
@@ -426,14 +430,14 @@ namespace DiscImageChef.DiscImages
                 }
                 case CREATOR_VIRTUAL_SERVER:
                 {
-                    ImageInfo.Application = "Microsoft Virtual Server";
+                    imageInfo.Application = "Microsoft Virtual Server";
                     switch(thisFooter.CreatorVersion)
                     {
                         case VERSION_VIRTUAL_SERVER2004:
-                            ImageInfo.ApplicationVersion = "2004";
+                            imageInfo.ApplicationVersion = "2004";
                             break;
                         default:
-                            ImageInfo.ApplicationVersion = $"Unknown version 0x{thisFooter.CreatorVersion:X8}";
+                            imageInfo.ApplicationVersion = $"Unknown version 0x{thisFooter.CreatorVersion:X8}";
                             break;
                     }
 
@@ -448,12 +452,11 @@ namespace DiscImageChef.DiscImages
                             switch(thisFooter.CreatorVersion)
                             {
                                 case VERSION_VIRTUAL_PC_MAC:
-                                    ImageInfo.Application = "Connectix Virtual PC";
-                                    ImageInfo.ApplicationVersion = "5, 6 or 7";
+                                    imageInfo.Application = "Connectix Virtual PC";
+                                    imageInfo.ApplicationVersion = "5, 6 or 7";
                                     break;
                                 default:
-                                    ImageInfo.ApplicationVersion =
-                                        $"Unknown version 0x{thisFooter.CreatorVersion:X8}";
+                                    imageInfo.ApplicationVersion = $"Unknown version 0x{thisFooter.CreatorVersion:X8}";
                                     break;
                             }
 
@@ -462,28 +465,27 @@ namespace DiscImageChef.DiscImages
                             switch(thisFooter.CreatorVersion)
                             {
                                 case VERSION_VIRTUAL_PC_MAC:
-                                    ImageInfo.Application = "Connectix Virtual PC";
-                                    ImageInfo.ApplicationVersion = "5, 6 or 7";
+                                    imageInfo.Application = "Connectix Virtual PC";
+                                    imageInfo.ApplicationVersion = "5, 6 or 7";
                                     break;
                                 case VERSION_VIRTUAL_PC2004:
-                                    ImageInfo.Application = "Microsoft Virtual PC";
-                                    ImageInfo.ApplicationVersion = "2004";
+                                    imageInfo.Application = "Microsoft Virtual PC";
+                                    imageInfo.ApplicationVersion = "2004";
                                     break;
                                 case VERSION_VIRTUAL_PC2007:
-                                    ImageInfo.Application = "Microsoft Virtual PC";
-                                    ImageInfo.ApplicationVersion = "2007";
+                                    imageInfo.Application = "Microsoft Virtual PC";
+                                    imageInfo.ApplicationVersion = "2007";
                                     break;
                                 default:
-                                    ImageInfo.ApplicationVersion =
-                                        $"Unknown version 0x{thisFooter.CreatorVersion:X8}";
+                                    imageInfo.ApplicationVersion = $"Unknown version 0x{thisFooter.CreatorVersion:X8}";
                                     break;
                             }
 
                             break;
                         default:
-                            ImageInfo.Application =
+                            imageInfo.Application =
                                 $"Virtual PC for unknown OS \"{Encoding.ASCII.GetString(BigEndianBitConverter.GetBytes(thisFooter.CreatorHostOs))}\"";
-                            ImageInfo.ApplicationVersion = $"Unknown version 0x{thisFooter.CreatorVersion:X8}";
+                            imageInfo.ApplicationVersion = $"Unknown version 0x{thisFooter.CreatorVersion:X8}";
                             break;
                     }
 
@@ -491,25 +493,25 @@ namespace DiscImageChef.DiscImages
                 }
                 default:
                 {
-                    ImageInfo.Application =
+                    imageInfo.Application =
                         $"Unknown application \"{Encoding.ASCII.GetString(BigEndianBitConverter.GetBytes(thisFooter.CreatorHostOs))}\"";
-                    ImageInfo.ApplicationVersion = $"Unknown version 0x{thisFooter.CreatorVersion:X8}";
+                    imageInfo.ApplicationVersion = $"Unknown version 0x{thisFooter.CreatorVersion:X8}";
                     break;
                 }
             }
 
             thisFilter = imageFilter;
-            ImageInfo.ImageSize = thisFooter.CurrentSize;
-            ImageInfo.Sectors = thisFooter.CurrentSize / 512;
-            ImageInfo.SectorSize = 512;
+            imageInfo.ImageSize = thisFooter.CurrentSize;
+            imageInfo.Sectors = thisFooter.CurrentSize / 512;
+            imageInfo.SectorSize = 512;
 
-            ImageInfo.CreationTime = imageFilter.GetCreationTime();
-            ImageInfo.LastModificationTime = thisDateTime;
-            ImageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
+            imageInfo.CreationTime = imageFilter.GetCreationTime();
+            imageInfo.LastModificationTime = thisDateTime;
+            imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
 
-            ImageInfo.Cylinders = (thisFooter.DiskGeometry & 0xFFFF0000) >> 16;
-            ImageInfo.Heads = (thisFooter.DiskGeometry & 0xFF00) >> 8;
-            ImageInfo.SectorsPerTrack = thisFooter.DiskGeometry & 0xFF;
+            imageInfo.Cylinders = (thisFooter.DiskGeometry & 0xFFFF0000) >> 16;
+            imageInfo.Heads = (thisFooter.DiskGeometry & 0xFF00) >> 8;
+            imageInfo.SectorsPerTrack = thisFooter.DiskGeometry & 0xFF;
 
             if(thisFooter.DiskType == TYPE_DYNAMIC || thisFooter.DiskType == TYPE_DIFFERENCING)
             {
@@ -675,7 +677,7 @@ namespace DiscImageChef.DiscImages
                 DicConsole.DebugWriteLine("VirtualPC plugin", "Bitmap is {0} sectors", bitmapSize);
             }
 
-            ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
 
             switch(thisFooter.DiskType)
             {
@@ -757,7 +759,7 @@ namespace DiscImageChef.DiscImages
                         if(parentPath != null)
                         {
                             DicConsole.DebugWriteLine("VirtualPC plugin", "Possible parent path: \"{0}\"", parentPath);
-                            Filter parentFilter =
+                            IFilter parentFilter =
                                 new FiltersList().GetFilter(Path.Combine(imageFilter.GetParentFolder(), parentPath));
 
                             if(parentFilter != null) locatorFound = true;
@@ -773,7 +775,7 @@ namespace DiscImageChef.DiscImages
 
                     {
                         parentImage = new Vhd();
-                        Filter parentFilter =
+                        IFilter parentFilter =
                             new FiltersList().GetFilter(Path.Combine(imageFilter.GetParentFolder(), parentPath));
 
                         if(parentFilter == null)
@@ -795,7 +797,7 @@ namespace DiscImageChef.DiscImages
                         // the parent never stored itself. So the only real way to know that images are related is
                         // because the parent IS found and SAME SIZE. Ugly...
                         // More funny even, tested parent images show an empty host OS, and child images a correct one.
-                        if(parentImage.ImageInfo.Sectors != ImageInfo.Sectors)
+                        if(parentImage.Info.Sectors != imageInfo.Sectors)
                             throw new
                                 ImageNotSupportedException("(VirtualPC plugin): Parent image is of different size");
                     }
@@ -817,7 +819,7 @@ namespace DiscImageChef.DiscImages
             }
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
             switch(thisFooter.DiskType)
             {
@@ -882,7 +884,7 @@ namespace DiscImageChef.DiscImages
             }
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
             switch(thisFooter.DiskType)
             {
@@ -981,98 +983,98 @@ namespace DiscImageChef.DiscImages
             return ~checksum;
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             return null;
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
             unknownLbas = new List();
-            for(ulong i = 0; i < ImageInfo.Sectors; i++) unknownLbas.Add(i);
+            for(ulong i = 0; i < imageInfo.Sectors; i++) unknownLbas.Add(i);
 
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return null;
         }
diff --git a/DiscImageChef.DiscImages/VHDX.cs b/DiscImageChef.DiscImages/VHDX.cs
index 8c39f089..188e1129 100644
--- a/DiscImageChef.DiscImages/VHDX.cs
+++ b/DiscImageChef.DiscImages/VHDX.cs
@@ -42,7 +42,7 @@ using DiscImageChef.Filters;
 
 namespace DiscImageChef.DiscImages
 {
-    public class Vhdx : ImagePlugin
+    public class Vhdx : IMediaImage
     {
         const ulong VHDX_SIGNATURE = 0x656C696678646876;
         const uint VHDX_HEADER_SIG = 0x64616568;
@@ -103,13 +103,14 @@ namespace DiscImageChef.DiscImages
         long chunkRatio;
         ulong dataBlocks;
         bool hasParent;
+        ImageInfo imageInfo;
         Stream imageStream;
         uint logicalSectorSize;
         int maxBlockCache;
         int maxSectorCache;
         long metadataOffset;
         Guid page83Data;
-        ImagePlugin parentImage;
+        IMediaImage parentImage;
         uint physicalSectorSize;
         byte[] sectorBitmap;
         ulong[] sectorBitmapPointers;
@@ -130,9 +131,7 @@ namespace DiscImageChef.DiscImages
 
         public Vhdx()
         {
-            Name = "Microsoft VHDX";
-            PluginUuid = new Guid("536B141B-D09C-4799-AB70-34631286EB9D");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -157,18 +156,23 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "VHDX";
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Partitions =>
+        public virtual string Name => "Microsoft VHDX";
+        public virtual Guid Id => new Guid("536B141B-D09C-4799-AB70-34631286EB9D");
+
+        public virtual string ImageFormat => "VHDX";
+
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Sessions =>
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -186,7 +190,7 @@ namespace DiscImageChef.DiscImages
             return vhdxId.signature == VHDX_SIGNATURE;
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -203,7 +207,7 @@ namespace DiscImageChef.DiscImages
 
             if(vhdxId.signature != VHDX_SIGNATURE) return false;
 
-            ImageInfo.Application = Encoding.Unicode.GetString(vhdxId.creator);
+            imageInfo.Application = Encoding.Unicode.GetString(vhdxId.creator);
 
             stream.Seek(64 * 1024, SeekOrigin.Begin);
             byte[] vHdrB = new byte[Marshal.SizeOf(vHdr)];
@@ -400,7 +404,7 @@ namespace DiscImageChef.DiscImages
                     stream.Read(tmpKey, 0, tmpKey.Length);
                     string entryType = Encoding.Unicode.GetString(tmpKey);
 
-                    Filter parentFilter;
+                    IFilter parentFilter;
                     if(string.Compare(entryType, RELATIVE_PATH_KEY, StringComparison.OrdinalIgnoreCase) == 0)
                     {
                         stream.Seek(parentEntry.valueOffset + metadataOffset, SeekOrigin.Begin);
@@ -541,21 +545,21 @@ namespace DiscImageChef.DiscImages
             sectorCache = new Dictionary();
             blockCache = new Dictionary();
 
-            ImageInfo.CreationTime = imageFilter.GetCreationTime();
-            ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
-            ImageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
-            ImageInfo.SectorSize = logicalSectorSize;
-            ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
-            ImageInfo.MediaType = MediaType.GENERIC_HDD;
-            ImageInfo.ImageSize = virtualDiskSize;
-            ImageInfo.Sectors = ImageInfo.ImageSize / ImageInfo.SectorSize;
-            ImageInfo.DriveSerialNumber = page83Data.ToString();
+            imageInfo.CreationTime = imageFilter.GetCreationTime();
+            imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+            imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
+            imageInfo.SectorSize = logicalSectorSize;
+            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+            imageInfo.MediaType = MediaType.GENERIC_HDD;
+            imageInfo.ImageSize = virtualDiskSize;
+            imageInfo.Sectors = imageInfo.ImageSize / imageInfo.SectorSize;
+            imageInfo.DriveSerialNumber = page83Data.ToString();
 
             // TODO: Separate image application from version, need several samples.
 
-            ImageInfo.Cylinders = (uint)(ImageInfo.Sectors / 16 / 63);
-            ImageInfo.Heads = 16;
-            ImageInfo.SectorsPerTrack = 63;
+            imageInfo.Cylinders = (uint)(imageInfo.Sectors / 16 / 63);
+            imageInfo.Heads = 16;
+            imageInfo.SectorsPerTrack = 63;
 
             return true;
         }
@@ -571,9 +575,9 @@ namespace DiscImageChef.DiscImages
             return (sectorBitmap[index] & val) == val;
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress),
                                                       $"Sector address {sectorAddress} not found");
 
@@ -624,15 +628,15 @@ namespace DiscImageChef.DiscImages
             return sector;
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress),
                                                       $"Sector address {sectorAddress} not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length),
-                                                      $"Requested more sectors ({sectorAddress + length}) than available ({ImageInfo.Sectors})");
+                                                      $"Requested more sectors ({sectorAddress + length}) than available ({imageInfo.Sectors})");
 
             MemoryStream ms = new MemoryStream();
 
@@ -652,98 +656,98 @@ namespace DiscImageChef.DiscImages
             return ~checksum;
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             return null;
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
             unknownLbas = new List();
-            for(ulong i = 0; i < ImageInfo.Sectors; i++) unknownLbas.Add(i);
+            for(ulong i = 0; i < imageInfo.Sectors; i++) unknownLbas.Add(i);
 
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return null;
         }
diff --git a/DiscImageChef.DiscImages/VMware.cs b/DiscImageChef.DiscImages/VMware.cs
index 26c7e667..1e4ce9ce 100644
--- a/DiscImageChef.DiscImages/VMware.cs
+++ b/DiscImageChef.DiscImages/VMware.cs
@@ -42,7 +42,7 @@ using DiscImageChef.Filters;
 
 namespace DiscImageChef.DiscImages
 {
-    public class VMware : ImagePlugin
+    public class VMware : IMediaImage
     {
         const uint VMWARE_EXTENT_MAGIC = 0x564D444B;
         const uint VMWARE_COW_MAGIC = 0x44574F43;
@@ -103,17 +103,18 @@ namespace DiscImageChef.DiscImages
 
         uint cid;
         Dictionary extents;
-        Filter gdFilter;
+        IFilter gdFilter;
         Dictionary grainCache;
 
         ulong grainSize;
         uint[] gTable;
         bool hasParent;
+        ImageInfo imageInfo;
         string imageType;
         uint maxCachedGrains;
         uint parentCid;
 
-        ImagePlugin parentImage;
+        IMediaImage parentImage;
         string parentName;
 
         Dictionary sectorCache;
@@ -124,9 +125,7 @@ namespace DiscImageChef.DiscImages
 
         public VMware()
         {
-            Name = "VMware disk image";
-            PluginUuid = new Guid("E314DE35-C103-48A3-AD36-990F68523C46");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -151,18 +150,23 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "VMware";
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Partitions =>
+        public virtual string Name => "VMware disk image";
+        public virtual Guid Id => new Guid("E314DE35-C103-48A3-AD36-990F68523C46");
+
+        public virtual string ImageFormat => "VMware";
+
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Sessions =>
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
 
@@ -205,7 +209,7 @@ namespace DiscImageChef.DiscImages
             return ddfMagicBytes.SequenceEqual(ddfMagic);
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
 
@@ -292,7 +296,7 @@ namespace DiscImageChef.DiscImages
 
                     if(!File.Exists(curPath)) break;
 
-                    Filter extentFilter = new FiltersList().GetFilter(curPath);
+                    IFilter extentFilter = new FiltersList().GetFilter(curPath);
                     Stream extentStream = extentFilter.GetDataForkStream();
 
                     if(stream.Length > Marshal.SizeOf(vmCHdr))
@@ -409,17 +413,17 @@ namespace DiscImageChef.DiscImages
                     }
                     else if(matchCylinders.Success)
                     {
-                        uint.TryParse(matchCylinders.Groups["cylinders"].Value, out ImageInfo.Cylinders);
+                        uint.TryParse(matchCylinders.Groups["cylinders"].Value, out imageInfo.Cylinders);
                         matchedCyls = true;
                     }
                     else if(matchHeads.Success)
                     {
-                        uint.TryParse(matchHeads.Groups["heads"].Value, out ImageInfo.Heads);
+                        uint.TryParse(matchHeads.Groups["heads"].Value, out imageInfo.Heads);
                         matchedHds = true;
                     }
                     else if(matchSectors.Success)
                     {
-                        uint.TryParse(matchSectors.Groups["sectors"].Value, out ImageInfo.SectorsPerTrack);
+                        uint.TryParse(matchSectors.Groups["sectors"].Value, out imageInfo.SectorsPerTrack);
                         matchedSpt = true;
                     }
                 }
@@ -500,7 +504,7 @@ namespace DiscImageChef.DiscImages
                 throw new
                     Exception("There are sparse extents but there is no header to find the grain tables, cannot proceed.");
 
-            ImageInfo.Sectors = currentSector;
+            imageInfo.Sectors = currentSector;
 
             uint grains = 0;
             uint gdEntries = 0;
@@ -531,7 +535,7 @@ namespace DiscImageChef.DiscImages
                 DicConsole.DebugWriteLine("VMware plugin", "vmEHdr.compression = 0x{0:X4}", vmEHdr.compression);
 
                 grainSize = vmEHdr.grainSize;
-                grains = (uint)(ImageInfo.Sectors / vmEHdr.grainSize) + 1;
+                grains = (uint)(imageInfo.Sectors / vmEHdr.grainSize) + 1;
                 gdEntries = grains / vmEHdr.GTEsPerGT;
                 gtEsPerGt = vmEHdr.GTEsPerGT;
 
@@ -560,12 +564,12 @@ namespace DiscImageChef.DiscImages
                 DicConsole.DebugWriteLine("VMware plugin", "vmCHdr.uncleanShutdown = {0}", vmCHdr.uncleanShutdown);
 
                 grainSize = vmCHdr.grainSize;
-                grains = (uint)(ImageInfo.Sectors / vmCHdr.grainSize) + 1;
+                grains = (uint)(imageInfo.Sectors / vmCHdr.grainSize) + 1;
                 gdEntries = vmCHdr.numGDEntries;
                 gdOffset = vmCHdr.gdOffset;
                 gtEsPerGt = grains / gdEntries;
-                ImageInfo.MediaTitle = StringHandlers.CToString(vmCHdr.name);
-                ImageInfo.Comments = StringHandlers.CToString(vmCHdr.description);
+                imageInfo.MediaTitle = StringHandlers.CToString(vmCHdr.name);
+                imageInfo.Comments = StringHandlers.CToString(vmCHdr.description);
                 version = vmCHdr.version;
             }
 
@@ -573,7 +577,7 @@ namespace DiscImageChef.DiscImages
             {
                 if(grains == 0 || gdEntries == 0) throw new Exception("Some error ocurred setting GD sizes");
 
-                DicConsole.DebugWriteLine("VMware plugin", "{0} sectors in {1} grains in {2} tables", ImageInfo.Sectors,
+                DicConsole.DebugWriteLine("VMware plugin", "{0} sectors in {1} grains in {2} tables", imageInfo.Sectors,
                                           grains, gdEntries);
 
                 Stream gdStream = gdFilter.GetDataForkStream();
@@ -608,7 +612,7 @@ namespace DiscImageChef.DiscImages
 
             if(hasParent)
             {
-                Filter parentFilter =
+                IFilter parentFilter =
                     new FiltersList().GetFilter(Path.Combine(imageFilter.GetParentFolder(), parentName));
                 if(parentFilter == null) throw new Exception($"Cannot find parent \"{parentName}\".");
 
@@ -619,35 +623,35 @@ namespace DiscImageChef.DiscImages
 
             sectorCache = new Dictionary();
 
-            ImageInfo.CreationTime = imageFilter.GetCreationTime();
-            ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
-            ImageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
-            ImageInfo.SectorSize = SECTOR_SIZE;
-            ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
-            ImageInfo.MediaType = MediaType.GENERIC_HDD;
-            ImageInfo.ImageSize = ImageInfo.Sectors * SECTOR_SIZE;
+            imageInfo.CreationTime = imageFilter.GetCreationTime();
+            imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+            imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
+            imageInfo.SectorSize = SECTOR_SIZE;
+            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+            imageInfo.MediaType = MediaType.GENERIC_HDD;
+            imageInfo.ImageSize = imageInfo.Sectors * SECTOR_SIZE;
             // VMDK version 1 started on VMware 4, so there is a previous version, "COWD"
-            ImageInfo.Version = cowD ? $"{version}" : $"{version + 3}";
+            imageInfo.Version = cowD ? $"{version}" : $"{version + 3}";
 
             if(cowD)
             {
-                ImageInfo.Cylinders = vmCHdr.cylinders;
-                ImageInfo.Heads = vmCHdr.heads;
-                ImageInfo.SectorsPerTrack = vmCHdr.spt;
+                imageInfo.Cylinders = vmCHdr.cylinders;
+                imageInfo.Heads = vmCHdr.heads;
+                imageInfo.SectorsPerTrack = vmCHdr.spt;
             }
             else if(!matchedCyls || !matchedHds || !matchedSpt)
             {
-                ImageInfo.Cylinders = (uint)(ImageInfo.Sectors / 16 / 63);
-                ImageInfo.Heads = 16;
-                ImageInfo.SectorsPerTrack = 63;
+                imageInfo.Cylinders = (uint)(imageInfo.Sectors / 16 / 63);
+                imageInfo.Heads = 16;
+                imageInfo.SectorsPerTrack = 63;
             }
 
             return true;
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress),
                                                       $"Sector address {sectorAddress} not found");
 
@@ -732,13 +736,13 @@ namespace DiscImageChef.DiscImages
             return sector;
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress),
                                                       $"Sector address {sectorAddress} not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
             MemoryStream ms = new MemoryStream();
@@ -752,98 +756,98 @@ namespace DiscImageChef.DiscImages
             return ms.ToArray();
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             return null;
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
             unknownLbas = new List();
-            for(ulong i = 0; i < ImageInfo.Sectors; i++) unknownLbas.Add(i);
+            for(ulong i = 0; i < imageInfo.Sectors; i++) unknownLbas.Add(i);
 
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return null;
         }
@@ -902,7 +906,7 @@ namespace DiscImageChef.DiscImages
             public string Access;
             public uint Sectors;
             public string Type;
-            public Filter Filter;
+            public IFilter Filter;
             public string Filename;
             public uint Offset;
         }
diff --git a/DiscImageChef.DiscImages/Virtual98.cs b/DiscImageChef.DiscImages/Virtual98.cs
index f5e64989..4dd121fd 100644
--- a/DiscImageChef.DiscImages/Virtual98.cs
+++ b/DiscImageChef.DiscImages/Virtual98.cs
@@ -43,18 +43,17 @@ using DiscImageChef.Filters;
 namespace DiscImageChef.DiscImages
 {
     // Info from Neko Project II emulator
-    public class Virtual98 : ImagePlugin
+    public class Virtual98 : IMediaImage
     {
         readonly byte[] signature = {0x56, 0x48, 0x44, 0x31, 0x2E, 0x30, 0x30, 0x00};
-        Filter nhdImageFilter;
+        ImageInfo imageInfo;
+        IFilter nhdImageFilter;
 
         Virtual98Header v98Hdr;
 
         public Virtual98()
         {
-            Name = "Virtual98 Disk Image";
-            PluginUuid = new Guid("C0CDE13D-04D0-4913-8740-AFAA44D0A107");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -79,18 +78,23 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "Virtual98 disk image";
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Partitions =>
+        public virtual string Name => "Virtual98 Disk Image";
+        public virtual Guid Id => new Guid("C0CDE13D-04D0-4913-8740-AFAA44D0A107");
+
+        public virtual string ImageFormat => "Virtual98 disk image";
+
+        public virtual List Partitions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Tracks =>
+        public virtual List Tracks =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override List Sessions =>
+        public virtual List Sessions =>
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -125,7 +129,7 @@ namespace DiscImageChef.DiscImages
             return true;
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -143,48 +147,48 @@ namespace DiscImageChef.DiscImages
             v98Hdr = (Virtual98Header)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(Virtual98Header));
             handle.Free();
 
-            ImageInfo.MediaType = MediaType.GENERIC_HDD;
+            imageInfo.MediaType = MediaType.GENERIC_HDD;
 
-            ImageInfo.ImageSize = (ulong)(stream.Length - 0xDC);
-            ImageInfo.CreationTime = imageFilter.GetCreationTime();
-            ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
-            ImageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
-            ImageInfo.Sectors = v98Hdr.totals;
-            ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
-            ImageInfo.SectorSize = v98Hdr.sectorsize;
-            ImageInfo.Cylinders = v98Hdr.cylinders;
-            ImageInfo.Heads = v98Hdr.surfaces;
-            ImageInfo.SectorsPerTrack = v98Hdr.sectors;
-            ImageInfo.Comments = StringHandlers.CToString(v98Hdr.comment, shiftjis);
+            imageInfo.ImageSize = (ulong)(stream.Length - 0xDC);
+            imageInfo.CreationTime = imageFilter.GetCreationTime();
+            imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+            imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
+            imageInfo.Sectors = v98Hdr.totals;
+            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+            imageInfo.SectorSize = v98Hdr.sectorsize;
+            imageInfo.Cylinders = v98Hdr.cylinders;
+            imageInfo.Heads = v98Hdr.surfaces;
+            imageInfo.SectorsPerTrack = v98Hdr.sectors;
+            imageInfo.Comments = StringHandlers.CToString(v98Hdr.comment, shiftjis);
 
             nhdImageFilter = imageFilter;
 
             return true;
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
             return ReadSectors(sectorAddress, 1);
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
-            byte[] buffer = new byte[length * ImageInfo.SectorSize];
+            byte[] buffer = new byte[length * imageInfo.SectorSize];
 
             Stream stream = nhdImageFilter.GetDataForkStream();
 
             // V98 are lazy allocated
-            if((long)(0xDC + sectorAddress * ImageInfo.SectorSize) >= stream.Length) return buffer;
+            if((long)(0xDC + sectorAddress * imageInfo.SectorSize) >= stream.Length) return buffer;
 
-            stream.Seek((long)(0xDC + sectorAddress * ImageInfo.SectorSize), SeekOrigin.Begin);
+            stream.Seek((long)(0xDC + sectorAddress * imageInfo.SectorSize), SeekOrigin.Begin);
 
-            int toRead = (int)(length * ImageInfo.SectorSize);
+            int toRead = (int)(length * imageInfo.SectorSize);
 
             if(toRead + stream.Position > stream.Length) toRead = (int)(stream.Length - stream.Position);
 
@@ -193,98 +197,98 @@ namespace DiscImageChef.DiscImages
             return buffer;
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             return null;
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
             unknownLbas = new List();
-            for(ulong i = 0; i < ImageInfo.Sectors; i++) unknownLbas.Add(i);
+            for(ulong i = 0; i < imageInfo.Sectors; i++) unknownLbas.Add(i);
 
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return null;
         }
diff --git a/DiscImageChef.DiscImages/ZZZRawImage.cs b/DiscImageChef.DiscImages/ZZZRawImage.cs
index 7f2a6d82..f362f511 100644
--- a/DiscImageChef.DiscImages/ZZZRawImage.cs
+++ b/DiscImageChef.DiscImages/ZZZRawImage.cs
@@ -39,18 +39,16 @@ using DiscImageChef.Filters;
 
 namespace DiscImageChef.DiscImages
 {
-    public class ZZZRawImage : ImagePlugin
+    public class ZZZRawImage : IMediaImage
     {
         bool differentTrackZeroSize;
         string extension;
-        Filter rawImageFilter;
+        ImageInfo imageInfo;
+        IFilter rawImageFilter;
 
         public ZZZRawImage()
         {
-            Name = "Raw Disk Image";
-            // Non-random UUID to recognize this specific plugin
-            PluginUuid = new Guid("12345678-AAAA-BBBB-CCCC-123456789000");
-            ImageInfo = new ImageInfo
+            imageInfo = new ImageInfo
             {
                 ReadableSectorTags = new List(),
                 ReadableMediaTags = new List(),
@@ -75,23 +73,28 @@ namespace DiscImageChef.DiscImages
             };
         }
 
-        public override string ImageFormat => "Raw disk image (sector by sector copy)";
+        public virtual string Name => "Raw Disk Image";
+        // Non-random UUID to recognize this specific plugin
+        public virtual Guid Id => new Guid("12345678-AAAA-BBBB-CCCC-123456789000");
+        public virtual ImageInfo Info => imageInfo;
 
-        public override List Tracks
+        public virtual string ImageFormat => "Raw disk image (sector by sector copy)";
+
+        public virtual List Tracks
         {
             get
             {
-                if(ImageInfo.XmlMediaType != XmlMediaType.OpticalDisc)
+                if(imageInfo.XmlMediaType != XmlMediaType.OpticalDisc)
                     throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
                 Track trk = new Track
                 {
-                    TrackBytesPerSector = (int)ImageInfo.SectorSize,
-                    TrackEndSector = ImageInfo.Sectors - 1,
+                    TrackBytesPerSector = (int)imageInfo.SectorSize,
+                    TrackEndSector = imageInfo.Sectors - 1,
                     TrackFile = rawImageFilter.GetFilename(),
                     TrackFileOffset = 0,
                     TrackFileType = "BINARY",
-                    TrackRawBytesPerSector = (int)ImageInfo.SectorSize,
+                    TrackRawBytesPerSector = (int)imageInfo.SectorSize,
                     TrackSequence = 1,
                     TrackStartSector = 0,
                     TrackSubchannelType = TrackSubchannelType.None,
@@ -103,16 +106,16 @@ namespace DiscImageChef.DiscImages
             }
         }
 
-        public override List Sessions
+        public virtual List Sessions
         {
             get
             {
-                if(ImageInfo.XmlMediaType != XmlMediaType.OpticalDisc)
+                if(imageInfo.XmlMediaType != XmlMediaType.OpticalDisc)
                     throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
                 Session sess = new Session
                 {
-                    EndSector = ImageInfo.Sectors - 1,
+                    EndSector = imageInfo.Sectors - 1,
                     EndTrack = 1,
                     SessionSequence = 1,
                     StartSector = 0,
@@ -123,36 +126,36 @@ namespace DiscImageChef.DiscImages
             }
         }
 
-        public override List Partitions
+        public virtual List Partitions
         {
             get
             {
-                if(ImageInfo.XmlMediaType != XmlMediaType.OpticalDisc)
+                if(imageInfo.XmlMediaType != XmlMediaType.OpticalDisc)
                     throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
                 List parts = new List();
                 Partition part = new Partition
                 {
                     Start = 0,
-                    Length = ImageInfo.Sectors,
+                    Length = imageInfo.Sectors,
                     Offset = 0,
                     Sequence = 0,
                     Type = "MODE1/2048",
-                    Size = ImageInfo.Sectors * ImageInfo.SectorSize
+                    Size = imageInfo.Sectors * imageInfo.SectorSize
                 };
                 parts.Add(part);
                 return parts;
             }
         }
 
-        public override bool IdentifyImage(Filter imageFilter)
+        public virtual bool IdentifyImage(IFilter imageFilter)
         {
             // Check if file is not multiple of 512
             if(imageFilter.GetDataForkLength() % 512 == 0) return true;
 
             extension = Path.GetExtension(imageFilter.GetFilename())?.ToLower();
 
-            if(extension == ".hdf" && ImageInfo.ImageSize % 256 == 0) return true;
+            if(extension == ".hdf" && imageInfo.ImageSize % 256 == 0) return true;
 
             // Check known disk sizes with sectors smaller than 512
             switch(imageFilter.GetDataForkLength())
@@ -184,7 +187,7 @@ namespace DiscImageChef.DiscImages
             }
         }
 
-        public override bool OpenImage(Filter imageFilter)
+        public virtual bool OpenImage(IFilter imageFilter)
         {
             Stream stream = imageFilter.GetDataForkStream();
             stream.Seek(0, SeekOrigin.Begin);
@@ -193,17 +196,17 @@ namespace DiscImageChef.DiscImages
             switch(extension)
             {
                 case ".iso" when imageFilter.GetDataForkLength() % 2048 == 0:
-                    ImageInfo.SectorSize = 2048;
+                    imageInfo.SectorSize = 2048;
                     break;
                 case ".d81" when imageFilter.GetDataForkLength() == 819200:
-                    ImageInfo.SectorSize = 256;
+                    imageInfo.SectorSize = 256;
                     break;
                 default:
                     if((extension == ".adf" || extension == ".adl" || extension == ".ssd" || extension == ".dsd") &&
                        (imageFilter.GetDataForkLength() == 163840 || imageFilter.GetDataForkLength() == 327680 ||
-                        imageFilter.GetDataForkLength() == 655360)) ImageInfo.SectorSize = 256;
+                        imageFilter.GetDataForkLength() == 655360)) imageInfo.SectorSize = 256;
                     else if((extension == ".adf" || extension == ".adl") && imageFilter.GetDataForkLength() == 819200)
-                        ImageInfo.SectorSize = 1024;
+                        imageInfo.SectorSize = 1024;
                     else
                         switch(imageFilter.GetDataForkLength())
                         {
@@ -212,7 +215,7 @@ namespace DiscImageChef.DiscImages
                             case 495872:
                             case 92160:
                             case 133120:
-                                ImageInfo.SectorSize = 128;
+                                imageInfo.SectorSize = 128;
                                 break;
                             case 116480:
                             case 287488: // T0S0 = 128bps
@@ -240,132 +243,132 @@ namespace DiscImageChef.DiscImages
                             case 822400:
                                 #endregion Commodore
 
-                                ImageInfo.SectorSize = 256;
+                                imageInfo.SectorSize = 256;
                                 break;
                             case 81664:
-                                ImageInfo.SectorSize = 319;
+                                imageInfo.SectorSize = 319;
                                 break;
                             case 306432: // T0S0 = 128bps
                             case 1146624: // T0S0 = 128bps, T0S1 = 256bps
                             case 1177344: // T0S0 = 128bps, T0S1 = 256bps
-                                ImageInfo.SectorSize = 512;
+                                imageInfo.SectorSize = 512;
                                 break;
                             case 1222400: // T0S0 = 128bps, T0S1 = 256bps
                             case 1304320: // T0S0 = 128bps, T0S1 = 256bps
                             case 1255168: // T0S0 = 128bps, T0S1 = 256bps
                             case 1261568:
                             case 1638400:
-                                ImageInfo.SectorSize = 1024;
+                                imageInfo.SectorSize = 1024;
                                 break;
                             default:
-                                ImageInfo.SectorSize = 512;
+                                imageInfo.SectorSize = 512;
                                 break;
                         }
 
                     break;
             }
 
-            ImageInfo.ImageSize = (ulong)imageFilter.GetDataForkLength();
-            ImageInfo.CreationTime = imageFilter.GetCreationTime();
-            ImageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
-            ImageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
+            imageInfo.ImageSize = (ulong)imageFilter.GetDataForkLength();
+            imageInfo.CreationTime = imageFilter.GetCreationTime();
+            imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
+            imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
             differentTrackZeroSize = false;
             rawImageFilter = imageFilter;
 
             switch(imageFilter.GetDataForkLength())
             {
                 case 242944:
-                    ImageInfo.Sectors = 1898;
+                    imageInfo.Sectors = 1898;
                     break;
                 case 256256:
-                    ImageInfo.Sectors = 2002;
+                    imageInfo.Sectors = 2002;
                     break;
                 case 495872:
-                    ImageInfo.Sectors = 3874;
+                    imageInfo.Sectors = 3874;
                     break;
                 case 116480:
-                    ImageInfo.Sectors = 455;
+                    imageInfo.Sectors = 455;
                     break;
                 case 287488: // T0S0 = 128bps
-                    ImageInfo.Sectors = 1136;
+                    imageInfo.Sectors = 1136;
                     differentTrackZeroSize = true;
                     break;
                 case 988416: // T0S0 = 128bps
-                    ImageInfo.Sectors = 3874;
+                    imageInfo.Sectors = 3874;
                     differentTrackZeroSize = true;
                     break;
                 case 995072: // T0S0 = 128bps, T0S1 = 256bps
-                    ImageInfo.Sectors = 3900;
+                    imageInfo.Sectors = 3900;
                     differentTrackZeroSize = true;
                     break;
                 case 1021696: // T0S0 = 128bps, T0S1 = 256bps
-                    ImageInfo.Sectors = 4004;
+                    imageInfo.Sectors = 4004;
                     differentTrackZeroSize = true;
                     break;
                 case 81664:
-                    ImageInfo.Sectors = 256;
+                    imageInfo.Sectors = 256;
                     break;
                 case 306432: // T0S0 = 128bps
-                    ImageInfo.Sectors = 618;
+                    imageInfo.Sectors = 618;
                     differentTrackZeroSize = true;
                     break;
                 case 1146624: // T0S0 = 128bps, T0S1 = 256bps
-                    ImageInfo.Sectors = 2272;
+                    imageInfo.Sectors = 2272;
                     differentTrackZeroSize = true;
                     break;
                 case 1177344: // T0S0 = 128bps, T0S1 = 256bps
-                    ImageInfo.Sectors = 2332;
+                    imageInfo.Sectors = 2332;
                     differentTrackZeroSize = true;
                     break;
                 case 1222400: // T0S0 = 128bps, T0S1 = 256bps
-                    ImageInfo.Sectors = 1236;
+                    imageInfo.Sectors = 1236;
                     differentTrackZeroSize = true;
                     break;
                 case 1304320: // T0S0 = 128bps, T0S1 = 256bps
-                    ImageInfo.Sectors = 1316;
+                    imageInfo.Sectors = 1316;
                     differentTrackZeroSize = true;
                     break;
                 case 1255168: // T0S0 = 128bps, T0S1 = 256bps
-                    ImageInfo.Sectors = 1268;
+                    imageInfo.Sectors = 1268;
                     differentTrackZeroSize = true;
                     break;
                 case 80384: // T0S0 = 128bps
-                    ImageInfo.Sectors = 322;
+                    imageInfo.Sectors = 322;
                     differentTrackZeroSize = true;
                     break;
                 case 325632: // T0S0 = 128bps, T0S1 = 256bps
-                    ImageInfo.Sectors = 1280;
+                    imageInfo.Sectors = 1280;
                     differentTrackZeroSize = true;
                     break;
                 case 653312: // T0S0 = 128bps, T0S1 = 256bps
-                    ImageInfo.Sectors = 2560;
+                    imageInfo.Sectors = 2560;
                     differentTrackZeroSize = true;
                     break;
                 case 1880064: // IBM XDF, 3,5", real number of sectors
-                    ImageInfo.Sectors = 670;
-                    ImageInfo.SectorSize = 8192; // Biggest sector size
+                    imageInfo.Sectors = 670;
+                    imageInfo.SectorSize = 8192; // Biggest sector size
                     differentTrackZeroSize = true;
                     break;
                 case 175531:
-                    ImageInfo.Sectors = 683;
+                    imageInfo.Sectors = 683;
                     break;
                 case 197375:
-                    ImageInfo.Sectors = 768;
+                    imageInfo.Sectors = 768;
                     break;
                 case 351062:
-                    ImageInfo.Sectors = 1366;
+                    imageInfo.Sectors = 1366;
                     break;
                 case 822400:
-                    ImageInfo.Sectors = 3200;
+                    imageInfo.Sectors = 3200;
                     break;
                 default:
-                    ImageInfo.Sectors = ImageInfo.ImageSize / ImageInfo.SectorSize;
+                    imageInfo.Sectors = imageInfo.ImageSize / imageInfo.SectorSize;
                     break;
             }
 
-            ImageInfo.MediaType = CalculateDiskType();
+            imageInfo.MediaType = CalculateDiskType();
 
-            switch(ImageInfo.MediaType)
+            switch(imageInfo.MediaType)
             {
                 case MediaType.CD:
                 case MediaType.DVDPR:
@@ -374,390 +377,390 @@ namespace DiscImageChef.DiscImages
                 case MediaType.DVDPRDL:
                 case MediaType.BDR:
                 case MediaType.BDRXL:
-                    ImageInfo.XmlMediaType = XmlMediaType.OpticalDisc;
+                    imageInfo.XmlMediaType = XmlMediaType.OpticalDisc;
                     break;
                 default:
-                    ImageInfo.XmlMediaType = XmlMediaType.BlockMedia;
+                    imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
                     break;
             }
 
             // Sharp X68000 SASI hard disks
             if(extension == ".hdf")
-                if(ImageInfo.ImageSize % 256 == 0)
+                if(imageInfo.ImageSize % 256 == 0)
                 {
-                    ImageInfo.SectorSize = 256;
-                    ImageInfo.Sectors = ImageInfo.ImageSize / ImageInfo.SectorSize;
-                    ImageInfo.MediaType = MediaType.GENERIC_HDD;
+                    imageInfo.SectorSize = 256;
+                    imageInfo.Sectors = imageInfo.ImageSize / imageInfo.SectorSize;
+                    imageInfo.MediaType = MediaType.GENERIC_HDD;
                 }
 
-            if(ImageInfo.XmlMediaType == XmlMediaType.OpticalDisc)
+            if(imageInfo.XmlMediaType == XmlMediaType.OpticalDisc)
             {
-                ImageInfo.HasSessions = true;
-                ImageInfo.HasPartitions = true;
+                imageInfo.HasSessions = true;
+                imageInfo.HasPartitions = true;
             }
 
-            DicConsole.VerboseWriteLine("Raw disk image contains a disk of type {0}", ImageInfo.MediaType);
+            DicConsole.VerboseWriteLine("Raw disk image contains a disk of type {0}", imageInfo.MediaType);
 
-            switch(ImageInfo.MediaType)
+            switch(imageInfo.MediaType)
             {
                 case MediaType.ACORN_35_DS_DD:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 5;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 5;
                     break;
                 case MediaType.ACORN_35_DS_HD:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 10;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 10;
                     break;
                 case MediaType.ACORN_525_DS_DD:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 16;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 16;
                     break;
                 case MediaType.ACORN_525_SS_DD_40:
-                    ImageInfo.Cylinders = 40;
-                    ImageInfo.Heads = 1;
-                    ImageInfo.SectorsPerTrack = 16;
+                    imageInfo.Cylinders = 40;
+                    imageInfo.Heads = 1;
+                    imageInfo.SectorsPerTrack = 16;
                     break;
                 case MediaType.ACORN_525_SS_DD_80:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 1;
-                    ImageInfo.SectorsPerTrack = 16;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 1;
+                    imageInfo.SectorsPerTrack = 16;
                     break;
                 case MediaType.ACORN_525_SS_SD_40:
-                    ImageInfo.Cylinders = 40;
-                    ImageInfo.Heads = 1;
-                    ImageInfo.SectorsPerTrack = 10;
+                    imageInfo.Cylinders = 40;
+                    imageInfo.Heads = 1;
+                    imageInfo.SectorsPerTrack = 10;
                     break;
                 case MediaType.ACORN_525_SS_SD_80:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 1;
-                    ImageInfo.SectorsPerTrack = 10;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 1;
+                    imageInfo.SectorsPerTrack = 10;
                     break;
                 case MediaType.Apple32DS:
-                    ImageInfo.Cylinders = 35;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 13;
+                    imageInfo.Cylinders = 35;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 13;
                     break;
                 case MediaType.Apple32SS:
-                    ImageInfo.Cylinders = 36;
-                    ImageInfo.Heads = 1;
-                    ImageInfo.SectorsPerTrack = 13;
+                    imageInfo.Cylinders = 36;
+                    imageInfo.Heads = 1;
+                    imageInfo.SectorsPerTrack = 13;
                     break;
                 case MediaType.Apple33DS:
-                    ImageInfo.Cylinders = 35;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 16;
+                    imageInfo.Cylinders = 35;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 16;
                     break;
                 case MediaType.Apple33SS:
-                    ImageInfo.Cylinders = 35;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 16;
+                    imageInfo.Cylinders = 35;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 16;
                     break;
                 case MediaType.AppleSonyDS:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 10;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 10;
                     break;
                 case MediaType.AppleSonySS:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 1;
-                    ImageInfo.SectorsPerTrack = 10;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 1;
+                    imageInfo.SectorsPerTrack = 10;
                     break;
                 case MediaType.ATARI_35_DS_DD:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 10;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 10;
                     break;
                 case MediaType.ATARI_35_DS_DD_11:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 11;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 11;
                     break;
                 case MediaType.ATARI_35_SS_DD:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 1;
-                    ImageInfo.SectorsPerTrack = 10;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 1;
+                    imageInfo.SectorsPerTrack = 10;
                     break;
                 case MediaType.ATARI_35_SS_DD_11:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 1;
-                    ImageInfo.SectorsPerTrack = 11;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 1;
+                    imageInfo.SectorsPerTrack = 11;
                     break;
                 case MediaType.ATARI_525_ED:
-                    ImageInfo.Cylinders = 40;
-                    ImageInfo.Heads = 1;
-                    ImageInfo.SectorsPerTrack = 26;
+                    imageInfo.Cylinders = 40;
+                    imageInfo.Heads = 1;
+                    imageInfo.SectorsPerTrack = 26;
                     break;
                 case MediaType.ATARI_525_SD:
-                    ImageInfo.Cylinders = 40;
-                    ImageInfo.Heads = 1;
-                    ImageInfo.SectorsPerTrack = 18;
+                    imageInfo.Cylinders = 40;
+                    imageInfo.Heads = 1;
+                    imageInfo.SectorsPerTrack = 18;
                     break;
                 case MediaType.CBM_35_DD:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 10;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 10;
                     break;
                 case MediaType.CBM_AMIGA_35_DD:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 11;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 11;
                     break;
                 case MediaType.CBM_AMIGA_35_HD:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 22;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 22;
                     break;
                 case MediaType.DMF:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 21;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 21;
                     break;
                 case MediaType.DOS_35_DS_DD_9:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 9;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 9;
                     break;
                 case MediaType.Apricot_35:
-                    ImageInfo.Cylinders = 70;
-                    ImageInfo.Heads = 1;
-                    ImageInfo.SectorsPerTrack = 9;
+                    imageInfo.Cylinders = 70;
+                    imageInfo.Heads = 1;
+                    imageInfo.SectorsPerTrack = 9;
                     break;
                 case MediaType.DOS_35_ED:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 36;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 36;
                     break;
                 case MediaType.DOS_35_HD:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 18;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 18;
                     break;
                 case MediaType.DOS_35_SS_DD_9:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 1;
-                    ImageInfo.SectorsPerTrack = 9;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 1;
+                    imageInfo.SectorsPerTrack = 9;
                     break;
                 case MediaType.DOS_525_DS_DD_8:
-                    ImageInfo.Cylinders = 40;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 8;
+                    imageInfo.Cylinders = 40;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 8;
                     break;
                 case MediaType.DOS_525_DS_DD_9:
-                    ImageInfo.Cylinders = 40;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 9;
+                    imageInfo.Cylinders = 40;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 9;
                     break;
                 case MediaType.DOS_525_HD:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 15;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 15;
                     break;
                 case MediaType.DOS_525_SS_DD_8:
-                    ImageInfo.Cylinders = 40;
-                    ImageInfo.Heads = 1;
-                    ImageInfo.SectorsPerTrack = 8;
+                    imageInfo.Cylinders = 40;
+                    imageInfo.Heads = 1;
+                    imageInfo.SectorsPerTrack = 8;
                     break;
                 case MediaType.DOS_525_SS_DD_9:
-                    ImageInfo.Cylinders = 40;
-                    ImageInfo.Heads = 1;
-                    ImageInfo.SectorsPerTrack = 9;
+                    imageInfo.Cylinders = 40;
+                    imageInfo.Heads = 1;
+                    imageInfo.SectorsPerTrack = 9;
                     break;
                 case MediaType.ECMA_54:
-                    ImageInfo.Cylinders = 77;
-                    ImageInfo.Heads = 1;
-                    ImageInfo.SectorsPerTrack = 26;
+                    imageInfo.Cylinders = 77;
+                    imageInfo.Heads = 1;
+                    imageInfo.SectorsPerTrack = 26;
                     break;
                 case MediaType.ECMA_59:
-                    ImageInfo.Cylinders = 77;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 26;
+                    imageInfo.Cylinders = 77;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 26;
                     break;
                 case MediaType.ECMA_66:
-                    ImageInfo.Cylinders = 35;
-                    ImageInfo.Heads = 1;
-                    ImageInfo.SectorsPerTrack = 9;
+                    imageInfo.Cylinders = 35;
+                    imageInfo.Heads = 1;
+                    imageInfo.SectorsPerTrack = 9;
                     break;
                 case MediaType.ECMA_69_8:
-                    ImageInfo.Cylinders = 77;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 8;
+                    imageInfo.Cylinders = 77;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 8;
                     break;
                 case MediaType.ECMA_70:
-                    ImageInfo.Cylinders = 40;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 16;
+                    imageInfo.Cylinders = 40;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 16;
                     break;
                 case MediaType.ECMA_78:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 16;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 16;
                     break;
                 case MediaType.ECMA_99_15:
-                    ImageInfo.Cylinders = 77;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 15;
+                    imageInfo.Cylinders = 77;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 15;
                     break;
                 case MediaType.ECMA_99_26:
-                    ImageInfo.Cylinders = 77;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 26;
+                    imageInfo.Cylinders = 77;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 26;
                     break;
                 case MediaType.ECMA_99_8:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 8;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 8;
                     break;
                 case MediaType.FDFORMAT_35_DD:
-                    ImageInfo.Cylinders = 82;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 10;
+                    imageInfo.Cylinders = 82;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 10;
                     break;
                 case MediaType.FDFORMAT_35_HD:
-                    ImageInfo.Cylinders = 82;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 21;
+                    imageInfo.Cylinders = 82;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 21;
                     break;
                 case MediaType.FDFORMAT_525_HD:
-                    ImageInfo.Cylinders = 82;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 17;
+                    imageInfo.Cylinders = 82;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 17;
                     break;
                 case MediaType.IBM23FD:
-                    ImageInfo.Cylinders = 32;
-                    ImageInfo.Heads = 1;
-                    ImageInfo.SectorsPerTrack = 8;
+                    imageInfo.Cylinders = 32;
+                    imageInfo.Heads = 1;
+                    imageInfo.SectorsPerTrack = 8;
                     break;
                 case MediaType.IBM33FD_128:
-                    ImageInfo.Cylinders = 73;
-                    ImageInfo.Heads = 1;
-                    ImageInfo.SectorsPerTrack = 26;
+                    imageInfo.Cylinders = 73;
+                    imageInfo.Heads = 1;
+                    imageInfo.SectorsPerTrack = 26;
                     break;
                 case MediaType.IBM33FD_256:
-                    ImageInfo.Cylinders = 74;
-                    ImageInfo.Heads = 1;
-                    ImageInfo.SectorsPerTrack = 15;
+                    imageInfo.Cylinders = 74;
+                    imageInfo.Heads = 1;
+                    imageInfo.SectorsPerTrack = 15;
                     break;
                 case MediaType.IBM33FD_512:
-                    ImageInfo.Cylinders = 74;
-                    ImageInfo.Heads = 1;
-                    ImageInfo.SectorsPerTrack = 8;
+                    imageInfo.Cylinders = 74;
+                    imageInfo.Heads = 1;
+                    imageInfo.SectorsPerTrack = 8;
                     break;
                 case MediaType.IBM43FD_128:
-                    ImageInfo.Cylinders = 74;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 26;
+                    imageInfo.Cylinders = 74;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 26;
                     break;
                 case MediaType.IBM43FD_256:
-                    ImageInfo.Cylinders = 74;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 15;
+                    imageInfo.Cylinders = 74;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 15;
                     break;
                 case MediaType.IBM53FD_1024:
-                    ImageInfo.Cylinders = 74;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 8;
+                    imageInfo.Cylinders = 74;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 8;
                     break;
                 case MediaType.IBM53FD_256:
-                    ImageInfo.Cylinders = 74;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 26;
+                    imageInfo.Cylinders = 74;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 26;
                     break;
                 case MediaType.IBM53FD_512:
-                    ImageInfo.Cylinders = 74;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 15;
+                    imageInfo.Cylinders = 74;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 15;
                     break;
                 case MediaType.NEC_35_TD:
-                    ImageInfo.Cylinders = 240;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 38;
+                    imageInfo.Cylinders = 240;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 38;
                     break;
                 case MediaType.NEC_525_HD:
-                    ImageInfo.Cylinders = 77;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 8;
+                    imageInfo.Cylinders = 77;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 8;
                     break;
                 case MediaType.XDF_35:
-                    ImageInfo.Cylinders = 80;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 23;
+                    imageInfo.Cylinders = 80;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 23;
                     break;
                 // Following ones are what the device itself report, not the physical geometry
                 case MediaType.Jaz:
-                    ImageInfo.Cylinders = 1021;
-                    ImageInfo.Heads = 64;
-                    ImageInfo.SectorsPerTrack = 32;
+                    imageInfo.Cylinders = 1021;
+                    imageInfo.Heads = 64;
+                    imageInfo.SectorsPerTrack = 32;
                     break;
                 case MediaType.PocketZip:
-                    ImageInfo.Cylinders = 154;
-                    ImageInfo.Heads = 16;
-                    ImageInfo.SectorsPerTrack = 32;
+                    imageInfo.Cylinders = 154;
+                    imageInfo.Heads = 16;
+                    imageInfo.SectorsPerTrack = 32;
                     break;
                 case MediaType.LS120:
-                    ImageInfo.Cylinders = 963;
-                    ImageInfo.Heads = 8;
-                    ImageInfo.SectorsPerTrack = 32;
+                    imageInfo.Cylinders = 963;
+                    imageInfo.Heads = 8;
+                    imageInfo.SectorsPerTrack = 32;
                     break;
                 case MediaType.LS240:
-                    ImageInfo.Cylinders = 262;
-                    ImageInfo.Heads = 32;
-                    ImageInfo.SectorsPerTrack = 56;
+                    imageInfo.Cylinders = 262;
+                    imageInfo.Heads = 32;
+                    imageInfo.SectorsPerTrack = 56;
                     break;
                 case MediaType.FD32MB:
-                    ImageInfo.Cylinders = 1024;
-                    ImageInfo.Heads = 2;
-                    ImageInfo.SectorsPerTrack = 32;
+                    imageInfo.Cylinders = 1024;
+                    imageInfo.Heads = 2;
+                    imageInfo.SectorsPerTrack = 32;
                     break;
                 default:
-                    ImageInfo.Cylinders = (uint)(ImageInfo.Sectors / 16 / 63);
-                    ImageInfo.Heads = 16;
-                    ImageInfo.SectorsPerTrack = 63;
+                    imageInfo.Cylinders = (uint)(imageInfo.Sectors / 16 / 63);
+                    imageInfo.Heads = 16;
+                    imageInfo.SectorsPerTrack = 63;
                     break;
             }
 
             return true;
         }
 
-        public override byte[] ReadSector(ulong sectorAddress)
+        public virtual byte[] ReadSector(ulong sectorAddress)
         {
             return ReadSectors(sectorAddress, 1);
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length)
         {
             if(differentTrackZeroSize) throw new NotImplementedException("Not yet implemented");
 
-            if(sectorAddress > ImageInfo.Sectors - 1)
+            if(sectorAddress > imageInfo.Sectors - 1)
                 throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
 
-            if(sectorAddress + length > ImageInfo.Sectors)
+            if(sectorAddress + length > imageInfo.Sectors)
                 throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
 
-            byte[] buffer = new byte[length * ImageInfo.SectorSize];
+            byte[] buffer = new byte[length * imageInfo.SectorSize];
 
             Stream stream = rawImageFilter.GetDataForkStream();
 
-            stream.Seek((long)(sectorAddress * ImageInfo.SectorSize), SeekOrigin.Begin);
+            stream.Seek((long)(sectorAddress * imageInfo.SectorSize), SeekOrigin.Begin);
 
-            stream.Read(buffer, 0, (int)(length * ImageInfo.SectorSize));
+            stream.Read(buffer, 0, (int)(length * imageInfo.SectorSize));
 
             return buffer;
         }
 
-        public override bool? VerifySector(ulong sectorAddress)
+        public virtual bool? VerifySector(ulong sectorAddress)
         {
             return null;
         }
 
-        public override bool? VerifySector(ulong sectorAddress, uint track)
+        public virtual bool? VerifySector(ulong sectorAddress, uint track)
         {
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
@@ -768,7 +771,7 @@ namespace DiscImageChef.DiscImages
             return null;
         }
 
-        public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
+        public virtual bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas,
                                             out List unknownLbas)
         {
             failingLbas = new List();
@@ -779,14 +782,14 @@ namespace DiscImageChef.DiscImages
             return null;
         }
 
-        public override bool? VerifyMediaImage()
+        public virtual bool? VerifyMediaImage()
         {
             return null;
         }
 
-        public override List GetSessionTracks(Session session)
+        public virtual List GetSessionTracks(Session session)
         {
-            if(ImageInfo.XmlMediaType != XmlMediaType.OpticalDisc)
+            if(imageInfo.XmlMediaType != XmlMediaType.OpticalDisc)
                 throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
             if(session.SessionSequence != 1)
@@ -794,13 +797,13 @@ namespace DiscImageChef.DiscImages
 
             Track trk = new Track
             {
-                TrackBytesPerSector = (int)ImageInfo.SectorSize,
-                TrackEndSector = ImageInfo.Sectors - 1,
+                TrackBytesPerSector = (int)imageInfo.SectorSize,
+                TrackEndSector = imageInfo.Sectors - 1,
                 TrackFilter = rawImageFilter,
                 TrackFile = rawImageFilter.GetFilename(),
                 TrackFileOffset = 0,
                 TrackFileType = "BINARY",
-                TrackRawBytesPerSector = (int)ImageInfo.SectorSize,
+                TrackRawBytesPerSector = (int)imageInfo.SectorSize,
                 TrackSequence = 1,
                 TrackStartSector = 0,
                 TrackSubchannelType = TrackSubchannelType.None,
@@ -811,9 +814,9 @@ namespace DiscImageChef.DiscImages
             return lst;
         }
 
-        public override List GetSessionTracks(ushort session)
+        public virtual List GetSessionTracks(ushort session)
         {
-            if(ImageInfo.XmlMediaType != XmlMediaType.OpticalDisc)
+            if(imageInfo.XmlMediaType != XmlMediaType.OpticalDisc)
                 throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
             if(session != 1)
@@ -821,13 +824,13 @@ namespace DiscImageChef.DiscImages
 
             Track trk = new Track
             {
-                TrackBytesPerSector = (int)ImageInfo.SectorSize,
-                TrackEndSector = ImageInfo.Sectors - 1,
+                TrackBytesPerSector = (int)imageInfo.SectorSize,
+                TrackEndSector = imageInfo.Sectors - 1,
                 TrackFilter = rawImageFilter,
                 TrackFile = rawImageFilter.GetFilename(),
                 TrackFileOffset = 0,
                 TrackFileType = "BINARY",
-                TrackRawBytesPerSector = (int)ImageInfo.SectorSize,
+                TrackRawBytesPerSector = (int)imageInfo.SectorSize,
                 TrackSequence = 1,
                 TrackStartSector = 0,
                 TrackSubchannelType = TrackSubchannelType.None,
@@ -838,9 +841,9 @@ namespace DiscImageChef.DiscImages
             return lst;
         }
 
-        public override byte[] ReadSector(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSector(ulong sectorAddress, uint track)
         {
-            if(ImageInfo.XmlMediaType != XmlMediaType.OpticalDisc)
+            if(imageInfo.XmlMediaType != XmlMediaType.OpticalDisc)
                 throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
             if(track != 1) throw new ArgumentOutOfRangeException(nameof(track), "Only a single track is supported");
@@ -848,9 +851,9 @@ namespace DiscImageChef.DiscImages
             return ReadSector(sectorAddress);
         }
 
-        public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
         {
-            if(ImageInfo.XmlMediaType != XmlMediaType.OpticalDisc)
+            if(imageInfo.XmlMediaType != XmlMediaType.OpticalDisc)
                 throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
             if(track != 1) throw new ArgumentOutOfRangeException(nameof(track), "Only a single track is supported");
@@ -858,9 +861,9 @@ namespace DiscImageChef.DiscImages
             return ReadSectors(sectorAddress, length);
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress, uint track)
         {
-            if(ImageInfo.XmlMediaType != XmlMediaType.OpticalDisc)
+            if(imageInfo.XmlMediaType != XmlMediaType.OpticalDisc)
                 throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
             if(track != 1) throw new ArgumentOutOfRangeException(nameof(track), "Only a single track is supported");
@@ -868,9 +871,9 @@ namespace DiscImageChef.DiscImages
             return ReadSector(sectorAddress);
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
         {
-            if(ImageInfo.XmlMediaType != XmlMediaType.OpticalDisc)
+            if(imageInfo.XmlMediaType != XmlMediaType.OpticalDisc)
                 throw new FeatureUnsupportedImageException("Feature not supported by image format");
 
             if(track != 1) throw new ArgumentOutOfRangeException(nameof(track), "Only a single track is supported");
@@ -880,19 +883,19 @@ namespace DiscImageChef.DiscImages
 
         MediaType CalculateDiskType()
         {
-            if(ImageInfo.SectorSize == 2048)
+            if(imageInfo.SectorSize == 2048)
             {
-                if(ImageInfo.Sectors <= 360000) return MediaType.CD;
-                if(ImageInfo.Sectors <= 2295104) return MediaType.DVDPR;
-                if(ImageInfo.Sectors <= 2298496) return MediaType.DVDR;
-                if(ImageInfo.Sectors <= 4171712) return MediaType.DVDRDL;
-                if(ImageInfo.Sectors <= 4173824) return MediaType.DVDPRDL;
-                if(ImageInfo.Sectors <= 24438784) return MediaType.BDR;
+                if(imageInfo.Sectors <= 360000) return MediaType.CD;
+                if(imageInfo.Sectors <= 2295104) return MediaType.DVDPR;
+                if(imageInfo.Sectors <= 2298496) return MediaType.DVDR;
+                if(imageInfo.Sectors <= 4171712) return MediaType.DVDRDL;
+                if(imageInfo.Sectors <= 4173824) return MediaType.DVDPRDL;
+                if(imageInfo.Sectors <= 24438784) return MediaType.BDR;
 
-                return ImageInfo.Sectors <= 62500864 ? MediaType.BDRXL : MediaType.Unknown;
+                return imageInfo.Sectors <= 62500864 ? MediaType.BDRXL : MediaType.Unknown;
             }
 
-            switch(ImageInfo.ImageSize)
+            switch(imageInfo.ImageSize)
             {
                 case 80384: return MediaType.ECMA_66;
                 case 81664: return MediaType.IBM23FD;
@@ -902,7 +905,7 @@ namespace DiscImageChef.DiscImages
                 case 133120: return MediaType.ATARI_525_ED;
                 case 143360: return MediaType.Apple33SS;
                 case 163840:
-                    if(ImageInfo.SectorSize == 256) return MediaType.ACORN_525_SS_DD_40;
+                    if(imageInfo.SectorSize == 256) return MediaType.ACORN_525_SS_DD_40;
 
                     return MediaType.DOS_525_SS_DD_8;
                 case 184320: return MediaType.DOS_525_SS_DD_9;
@@ -916,7 +919,7 @@ namespace DiscImageChef.DiscImages
                 case 322560: return MediaType.Apricot_35;
                 case 325632: return MediaType.ECMA_70;
                 case 327680:
-                    if(ImageInfo.SectorSize == 256) return MediaType.ACORN_525_SS_DD_80;
+                    if(imageInfo.SectorSize == 256) return MediaType.ACORN_525_SS_DD_80;
 
                     return MediaType.DOS_525_DS_DD_8;
                 case 368640:
@@ -934,8 +937,8 @@ namespace DiscImageChef.DiscImages
                 case 655360: return MediaType.ACORN_525_DS_DD;
                 case 737280: return MediaType.DOS_35_DS_DD_9;
                 case 819200:
-                    if(ImageInfo.SectorSize == 256) return MediaType.CBM_35_DD;
-                    if((extension == ".adf" || extension == ".adl") && ImageInfo.SectorSize == 1024)
+                    if(imageInfo.SectorSize == 256) return MediaType.CBM_35_DD;
+                    if((extension == ".adf" || extension == ".adl") && imageInfo.SectorSize == 1024)
                         return MediaType.ACORN_35_DS_DD;
                     if(extension == ".st") return MediaType.ATARI_35_DS_DD;
 
@@ -991,37 +994,37 @@ namespace DiscImageChef.DiscImages
             }
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorLong(ulong sectorAddress)
+        public virtual byte[] ReadSectorLong(ulong sectorAddress)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
+        public virtual byte[] ReadSectorsLong(ulong sectorAddress, uint length)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadDiskTag(MediaTagType tag)
+        public virtual byte[] ReadDiskTag(MediaTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
 
-        public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
+        public virtual byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
         {
             throw new FeatureUnsupportedImageException("Feature not supported by image format");
         }
diff --git a/DiscImageChef.Filesystems/AODOS.cs b/DiscImageChef.Filesystems/AODOS.cs
index d13d7969..a30dc1a4 100644
--- a/DiscImageChef.Filesystems/AODOS.cs
+++ b/DiscImageChef.Filesystems/AODOS.cs
@@ -43,41 +43,26 @@ namespace DiscImageChef.Filesystems
 {
     // Information has been extracted looking at available disk images
     // This may be missing fields, or not, I don't know russian so any help is appreciated
-    public class AODOS : Filesystem
+    public class AODOS : IFilesystem
     {
         readonly byte[] AODOSIdentifier = {0x20, 0x41, 0x4F, 0x2D, 0x44, 0x4F, 0x53, 0x20};
+        Encoding currentEncoding;
+        FileSystemType xmlFsType;
+        public virtual FileSystemType XmlFsType => xmlFsType;
+        public virtual string Name => "Alexander Osipov DOS file system";
+        public virtual Guid Id => new Guid("668E5039-9DDD-442A-BE1B-A315D6E38E26");
+        public virtual Encoding Encoding => currentEncoding;
 
-        public AODOS()
-        {
-            Name = "Alexander Osipov DOS file system";
-            PluginUuid = new Guid("668E5039-9DDD-442A-BE1B-A315D6E38E26");
-            CurrentEncoding = Encoding.GetEncoding("koi8-r");
-        }
-
-        public AODOS(Encoding encoding)
-        {
-            Name = "Alexander Osipov DOS file system";
-            PluginUuid = new Guid("668E5039-9DDD-442A-BE1B-A315D6E38E26");
-            CurrentEncoding = Encoding.GetEncoding("koi8-r");
-        }
-
-        public AODOS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
-        {
-            Name = "Alexander Osipov DOS file system";
-            PluginUuid = new Guid("668E5039-9DDD-442A-BE1B-A315D6E38E26");
-            CurrentEncoding = Encoding.GetEncoding("koi8-r");
-        }
-
-        public override bool Identify(ImagePlugin imagePlugin, Partition partition)
+        public virtual bool Identify(IMediaImage imagePlugin, Partition partition)
         {
             // Does AO-DOS support hard disks?
             if(partition.Start > 0) return false;
 
             // How is it really?
-            if(imagePlugin.ImageInfo.SectorSize != 512) return false;
+            if(imagePlugin.Info.SectorSize != 512) return false;
 
             // Does AO-DOS support any other kind of disk?
-            if(imagePlugin.ImageInfo.Sectors != 800 && imagePlugin.ImageInfo.Sectors != 1600) return false;
+            if(imagePlugin.Info.Sectors != 800 && imagePlugin.Info.Sectors != 1600) return false;
 
             byte[] sector = imagePlugin.ReadSector(0);
             AODOS_BootBlock bb = new AODOS_BootBlock();
@@ -89,8 +74,9 @@ namespace DiscImageChef.Filesystems
             return bb.identifier.SequenceEqual(AODOSIdentifier);
         }
 
-        public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information)
+        public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding)
         {
+            currentEncoding = Encoding.GetEncoding("koi8-r");
             byte[] sector = imagePlugin.ReadSector(0);
             AODOS_BootBlock bb = new AODOS_BootBlock();
             IntPtr bbPtr = Marshal.AllocHGlobal(Marshal.SizeOf(bb));
@@ -102,83 +88,78 @@ namespace DiscImageChef.Filesystems
 
             sbInformation.AppendLine("Alexander Osipov DOS file system");
 
-            XmlFsType = new FileSystemType
+            xmlFsType = new FileSystemType
             {
                 Type = "Alexander Osipov DOS file system",
-                Clusters = (long)imagePlugin.ImageInfo.Sectors,
-                ClusterSize = (int)imagePlugin.ImageInfo.SectorSize,
+                Clusters = (long)imagePlugin.Info.Sectors,
+                ClusterSize = (int)imagePlugin.Info.SectorSize,
                 Files = bb.files,
                 FilesSpecified = true,
-                FreeClusters = (long)(imagePlugin.ImageInfo.Sectors - bb.usedSectors),
+                FreeClusters = (long)(imagePlugin.Info.Sectors - bb.usedSectors),
                 FreeClustersSpecified = true,
-                VolumeName = StringHandlers.SpacePaddedToString(bb.volumeLabel, CurrentEncoding),
+                VolumeName = StringHandlers.SpacePaddedToString(bb.volumeLabel, currentEncoding),
                 Bootable = true
             };
 
             sbInformation.AppendFormat("{0} files on volume", bb.files).AppendLine();
             sbInformation.AppendFormat("{0} used sectors on volume", bb.usedSectors).AppendLine();
-            sbInformation.AppendFormat("Disk name: {0}", StringHandlers.CToString(bb.volumeLabel, CurrentEncoding))
+            sbInformation.AppendFormat("Disk name: {0}", StringHandlers.CToString(bb.volumeLabel, currentEncoding))
                          .AppendLine();
 
             information = sbInformation.ToString();
         }
 
-        public override Errno Mount()
+        public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Mount(bool debug)
+        public virtual Errno Unmount()
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Unmount()
+        public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
+        public virtual Errno GetAttributes(string path, ref FileAttributes attributes)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno GetAttributes(string path, ref FileAttributes attributes)
+        public virtual Errno ListXAttr(string path, ref List xattrs)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno ListXAttr(string path, ref List xattrs)
+        public virtual Errno GetXattr(string path, string xattr, ref byte[] buf)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno GetXattr(string path, string xattr, ref byte[] buf)
+        public virtual Errno Read(string path, long offset, long size, ref byte[] buf)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Read(string path, long offset, long size, ref byte[] buf)
+        public virtual Errno ReadDir(string path, ref List contents)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno ReadDir(string path, ref List contents)
+        public virtual Errno StatFs(ref FileSystemInfo stat)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno StatFs(ref FileSystemInfo stat)
+        public virtual Errno Stat(string path, ref FileEntryInfo stat)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Stat(string path, ref FileEntryInfo stat)
-        {
-            return Errno.NotImplemented;
-        }
-
-        public override Errno ReadLink(string path, ref string dest)
+        public virtual Errno ReadLink(string path, ref string dest)
         {
             return Errno.NotImplemented;
         }
diff --git a/DiscImageChef.Filesystems/APFS.cs b/DiscImageChef.Filesystems/APFS.cs
index c10a1215..efd9e526 100644
--- a/DiscImageChef.Filesystems/APFS.cs
+++ b/DiscImageChef.Filesystems/APFS.cs
@@ -40,33 +40,19 @@ using Schemas;
 
 namespace DiscImageChef.Filesystems
 {
-    public class APFS : Filesystem
+    public class APFS : IFilesystem
     {
         const uint APFS_CONTAINER_MAGIC = 0x4253584E; // "NXSB"
         const uint APFS_VOLUME_MAGIC = 0x42535041; // "APSB"
+        FileSystemType xmlFsType;
+        public virtual FileSystemType XmlFsType => xmlFsType;
 
-        public APFS()
-        {
-            Name = "Apple File System";
-            PluginUuid = new Guid("A4060F9D-2909-42E2-9D95-DB31FA7EA797");
-            CurrentEncoding = Encoding.UTF8;
-        }
+        Encoding currentEncoding;
+        public virtual Encoding Encoding => currentEncoding;
+        public virtual string Name => "Apple File System";
+        public virtual Guid Id => new Guid("A4060F9D-2909-42E2-9D95-DB31FA7EA797");
 
-        public APFS(Encoding encoding)
-        {
-            Name = "Apple File System";
-            PluginUuid = new Guid("A4060F9D-2909-42E2-9D95-DB31FA7EA797");
-            CurrentEncoding = Encoding.UTF8;
-        }
-
-        public APFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
-        {
-            Name = "Apple File System";
-            PluginUuid = new Guid("A4060F9D-2909-42E2-9D95-DB31FA7EA797");
-            CurrentEncoding = Encoding.UTF8;
-        }
-
-        public override bool Identify(ImagePlugin imagePlugin, Partition partition)
+        public virtual bool Identify(IMediaImage imagePlugin, Partition partition)
         {
             if(partition.Start >= partition.End) return false;
 
@@ -85,10 +71,12 @@ namespace DiscImageChef.Filesystems
             return nxSb.magic == APFS_CONTAINER_MAGIC;
         }
 
-        public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information)
+        public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
+                                            Encoding encoding)
         {
+            currentEncoding = Encoding.UTF8;
             StringBuilder sbInformation = new StringBuilder();
-            XmlFsType = new FileSystemType();
+            xmlFsType = new FileSystemType();
             information = "";
 
             if(partition.Start >= partition.End) return;
@@ -115,7 +103,7 @@ namespace DiscImageChef.Filesystems
 
             information = sbInformation.ToString();
 
-            XmlFsType = new FileSystemType
+            xmlFsType = new FileSystemType
             {
                 Bootable = false,
                 Clusters = (long)nxSb.containerBlocks,
@@ -124,62 +112,57 @@ namespace DiscImageChef.Filesystems
             };
         }
 
-        public override Errno Mount()
+        public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Mount(bool debug)
+        public virtual Errno Unmount()
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Unmount()
+        public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
+        public virtual Errno GetAttributes(string path, ref FileAttributes attributes)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno GetAttributes(string path, ref FileAttributes attributes)
+        public virtual Errno ListXAttr(string path, ref List xattrs)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno ListXAttr(string path, ref List xattrs)
+        public virtual Errno GetXattr(string path, string xattr, ref byte[] buf)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno GetXattr(string path, string xattr, ref byte[] buf)
+        public virtual Errno Read(string path, long offset, long size, ref byte[] buf)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Read(string path, long offset, long size, ref byte[] buf)
+        public virtual Errno ReadDir(string path, ref List contents)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno ReadDir(string path, ref List contents)
+        public virtual Errno StatFs(ref FileSystemInfo stat)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno StatFs(ref FileSystemInfo stat)
+        public virtual Errno Stat(string path, ref FileEntryInfo stat)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Stat(string path, ref FileEntryInfo stat)
-        {
-            return Errno.NotImplemented;
-        }
-
-        public override Errno ReadLink(string path, ref string dest)
+        public virtual Errno ReadLink(string path, ref string dest)
         {
             return Errno.NotImplemented;
         }
diff --git a/DiscImageChef.Filesystems/Acorn.cs b/DiscImageChef.Filesystems/Acorn.cs
index 4dfc28c7..c6030c67 100644
--- a/DiscImageChef.Filesystems/Acorn.cs
+++ b/DiscImageChef.Filesystems/Acorn.cs
@@ -41,7 +41,7 @@ using Schemas;
 
 namespace DiscImageChef.Filesystems
 {
-    public class AcornADFS : Filesystem
+    public class AcornADFS : IFilesystem
     {
         /// 
         ///     Location for boot block, in bytes
@@ -76,37 +76,23 @@ namespace DiscImageChef.Filesystems
         ///     Old directory format magic number, "Hugo"
         /// 
         const uint OLD_DIR_MAGIC = 0x6F677548;
+        Encoding currentEncoding;
 
-        public AcornADFS()
-        {
-            Name = "Acorn Advanced Disc Filing System";
-            PluginUuid = new Guid("BAFC1E50-9C64-4CD3-8400-80628CC27AFA");
-            CurrentEncoding = Encoding.GetEncoding("iso-8859-1");
-        }
-
-        public AcornADFS(Encoding encoding)
-        {
-            Name = "Acorn Advanced Disc Filing System";
-            PluginUuid = new Guid("BAFC1E50-9C64-4CD3-8400-80628CC27AFA");
-            CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
-        }
-
-        public AcornADFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
-        {
-            Name = "Acorn Advanced Disc Filing System";
-            PluginUuid = new Guid("BAFC1E50-9C64-4CD3-8400-80628CC27AFA");
-            CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
-        }
+        FileSystemType xmlFsType;
+        public virtual FileSystemType XmlFsType => xmlFsType;
+        public virtual string Name => "Acorn Advanced Disc Filing System";
+        public virtual Guid Id => new Guid("BAFC1E50-9C64-4CD3-8400-80628CC27AFA");
+        public virtual Encoding Encoding => currentEncoding;
 
         // TODO: BBC Master hard disks are untested...
-        public override bool Identify(ImagePlugin imagePlugin, Partition partition)
+        public virtual bool Identify(IMediaImage imagePlugin, Partition partition)
         {
             if(partition.Start >= partition.End) return false;
 
             ulong sbSector;
             uint sectorsToRead;
 
-            if(imagePlugin.ImageInfo.SectorSize < 256) return false;
+            if(imagePlugin.Info.SectorSize < 256) return false;
 
             byte[] sector;
             GCHandle ptr;
@@ -146,9 +132,9 @@ namespace DiscImageChef.Filesystems
                 if(oldMap0.checksum == oldChk0 && oldMap1.checksum == oldChk1 && oldMap0.checksum != 0 &&
                    oldMap1.checksum != 0)
                 {
-                    sbSector = OLD_DIRECTORY_LOCATION / imagePlugin.ImageInfo.SectorSize;
-                    sectorsToRead = OLD_DIRECTORY_SIZE / imagePlugin.ImageInfo.SectorSize;
-                    if(OLD_DIRECTORY_SIZE % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++;
+                    sbSector = OLD_DIRECTORY_LOCATION / imagePlugin.Info.SectorSize;
+                    sectorsToRead = OLD_DIRECTORY_SIZE / imagePlugin.Info.SectorSize;
+                    if(OLD_DIRECTORY_SIZE % imagePlugin.Info.SectorSize > 0) sectorsToRead++;
 
                     sector = imagePlugin.ReadSectors(sbSector, sectorsToRead);
                     if(sector.Length > OLD_DIRECTORY_SIZE)
@@ -174,9 +160,9 @@ namespace DiscImageChef.Filesystems
                        oldRoot.header.magic == NEW_DIR_MAGIC && oldRoot.tail.magic == NEW_DIR_MAGIC) return true;
 
                     // RISC OS says the old directory can't be in the new location, hard disks created by RISC OS 3.10 do that...
-                    sbSector = NEW_DIRECTORY_LOCATION / imagePlugin.ImageInfo.SectorSize;
-                    sectorsToRead = NEW_DIRECTORY_SIZE / imagePlugin.ImageInfo.SectorSize;
-                    if(NEW_DIRECTORY_SIZE % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++;
+                    sbSector = NEW_DIRECTORY_LOCATION / imagePlugin.Info.SectorSize;
+                    sectorsToRead = NEW_DIRECTORY_SIZE / imagePlugin.Info.SectorSize;
+                    if(NEW_DIRECTORY_SIZE % imagePlugin.Info.SectorSize > 0) sectorsToRead++;
 
                     sector = imagePlugin.ReadSectors(sbSector, sectorsToRead);
                     if(sector.Length > OLD_DIRECTORY_SIZE)
@@ -210,9 +196,9 @@ namespace DiscImageChef.Filesystems
             DicConsole.DebugWriteLine("ADFS Plugin", "newChk = {0}", newChk);
             DicConsole.DebugWriteLine("ADFS Plugin", "map.zoneChecksum = {0}", sector[0]);
 
-            sbSector = BOOT_BLOCK_LOCATION / imagePlugin.ImageInfo.SectorSize;
-            sectorsToRead = BOOT_BLOCK_SIZE / imagePlugin.ImageInfo.SectorSize;
-            if(BOOT_BLOCK_SIZE % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++;
+            sbSector = BOOT_BLOCK_LOCATION / imagePlugin.Info.SectorSize;
+            sectorsToRead = BOOT_BLOCK_SIZE / imagePlugin.Info.SectorSize;
+            if(BOOT_BLOCK_SIZE % imagePlugin.Info.SectorSize > 0) sectorsToRead++;
 
             if(sbSector + partition.Start + sectorsToRead >= partition.End) return false;
 
@@ -258,16 +244,17 @@ namespace DiscImageChef.Filesystems
             bytes *= 0x100000000;
             bytes += drSb.disc_size;
 
-            return bytes <= imagePlugin.ImageInfo.Sectors * imagePlugin.ImageInfo.SectorSize;
+            return bytes <= imagePlugin.Info.Sectors * imagePlugin.Info.SectorSize;
         }
 
         // TODO: Find root directory on volumes with DiscRecord
         // TODO: Support big directories (ADFS-G?)
         // TODO: Find the real freemap on volumes with DiscRecord, as DiscRecord's discid may be empty but this one isn't
-        public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information)
+        public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding)
         {
+            currentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
             StringBuilder sbInformation = new StringBuilder();
-            XmlFsType = new FileSystemType();
+            xmlFsType = new FileSystemType();
             information = "";
 
             ulong sbSector;
@@ -313,19 +300,19 @@ namespace DiscImageChef.Filesystems
                         namebytes[i * 2 + 1] = oldMap1.name[i];
                     }
 
-                    XmlFsType = new FileSystemType
+                    xmlFsType = new FileSystemType
                     {
                         Bootable = oldMap1.boot != 0, // Or not?
-                        Clusters = (long)(bytes / imagePlugin.ImageInfo.SectorSize),
-                        ClusterSize = (int)imagePlugin.ImageInfo.SectorSize,
+                        Clusters = (long)(bytes / imagePlugin.Info.SectorSize),
+                        ClusterSize = (int)imagePlugin.Info.SectorSize,
                         Type = "Acorn Advanced Disc Filing System"
                     };
 
                     if(ArrayHelpers.ArrayIsNullOrEmpty(namebytes))
                     {
-                        sbSector = OLD_DIRECTORY_LOCATION / imagePlugin.ImageInfo.SectorSize;
-                        sectorsToRead = OLD_DIRECTORY_SIZE / imagePlugin.ImageInfo.SectorSize;
-                        if(OLD_DIRECTORY_SIZE % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++;
+                        sbSector = OLD_DIRECTORY_LOCATION / imagePlugin.Info.SectorSize;
+                        sectorsToRead = OLD_DIRECTORY_SIZE / imagePlugin.Info.SectorSize;
+                        if(OLD_DIRECTORY_SIZE % imagePlugin.Info.SectorSize > 0) sectorsToRead++;
 
                         sector = imagePlugin.ReadSectors(sbSector, sectorsToRead);
                         if(sector.Length > OLD_DIRECTORY_SIZE)
@@ -344,9 +331,9 @@ namespace DiscImageChef.Filesystems
                         else
                         {
                             // RISC OS says the old directory can't be in the new location, hard disks created by RISC OS 3.10 do that...
-                            sbSector = NEW_DIRECTORY_LOCATION / imagePlugin.ImageInfo.SectorSize;
-                            sectorsToRead = NEW_DIRECTORY_SIZE / imagePlugin.ImageInfo.SectorSize;
-                            if(NEW_DIRECTORY_SIZE % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++;
+                            sbSector = NEW_DIRECTORY_LOCATION / imagePlugin.Info.SectorSize;
+                            sectorsToRead = NEW_DIRECTORY_SIZE / imagePlugin.Info.SectorSize;
+                            if(NEW_DIRECTORY_SIZE % imagePlugin.Info.SectorSize > 0) sectorsToRead++;
 
                             sector = imagePlugin.ReadSectors(sbSector, sectorsToRead);
                             if(sector.Length > OLD_DIRECTORY_SIZE)
@@ -384,17 +371,17 @@ namespace DiscImageChef.Filesystems
 
                     sbInformation.AppendLine("Acorn Advanced Disc Filing System");
                     sbInformation.AppendLine();
-                    sbInformation.AppendFormat("{0} bytes per sector", imagePlugin.ImageInfo.SectorSize).AppendLine();
+                    sbInformation.AppendFormat("{0} bytes per sector", imagePlugin.Info.SectorSize).AppendLine();
                     sbInformation.AppendFormat("Volume has {0} bytes", bytes).AppendLine();
-                    sbInformation.AppendFormat("Volume name: {0}", StringHandlers.CToString(namebytes, CurrentEncoding))
+                    sbInformation.AppendFormat("Volume name: {0}", StringHandlers.CToString(namebytes, currentEncoding))
                                  .AppendLine();
                     if(oldMap1.discId > 0)
                     {
-                        XmlFsType.VolumeSerial = $"{oldMap1.discId:X4}";
+                        xmlFsType.VolumeSerial = $"{oldMap1.discId:X4}";
                         sbInformation.AppendFormat("Volume ID: {0:X4}", oldMap1.discId).AppendLine();
                     }
                     if(!ArrayHelpers.ArrayIsNullOrEmpty(namebytes))
-                        XmlFsType.VolumeName = StringHandlers.CToString(namebytes, CurrentEncoding);
+                        xmlFsType.VolumeName = StringHandlers.CToString(namebytes, currentEncoding);
 
                     information = sbInformation.ToString();
 
@@ -410,9 +397,9 @@ namespace DiscImageChef.Filesystems
             DicConsole.DebugWriteLine("ADFS Plugin", "newChk = {0}", newChk);
             DicConsole.DebugWriteLine("ADFS Plugin", "map.zoneChecksum = {0}", sector[0]);
 
-            sbSector = BOOT_BLOCK_LOCATION / imagePlugin.ImageInfo.SectorSize;
-            sectorsToRead = BOOT_BLOCK_SIZE / imagePlugin.ImageInfo.SectorSize;
-            if(BOOT_BLOCK_SIZE % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++;
+            sbSector = BOOT_BLOCK_LOCATION / imagePlugin.Info.SectorSize;
+            sectorsToRead = BOOT_BLOCK_SIZE / imagePlugin.Info.SectorSize;
+            if(BOOT_BLOCK_SIZE % imagePlugin.Info.SectorSize > 0) sectorsToRead++;
 
             byte[] bootSector = imagePlugin.ReadSectors(sbSector + partition.Start, sectorsToRead);
             int bootChk = 0;
@@ -452,7 +439,7 @@ namespace DiscImageChef.Filesystems
             DicConsole.DebugWriteLine("ADFS Plugin", "drSb.disc_size = {0}", drSb.disc_size);
             DicConsole.DebugWriteLine("ADFS Plugin", "drSb.disc_id = {0}", drSb.disc_id);
             DicConsole.DebugWriteLine("ADFS Plugin", "drSb.disc_name = {0}",
-                                      StringHandlers.CToString(drSb.disc_name, CurrentEncoding));
+                                      StringHandlers.CToString(drSb.disc_name, currentEncoding));
             DicConsole.DebugWriteLine("ADFS Plugin", "drSb.disc_type = {0}", drSb.disc_type);
             DicConsole.DebugWriteLine("ADFS Plugin", "drSb.disc_size_high = {0}", drSb.disc_size_high);
             DicConsole.DebugWriteLine("ADFS Plugin", "drSb.flags = {0}", drSb.flags);
@@ -476,9 +463,9 @@ namespace DiscImageChef.Filesystems
             zones *= 0x100000000;
             zones += drSb.nzones;
 
-            if(bytes > imagePlugin.ImageInfo.Sectors * imagePlugin.ImageInfo.SectorSize) return;
+            if(bytes > imagePlugin.Info.Sectors * imagePlugin.Info.SectorSize) return;
 
-            XmlFsType = new FileSystemType();
+            xmlFsType = new FileSystemType();
 
             sbInformation.AppendLine("Acorn Advanced Disc Filing System");
             sbInformation.AppendLine();
@@ -496,80 +483,75 @@ namespace DiscImageChef.Filesystems
             sbInformation.AppendFormat("Volume flags: 0x{0:X4}", drSb.flags).AppendLine();
             if(drSb.disc_id > 0)
             {
-                XmlFsType.VolumeSerial = $"{drSb.disc_id:X4}";
+                xmlFsType.VolumeSerial = $"{drSb.disc_id:X4}";
                 sbInformation.AppendFormat("Volume ID: {0:X4}", drSb.disc_id).AppendLine();
             }
             if(!ArrayHelpers.ArrayIsNullOrEmpty(drSb.disc_name))
             {
-                string discname = StringHandlers.CToString(drSb.disc_name, CurrentEncoding);
-                XmlFsType.VolumeName = discname;
+                string discname = StringHandlers.CToString(drSb.disc_name, currentEncoding);
+                xmlFsType.VolumeName = discname;
                 sbInformation.AppendFormat("Volume name: {0}", discname).AppendLine();
             }
 
             information = sbInformation.ToString();
 
-            XmlFsType.Bootable |= drSb.bootoption != 0; // Or not?
-            XmlFsType.Clusters = (long)(bytes / (ulong)(1 << drSb.log2secsize));
-            XmlFsType.ClusterSize = 1 << drSb.log2secsize;
-            XmlFsType.Type = "Acorn Advanced Disc Filing System";
+            xmlFsType.Bootable |= drSb.bootoption != 0; // Or not?
+            xmlFsType.Clusters = (long)(bytes / (ulong)(1 << drSb.log2secsize));
+            xmlFsType.ClusterSize = 1 << drSb.log2secsize;
+            xmlFsType.Type = "Acorn Advanced Disc Filing System";
         }
 
-        public override Errno Mount()
+        public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Mount(bool debug)
+        public virtual Errno Unmount()
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Unmount()
+        public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
+        public virtual Errno GetAttributes(string path, ref FileAttributes attributes)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno GetAttributes(string path, ref FileAttributes attributes)
+        public virtual Errno ListXAttr(string path, ref List xattrs)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno ListXAttr(string path, ref List xattrs)
+        public virtual Errno GetXattr(string path, string xattr, ref byte[] buf)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno GetXattr(string path, string xattr, ref byte[] buf)
+        public virtual Errno Read(string path, long offset, long size, ref byte[] buf)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Read(string path, long offset, long size, ref byte[] buf)
+        public virtual Errno ReadDir(string path, ref List contents)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno ReadDir(string path, ref List contents)
+        public virtual Errno StatFs(ref FileSystemInfo stat)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno StatFs(ref FileSystemInfo stat)
+        public virtual Errno Stat(string path, ref FileEntryInfo stat)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Stat(string path, ref FileEntryInfo stat)
-        {
-            return Errno.NotImplemented;
-        }
-
-        public override Errno ReadLink(string path, ref string dest)
+        public virtual Errno ReadLink(string path, ref string dest)
         {
             return Errno.NotImplemented;
         }
diff --git a/DiscImageChef.Filesystems/AmigaDOS.cs b/DiscImageChef.Filesystems/AmigaDOS.cs
index 4a679012..1738ffe3 100644
--- a/DiscImageChef.Filesystems/AmigaDOS.cs
+++ b/DiscImageChef.Filesystems/AmigaDOS.cs
@@ -43,36 +43,22 @@ using Schemas;
 
 namespace DiscImageChef.Filesystems
 {
-    public class AmigaDOSPlugin : Filesystem
+    public class AmigaDOSPlugin : IFilesystem
     {
         const uint FFS_MASK = 0x444F5300;
         const uint MUFS_MASK = 0x6D754600;
 
         const uint TYPE_HEADER = 2;
         const uint SUBTYPE_ROOT = 1;
+        Encoding currentEncoding;
 
-        public AmigaDOSPlugin()
-        {
-            Name = "Amiga DOS filesystem";
-            PluginUuid = new Guid("3c882400-208c-427d-a086-9119852a1bc7");
-            CurrentEncoding = Encoding.GetEncoding("iso-8859-1");
-        }
+        FileSystemType xmlFsType;
+        public virtual FileSystemType XmlFsType => xmlFsType;
+        public virtual string Name => "Amiga DOS filesystem";
+        public virtual Guid Id => new Guid("3c882400-208c-427d-a086-9119852a1bc7");
+        public virtual Encoding Encoding => currentEncoding;
 
-        public AmigaDOSPlugin(Encoding encoding)
-        {
-            Name = "Amiga DOS filesystem";
-            PluginUuid = new Guid("3c882400-208c-427d-a086-9119852a1bc7");
-            CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
-        }
-
-        public AmigaDOSPlugin(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
-        {
-            Name = "Amiga DOS filesystem";
-            PluginUuid = new Guid("3c882400-208c-427d-a086-9119852a1bc7");
-            CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
-        }
-
-        public override bool Identify(ImagePlugin imagePlugin, Partition partition)
+        public virtual bool Identify(IMediaImage imagePlugin, Partition partition)
         {
             if(partition.Start >= partition.End) return false;
 
@@ -168,10 +154,11 @@ namespace DiscImageChef.Filesystems
             return false;
         }
 
-        public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information)
+        public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding)
         {
+            currentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
             StringBuilder sbInformation = new StringBuilder();
-            XmlFsType = new FileSystemType();
+            xmlFsType = new FileSystemType();
             information = null;
             BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;
 
@@ -255,41 +242,41 @@ namespace DiscImageChef.Filesystems
 
             rootBlk = MarshalRootBlock(rootBlockSector);
 
-            string diskName = StringHandlers.PascalToString(rootBlk.diskName, CurrentEncoding);
+            string diskName = StringHandlers.PascalToString(rootBlk.diskName, currentEncoding);
 
             switch(bootBlk.diskType & 0xFF)
             {
                 case 0:
                     sbInformation.Append("Amiga Original File System");
-                    XmlFsType.Type = "Amiga OFS";
+                    xmlFsType.Type = "Amiga OFS";
                     break;
                 case 1:
                     sbInformation.Append("Amiga Fast File System");
-                    XmlFsType.Type = "Amiga FFS";
+                    xmlFsType.Type = "Amiga FFS";
                     break;
                 case 2:
                     sbInformation.Append("Amiga Original File System with international characters");
-                    XmlFsType.Type = "Amiga OFS";
+                    xmlFsType.Type = "Amiga OFS";
                     break;
                 case 3:
                     sbInformation.Append("Amiga Fast File System with international characters");
-                    XmlFsType.Type = "Amiga FFS";
+                    xmlFsType.Type = "Amiga FFS";
                     break;
                 case 4:
                     sbInformation.Append("Amiga Original File System with directory cache");
-                    XmlFsType.Type = "Amiga OFS";
+                    xmlFsType.Type = "Amiga OFS";
                     break;
                 case 5:
                     sbInformation.Append("Amiga Fast File System with directory cache");
-                    XmlFsType.Type = "Amiga FFS";
+                    xmlFsType.Type = "Amiga FFS";
                     break;
                 case 6:
                     sbInformation.Append("Amiga Original File System with long filenames");
-                    XmlFsType.Type = "Amiga OFS2";
+                    xmlFsType.Type = "Amiga OFS2";
                     break;
                 case 7:
                     sbInformation.Append("Amiga Fast File System with long filenames");
-                    XmlFsType.Type = "Amiga FFS2";
+                    xmlFsType.Type = "Amiga FFS2";
                     break;
             }
 
@@ -316,7 +303,7 @@ namespace DiscImageChef.Filesystems
             if((bootBlk.diskType & 0xFF) == 4 || (bootBlk.diskType & 0xFF) == 5)
                 sbInformation.AppendFormat("Directory cache starts at block {0}", rootBlk.extension).AppendLine();
 
-            long blocks = (long)((partition.End - partition.Start + 1) * imagePlugin.ImageInfo.SectorSize / blockSize);
+            long blocks = (long)((partition.End - partition.Start + 1) * imagePlugin.Info.SectorSize / blockSize);
 
             sbInformation.AppendFormat("Volume block size is {0} bytes", blockSize).AppendLine();
             sbInformation.AppendFormat("Volume has {0} blocks", blocks).AppendLine();
@@ -332,17 +319,17 @@ namespace DiscImageChef.Filesystems
             sbInformation.AppendFormat("Root block checksum is 0x{0:X8}", rootBlk.checksum).AppendLine();
             information = sbInformation.ToString();
 
-            XmlFsType.CreationDate = DateHandlers.AmigaToDateTime(rootBlk.cDays, rootBlk.cMins, rootBlk.cTicks);
-            XmlFsType.CreationDateSpecified = true;
-            XmlFsType.ModificationDate = DateHandlers.AmigaToDateTime(rootBlk.vDays, rootBlk.vMins, rootBlk.vTicks);
-            XmlFsType.ModificationDateSpecified = true;
-            XmlFsType.Dirty = rootBlk.bitmapFlag != 0xFFFFFFFF;
-            XmlFsType.Clusters = blocks;
-            XmlFsType.ClusterSize = (int)blockSize;
-            XmlFsType.VolumeName = diskName;
-            XmlFsType.Bootable = bsum == bootBlk.checksum;
+            xmlFsType.CreationDate = DateHandlers.AmigaToDateTime(rootBlk.cDays, rootBlk.cMins, rootBlk.cTicks);
+            xmlFsType.CreationDateSpecified = true;
+            xmlFsType.ModificationDate = DateHandlers.AmigaToDateTime(rootBlk.vDays, rootBlk.vMins, rootBlk.vTicks);
+            xmlFsType.ModificationDateSpecified = true;
+            xmlFsType.Dirty = rootBlk.bitmapFlag != 0xFFFFFFFF;
+            xmlFsType.Clusters = blocks;
+            xmlFsType.ClusterSize = (int)blockSize;
+            xmlFsType.VolumeName = diskName;
+            xmlFsType.Bootable = bsum == bootBlk.checksum;
             // Useful as a serial
-            XmlFsType.VolumeSerial = $"{rootBlk.checksum:X8}";
+            xmlFsType.VolumeSerial = $"{rootBlk.checksum:X8}";
         }
 
         static RootBlock MarshalRootBlock(byte[] block)
@@ -384,62 +371,57 @@ namespace DiscImageChef.Filesystems
             return ~sum;
         }
 
-        public override Errno Mount()
+        public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Mount(bool debug)
+        public virtual Errno Unmount()
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Unmount()
+        public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
+        public virtual Errno GetAttributes(string path, ref FileAttributes attributes)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno GetAttributes(string path, ref FileAttributes attributes)
+        public virtual Errno ListXAttr(string path, ref List xattrs)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno ListXAttr(string path, ref List xattrs)
+        public virtual Errno GetXattr(string path, string xattr, ref byte[] buf)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno GetXattr(string path, string xattr, ref byte[] buf)
+        public virtual Errno Read(string path, long offset, long size, ref byte[] buf)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Read(string path, long offset, long size, ref byte[] buf)
+        public virtual Errno ReadDir(string path, ref List contents)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno ReadDir(string path, ref List contents)
+        public virtual Errno StatFs(ref FileSystemInfo stat)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno StatFs(ref FileSystemInfo stat)
+        public virtual Errno Stat(string path, ref FileEntryInfo stat)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Stat(string path, ref FileEntryInfo stat)
-        {
-            return Errno.NotImplemented;
-        }
-
-        public override Errno ReadLink(string path, ref string dest)
+        public virtual Errno ReadLink(string path, ref string dest)
         {
             return Errno.NotImplemented;
         }
diff --git a/DiscImageChef.Filesystems/AppleDOS/AppleDOS.cs b/DiscImageChef.Filesystems/AppleDOS/AppleDOS.cs
index 7952af17..ab52fc49 100644
--- a/DiscImageChef.Filesystems/AppleDOS/AppleDOS.cs
+++ b/DiscImageChef.Filesystems/AppleDOS/AppleDOS.cs
@@ -35,13 +35,15 @@ using System.Collections.Generic;
 using Claunia.Encoding;
 using DiscImageChef.CommonTypes;
 using DiscImageChef.DiscImages;
+using Schemas;
 using Encoding = System.Text.Encoding;
 
 namespace DiscImageChef.Filesystems.AppleDOS
 {
-    public partial class AppleDOS : Filesystem
+    public partial class AppleDOS : IFilesystem
     {
-        readonly ImagePlugin device;
+        IMediaImage device;
+        Encoding currentEncoding;
         bool debug;
         bool mounted;
         int sectorsPerTrack;
@@ -53,30 +55,11 @@ namespace DiscImageChef.Filesystems.AppleDOS
 
         Vtoc vtoc;
 
-        public AppleDOS()
-        {
-            Name = "Apple DOS File System";
-            PluginUuid = new Guid("8658A1E9-B2E7-4BCC-9638-157A31B0A700\n");
-            CurrentEncoding = new LisaRoman();
-        }
-
-        public AppleDOS(Encoding encoding)
-        {
-            Name = "Apple DOS File System";
-            PluginUuid = new Guid("8658A1E9-B2E7-4BCC-9638-157A31B0A700\n");
-            // TODO: Until Apple ][ encoding is implemented
-            CurrentEncoding = new LisaRoman();
-        }
-
-        public AppleDOS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
-        {
-            device = imagePlugin;
-            start = partition.Start;
-            Name = "Apple DOS File System";
-            PluginUuid = new Guid("8658A1E9-B2E7-4BCC-9638-157A31B0A700\n");
-            // TODO: Until Apple ][ encoding is implemented
-            CurrentEncoding = new LisaRoman();
-        }
+        FileSystemType xmlFsType;
+        public virtual FileSystemType XmlFsType => xmlFsType;
+        public virtual Encoding Encoding => currentEncoding;
+        public virtual string Name => "Apple DOS File System";
+        public virtual Guid Id => new Guid("8658A1E9-B2E7-4BCC-9638-157A31B0A700\n");
 
         #region Caches
         /// Caches track/sector lists
diff --git a/DiscImageChef.Filesystems/AppleDOS/Dir.cs b/DiscImageChef.Filesystems/AppleDOS/Dir.cs
index 3b48864b..6b521470 100644
--- a/DiscImageChef.Filesystems/AppleDOS/Dir.cs
+++ b/DiscImageChef.Filesystems/AppleDOS/Dir.cs
@@ -45,7 +45,7 @@ namespace DiscImageChef.Filesystems.AppleDOS
         /// 
         /// Link path.
         /// Link destination.
-        public override Errno ReadLink(string path, ref string dest)
+        public virtual Errno ReadLink(string path, ref string dest)
         {
             return !mounted ? Errno.AccessDenied : Errno.NotSupported;
         }
@@ -55,7 +55,7 @@ namespace DiscImageChef.Filesystems.AppleDOS
         /// 
         /// Directory path.
         /// Directory contents.
-        public override Errno ReadDir(string path, ref List contents)
+        public virtual Errno ReadDir(string path, ref List contents)
         {
             if(!mounted) return Errno.AccessDenied;
 
@@ -85,7 +85,7 @@ namespace DiscImageChef.Filesystems.AppleDOS
             fileSizeCache = new Dictionary();
             lockedFiles = new List();
 
-            if(lba == 0 || lba > device.ImageInfo.Sectors) return Errno.InvalidArgument;
+            if(lba == 0 || lba > device.Info.Sectors) return Errno.InvalidArgument;
 
             while(lba != 0)
             {
@@ -111,7 +111,7 @@ namespace DiscImageChef.Filesystems.AppleDOS
                     // Apple DOS has high byte set over ASCII.
                     for(int i = 0; i < 30; i++) filenameB[i] = (byte)(entry.filename[i] & 0x7F);
 
-                    string filename = StringHandlers.SpacePaddedToString(filenameB, CurrentEncoding);
+                    string filename = StringHandlers.SpacePaddedToString(filenameB, currentEncoding);
 
                     if(!catalogCache.ContainsKey(filename)) catalogCache.Add(filename, ts);
 
@@ -127,7 +127,7 @@ namespace DiscImageChef.Filesystems.AppleDOS
 
                 lba = (ulong)(catSector.trackOfNext * sectorsPerTrack + catSector.sectorOfNext);
 
-                if(lba > device.ImageInfo.Sectors) break;
+                if(lba > device.Info.Sectors) break;
             }
 
             if(debug) catalogBlocks = catalogMs.ToArray();
diff --git a/DiscImageChef.Filesystems/AppleDOS/File.cs b/DiscImageChef.Filesystems/AppleDOS/File.cs
index e96cf222..4fc3dcdb 100644
--- a/DiscImageChef.Filesystems/AppleDOS/File.cs
+++ b/DiscImageChef.Filesystems/AppleDOS/File.cs
@@ -40,7 +40,7 @@ namespace DiscImageChef.Filesystems.AppleDOS
 {
     public partial class AppleDOS
     {
-        public override Errno GetAttributes(string path, ref FileAttributes attributes)
+        public virtual Errno GetAttributes(string path, ref FileAttributes attributes)
         {
             if(!mounted) return Errno.AccessDenied;
 
@@ -64,7 +64,7 @@ namespace DiscImageChef.Filesystems.AppleDOS
             return Errno.NoError;
         }
 
-        public override Errno Read(string path, long offset, long size, ref byte[] buf)
+        public virtual Errno Read(string path, long offset, long size, ref byte[] buf)
         {
             if(!mounted) return Errno.AccessDenied;
 
@@ -103,7 +103,7 @@ namespace DiscImageChef.Filesystems.AppleDOS
             return Errno.NoError;
         }
 
-        public override Errno Stat(string path, ref FileEntryInfo stat)
+        public virtual Errno Stat(string path, ref FileEntryInfo stat)
         {
             if(!mounted) return Errno.AccessDenied;
 
@@ -148,7 +148,7 @@ namespace DiscImageChef.Filesystems.AppleDOS
             return Errno.NoError;
         }
 
-        public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
+        public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
         {
             // TODO: Not really important.
             return !mounted ? Errno.AccessDenied : Errno.NotImplemented;
diff --git a/DiscImageChef.Filesystems/AppleDOS/Info.cs b/DiscImageChef.Filesystems/AppleDOS/Info.cs
index 6a370777..52961810 100644
--- a/DiscImageChef.Filesystems/AppleDOS/Info.cs
+++ b/DiscImageChef.Filesystems/AppleDOS/Info.cs
@@ -33,22 +33,24 @@
 using System;
 using System.Runtime.InteropServices;
 using System.Text;
+using Claunia.Encoding;
 using DiscImageChef.CommonTypes;
 using DiscImageChef.DiscImages;
 using Schemas;
+using Encoding = System.Text.Encoding;
 
 namespace DiscImageChef.Filesystems.AppleDOS
 {
     public partial class AppleDOS
     {
-        public override bool Identify(ImagePlugin imagePlugin, Partition partition)
+        public virtual bool Identify(IMediaImage imagePlugin, Partition partition)
         {
-            if(imagePlugin.ImageInfo.Sectors != 455 && imagePlugin.ImageInfo.Sectors != 560) return false;
+            if(imagePlugin.Info.Sectors != 455 && imagePlugin.Info.Sectors != 560) return false;
 
-            if(partition.Start > 0 || imagePlugin.ImageInfo.SectorSize != 256) return false;
+            if(partition.Start > 0 || imagePlugin.Info.SectorSize != 256) return false;
 
             int spt;
-            spt = imagePlugin.ImageInfo.Sectors == 455 ? 13 : 16;
+            spt = imagePlugin.Info.Sectors == 455 ? 13 : 16;
 
             byte[] vtocB = imagePlugin.ReadSector((ulong)(17 * spt));
             vtoc = new Vtoc();
@@ -61,13 +63,15 @@ namespace DiscImageChef.Filesystems.AppleDOS
                    vtoc.sectorsPerTrack == spt && vtoc.bytesPerSector == 256;
         }
 
-        public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information)
+        public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding)
         {
+            // TODO: Until Apple ][ encoding is implemented
+            currentEncoding = new LisaRoman();
             information = "";
             StringBuilder sb = new StringBuilder();
 
             int spt;
-            spt = imagePlugin.ImageInfo.Sectors == 455 ? 13 : 16;
+            spt = imagePlugin.Info.Sectors == 455 ? 13 : 16;
 
             byte[] vtocB = imagePlugin.ReadSector((ulong)(17 * spt));
             vtoc = new Vtoc();
@@ -91,11 +95,11 @@ namespace DiscImageChef.Filesystems.AppleDOS
 
             information = sb.ToString();
 
-            XmlFsType = new FileSystemType
+            xmlFsType = new FileSystemType
             {
                 Bootable = true,
-                Clusters = (long)imagePlugin.ImageInfo.Sectors,
-                ClusterSize = (int)imagePlugin.ImageInfo.SectorSize,
+                Clusters = (long)imagePlugin.Info.Sectors,
+                ClusterSize = (int)imagePlugin.Info.SectorSize,
                 Type = "Apple DOS"
             };
         }
diff --git a/DiscImageChef.Filesystems/AppleDOS/Super.cs b/DiscImageChef.Filesystems/AppleDOS/Super.cs
index bf92cf29..a8033413 100644
--- a/DiscImageChef.Filesystems/AppleDOS/Super.cs
+++ b/DiscImageChef.Filesystems/AppleDOS/Super.cs
@@ -32,8 +32,12 @@
 
 using System;
 using System.Runtime.InteropServices;
+using Claunia.Encoding;
+using DiscImageChef.CommonTypes;
 using DiscImageChef.Console;
+using DiscImageChef.DiscImages;
 using Schemas;
+using Encoding = System.Text.Encoding;
 
 namespace DiscImageChef.Filesystems.AppleDOS
 {
@@ -42,17 +46,14 @@ namespace DiscImageChef.Filesystems.AppleDOS
         /// 
         ///     Mounts an Apple DOS filesystem
         /// 
-        public override Errno Mount()
+        public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug)
         {
-            return Mount(false);
-        }
-
-        /// 
-        ///     Mounts an Apple DOS filesystem
-        /// 
-        public override Errno Mount(bool debug)
-        {
-            if(device.ImageInfo.Sectors != 455 && device.ImageInfo.Sectors != 560)
+            device = imagePlugin;
+            start = partition.Start;
+            // TODO: Until Apple ][ encoding is implemented
+            currentEncoding = new LisaRoman();
+            
+            if(device.Info.Sectors != 455 && device.Info.Sectors != 560)
             {
                 DicConsole.DebugWriteLine("Apple DOS plugin", "Incorrect device size.");
                 return Errno.InOutError;
@@ -64,13 +65,13 @@ namespace DiscImageChef.Filesystems.AppleDOS
                 return Errno.InOutError;
             }
 
-            if(device.ImageInfo.SectorSize != 256)
+            if(device.Info.SectorSize != 256)
             {
                 DicConsole.DebugWriteLine("Apple DOS plugin", "Incorrect sector size.");
                 return Errno.InOutError;
             }
 
-            sectorsPerTrack = device.ImageInfo.Sectors == 455 ? 13 : 16;
+            sectorsPerTrack = device.Info.Sectors == 455 ? 13 : 16;
 
             // Read the VTOC
             vtocBlocks = device.ReadSector((ulong)(17 * sectorsPerTrack));
@@ -99,17 +100,17 @@ namespace DiscImageChef.Filesystems.AppleDOS
             }
 
             // Create XML metadata for mounted filesystem
-            XmlFsType = new FileSystemType
+            xmlFsType = new FileSystemType
             {
                 Bootable = true,
-                Clusters = (long)device.ImageInfo.Sectors,
+                Clusters = (long)device.Info.Sectors,
                 ClusterSize = vtoc.bytesPerSector,
                 Files = catalogCache.Count,
                 FilesSpecified = true,
                 FreeClustersSpecified = true,
                 Type = "Apple DOS"
             };
-            XmlFsType.FreeClusters = XmlFsType.Clusters - usedSectors;
+            xmlFsType.FreeClusters = xmlFsType.Clusters - usedSectors;
 
             this.debug = debug;
             mounted = true;
@@ -119,7 +120,7 @@ namespace DiscImageChef.Filesystems.AppleDOS
         /// 
         ///     Umounts this DOS filesystem
         /// 
-        public override Errno Unmount()
+        public virtual Errno Unmount()
         {
             mounted = false;
             extentCache = null;
@@ -134,14 +135,14 @@ namespace DiscImageChef.Filesystems.AppleDOS
         ///     Gets information about the mounted volume.
         /// 
         /// Information about the mounted volume.
-        public override Errno StatFs(ref FileSystemInfo stat)
+        public virtual Errno StatFs(ref FileSystemInfo stat)
         {
             stat = new FileSystemInfo
             {
-                Blocks = (long)device.ImageInfo.Sectors,
+                Blocks = (long)device.Info.Sectors,
                 FilenameLength = 30,
                 Files = (ulong)catalogCache.Count,
-                PluginId = PluginUuid,
+                PluginId = Id,
                 Type = "Apple DOS"
             };
             stat.FreeFiles = totalFileEntries - stat.Files;
diff --git a/DiscImageChef.Filesystems/AppleDOS/Xattr.cs b/DiscImageChef.Filesystems/AppleDOS/Xattr.cs
index c5bcec36..7fb43e9d 100644
--- a/DiscImageChef.Filesystems/AppleDOS/Xattr.cs
+++ b/DiscImageChef.Filesystems/AppleDOS/Xattr.cs
@@ -43,7 +43,7 @@ namespace DiscImageChef.Filesystems.AppleDOS
         /// Error number.
         /// Path.
         /// List of extended attributes, alternate data streams and forks.
-        public override Errno ListXAttr(string path, ref List xattrs)
+        public virtual Errno ListXAttr(string path, ref List xattrs)
         {
             if(!mounted) return Errno.AccessDenied;
 
@@ -77,7 +77,7 @@ namespace DiscImageChef.Filesystems.AppleDOS
         /// File path.
         /// Extended attribute, alternate data stream or fork name.
         /// Buffer.
-        public override Errno GetXattr(string path, string xattr, ref byte[] buf)
+        public virtual Errno GetXattr(string path, string xattr, ref byte[] buf)
         {
             if(!mounted) return Errno.AccessDenied;
 
diff --git a/DiscImageChef.Filesystems/AppleHFS.cs b/DiscImageChef.Filesystems/AppleHFS.cs
index d7dcdcdc..520d6bf1 100644
--- a/DiscImageChef.Filesystems/AppleHFS.cs
+++ b/DiscImageChef.Filesystems/AppleHFS.cs
@@ -42,7 +42,7 @@ namespace DiscImageChef.Filesystems
 {
     // Information from Inside Macintosh
     // https://developer.apple.com/legacy/library/documentation/mac/pdf/Files/File_Manager.pdf
-    public class AppleHFS : Filesystem
+    public class AppleHFS : IFilesystem
     {
         /// 
         ///     "BD", HFS magic
@@ -56,37 +56,23 @@ namespace DiscImageChef.Filesystems
         ///     "LK", HFS bootblock magic
         /// 
         const ushort HFSBB_MAGIC = 0x4C4B;
+        Encoding currentEncoding;
+        FileSystemType xmlFsType;
+        public virtual FileSystemType XmlFsType => xmlFsType;
 
-        public AppleHFS()
-        {
-            Name = "Apple Hierarchical File System";
-            PluginUuid = new Guid("36405F8D-0D26-6ECC-0BBB-1D5225FF404F");
-            CurrentEncoding = Encoding.GetEncoding("macintosh");
-        }
+        public virtual Encoding Encoding => currentEncoding;
+        public virtual string Name => "Apple Hierarchical File System";
+        public virtual Guid Id => new Guid("36405F8D-0D26-6ECC-0BBB-1D5225FF404F");
 
-        public AppleHFS(Encoding encoding)
-        {
-            Name = "Apple Hierarchical File System";
-            PluginUuid = new Guid("36405F8D-0D26-6ECC-0BBB-1D5225FF404F");
-            CurrentEncoding = encoding ?? Encoding.GetEncoding("macintosh");
-        }
-
-        public AppleHFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
-        {
-            Name = "Apple Hierarchical File System";
-            PluginUuid = new Guid("36405F8D-0D26-6ECC-0BBB-1D5225FF404F");
-            CurrentEncoding = encoding ?? Encoding.GetEncoding("macintosh");
-        }
-
-        public override bool Identify(ImagePlugin imagePlugin, Partition partition)
+        public virtual bool Identify(IMediaImage imagePlugin, Partition partition)
         {
             if(2 + partition.Start >= partition.End) return false;
 
             byte[] mdbSector;
             ushort drSigWord;
 
-            if(imagePlugin.ImageInfo.SectorSize == 2352 || imagePlugin.ImageInfo.SectorSize == 2448 ||
-               imagePlugin.ImageInfo.SectorSize == 2048)
+            if(imagePlugin.Info.SectorSize == 2352 || imagePlugin.Info.SectorSize == 2448 ||
+               imagePlugin.Info.SectorSize == 2048)
             {
                 mdbSector = imagePlugin.ReadSectors(partition.Start, 2);
 
@@ -116,8 +102,10 @@ namespace DiscImageChef.Filesystems
             return false;
         }
 
-        public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information)
+        public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
+                                            Encoding encoding)
         {
+            currentEncoding = encoding ?? Encoding.GetEncoding("macintosh");
             information = "";
 
             StringBuilder sb = new StringBuilder();
@@ -128,8 +116,8 @@ namespace DiscImageChef.Filesystems
 
             bool APMFromHDDOnCD = false;
 
-            if(imagePlugin.ImageInfo.SectorSize == 2352 || imagePlugin.ImageInfo.SectorSize == 2448 ||
-               imagePlugin.ImageInfo.SectorSize == 2048)
+            if(imagePlugin.Info.SectorSize == 2352 || imagePlugin.Info.SectorSize == 2448 ||
+               imagePlugin.Info.SectorSize == 2048)
             {
                 byte[] tmpSector = imagePlugin.ReadSectors(partition.Start, 2);
 
@@ -205,7 +193,7 @@ namespace DiscImageChef.Filesystems
             sb.AppendFormat("{0} bytes in the Extents B-Tree", MDB.drXTFlSize).AppendLine();
             sb.AppendFormat("{0} bytes in the Catalog B-Tree", MDB.drCTFlSize).AppendLine();
 
-            sb.AppendFormat("Volume name: {0}", StringHandlers.PascalToString(MDB.drVN, CurrentEncoding)).AppendLine();
+            sb.AppendFormat("Volume name: {0}", StringHandlers.PascalToString(MDB.drVN, currentEncoding)).AppendLine();
 
             sb.AppendLine("Finder info:");
             sb.AppendFormat("CNID of bootable system's directory: {0}", MDB.drFndrInfo0).AppendLine();
@@ -242,19 +230,19 @@ namespace DiscImageChef.Filesystems
                     else if(BB.boot_flags < 0) sb.AppendLine("Allocate secondary sound and video buffers at boot.");
 
                     sb.AppendFormat("System filename: {0}",
-                                    StringHandlers.PascalToString(BB.system_name, CurrentEncoding)).AppendLine();
+                                    StringHandlers.PascalToString(BB.system_name, currentEncoding)).AppendLine();
                     sb.AppendFormat("Finder filename: {0}",
-                                    StringHandlers.PascalToString(BB.finder_name, CurrentEncoding)).AppendLine();
+                                    StringHandlers.PascalToString(BB.finder_name, currentEncoding)).AppendLine();
                     sb.AppendFormat("Debugger filename: {0}",
-                                    StringHandlers.PascalToString(BB.debug_name, CurrentEncoding)).AppendLine();
+                                    StringHandlers.PascalToString(BB.debug_name, currentEncoding)).AppendLine();
                     sb.AppendFormat("Disassembler filename: {0}",
-                                    StringHandlers.PascalToString(BB.disasm_name, CurrentEncoding)).AppendLine();
+                                    StringHandlers.PascalToString(BB.disasm_name, currentEncoding)).AppendLine();
                     sb.AppendFormat("Startup screen filename: {0}",
-                                    StringHandlers.PascalToString(BB.stupscr_name, CurrentEncoding)).AppendLine();
+                                    StringHandlers.PascalToString(BB.stupscr_name, currentEncoding)).AppendLine();
                     sb.AppendFormat("First program to execute at boot: {0}",
-                                    StringHandlers.PascalToString(BB.bootup_name, CurrentEncoding)).AppendLine();
+                                    StringHandlers.PascalToString(BB.bootup_name, currentEncoding)).AppendLine();
                     sb.AppendFormat("Clipboard filename: {0}",
-                                    StringHandlers.PascalToString(BB.clipbrd_name, CurrentEncoding)).AppendLine();
+                                    StringHandlers.PascalToString(BB.clipbrd_name, currentEncoding)).AppendLine();
                     sb.AppendFormat("Maximum opened files: {0}", BB.max_files * 4).AppendLine();
                     sb.AppendFormat("Event queue size: {0}", BB.queue_size).AppendLine();
                     sb.AppendFormat("Heap size with 128KiB of RAM: {0} bytes", BB.heap_128k).AppendLine();
@@ -268,38 +256,38 @@ namespace DiscImageChef.Filesystems
 
             information = sb.ToString();
 
-            XmlFsType = new FileSystemType();
+            xmlFsType = new FileSystemType();
             if(MDB.drVolBkUp > 0)
             {
-                XmlFsType.BackupDate = DateHandlers.MacToDateTime(MDB.drVolBkUp);
-                XmlFsType.BackupDateSpecified = true;
+                xmlFsType.BackupDate = DateHandlers.MacToDateTime(MDB.drVolBkUp);
+                xmlFsType.BackupDateSpecified = true;
             }
-            XmlFsType.Bootable = BB.signature == HFSBB_MAGIC || MDB.drFndrInfo0 != 0 || MDB.drFndrInfo3 != 0 ||
+            xmlFsType.Bootable = BB.signature == HFSBB_MAGIC || MDB.drFndrInfo0 != 0 || MDB.drFndrInfo3 != 0 ||
                                  MDB.drFndrInfo5 != 0;
-            XmlFsType.Clusters = MDB.drNmAlBlks;
-            XmlFsType.ClusterSize = (int)MDB.drAlBlkSiz;
+            xmlFsType.Clusters = MDB.drNmAlBlks;
+            xmlFsType.ClusterSize = (int)MDB.drAlBlkSiz;
             if(MDB.drCrDate > 0)
             {
-                XmlFsType.CreationDate = DateHandlers.MacToDateTime(MDB.drCrDate);
-                XmlFsType.CreationDateSpecified = true;
+                xmlFsType.CreationDate = DateHandlers.MacToDateTime(MDB.drCrDate);
+                xmlFsType.CreationDateSpecified = true;
             }
-            XmlFsType.Dirty = (MDB.drAtrb & 0x100) != 0x100;
-            XmlFsType.Files = MDB.drFilCnt;
-            XmlFsType.FilesSpecified = true;
-            XmlFsType.FreeClusters = MDB.drFreeBks;
-            XmlFsType.FreeClustersSpecified = true;
+            xmlFsType.Dirty = (MDB.drAtrb & 0x100) != 0x100;
+            xmlFsType.Files = MDB.drFilCnt;
+            xmlFsType.FilesSpecified = true;
+            xmlFsType.FreeClusters = MDB.drFreeBks;
+            xmlFsType.FreeClustersSpecified = true;
             if(MDB.drLsMod > 0)
             {
-                XmlFsType.ModificationDate = DateHandlers.MacToDateTime(MDB.drLsMod);
-                XmlFsType.ModificationDateSpecified = true;
+                xmlFsType.ModificationDate = DateHandlers.MacToDateTime(MDB.drLsMod);
+                xmlFsType.ModificationDateSpecified = true;
             }
-            XmlFsType.Type = "HFS";
-            XmlFsType.VolumeName = StringHandlers.PascalToString(MDB.drVN, CurrentEncoding);
+            xmlFsType.Type = "HFS";
+            xmlFsType.VolumeName = StringHandlers.PascalToString(MDB.drVN, currentEncoding);
             if(MDB.drFndrInfo6 != 0 && MDB.drFndrInfo7 != 0)
-                XmlFsType.VolumeSerial = $"{MDB.drFndrInfo6:X8}{MDB.drFndrInfo7:X8}";
+                xmlFsType.VolumeSerial = $"{MDB.drFndrInfo6:X8}{MDB.drFndrInfo7:X8}";
         }
 
-        static byte[] Read2048SectorAs512(ImagePlugin imagePlugin, ulong lba)
+        static byte[] Read2048SectorAs512(IMediaImage imagePlugin, ulong lba)
         {
             ulong lba2K = lba / 4;
             int remainder = (int)(lba % 4);
@@ -312,62 +300,57 @@ namespace DiscImageChef.Filesystems
             return sector;
         }
 
-        public override Errno Mount()
+        public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Mount(bool debug)
+        public virtual Errno Unmount()
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Unmount()
+        public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
+        public virtual Errno GetAttributes(string path, ref FileAttributes attributes)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno GetAttributes(string path, ref FileAttributes attributes)
+        public virtual Errno ListXAttr(string path, ref List xattrs)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno ListXAttr(string path, ref List xattrs)
+        public virtual Errno GetXattr(string path, string xattr, ref byte[] buf)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno GetXattr(string path, string xattr, ref byte[] buf)
+        public virtual Errno Read(string path, long offset, long size, ref byte[] buf)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Read(string path, long offset, long size, ref byte[] buf)
+        public virtual Errno ReadDir(string path, ref List contents)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno ReadDir(string path, ref List contents)
+        public virtual Errno StatFs(ref FileSystemInfo stat)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno StatFs(ref FileSystemInfo stat)
+        public virtual Errno Stat(string path, ref FileEntryInfo stat)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Stat(string path, ref FileEntryInfo stat)
-        {
-            return Errno.NotImplemented;
-        }
-
-        public override Errno ReadLink(string path, ref string dest)
+        public virtual Errno ReadLink(string path, ref string dest)
         {
             return Errno.NotImplemented;
         }
diff --git a/DiscImageChef.Filesystems/AppleHFSPlus.cs b/DiscImageChef.Filesystems/AppleHFSPlus.cs
index 27b0270f..36725d8d 100644
--- a/DiscImageChef.Filesystems/AppleHFSPlus.cs
+++ b/DiscImageChef.Filesystems/AppleHFSPlus.cs
@@ -41,7 +41,7 @@ using Schemas;
 namespace DiscImageChef.Filesystems
 {
     // Information from Apple TechNote 1150: https://developer.apple.com/legacy/library/technotes/tn/tn1150.html
-    public class AppleHFSPlus : Filesystem
+    public class AppleHFSPlus : IFilesystem
     {
         /// 
         ///     "BD", HFS magic
@@ -56,37 +56,25 @@ namespace DiscImageChef.Filesystems
         /// 
         const ushort HFSX_MAGIC = 0x4858;
 
-        public AppleHFSPlus()
-        {
-            Name = "Apple HFS+ filesystem";
-            PluginUuid = new Guid("36405F8D-0D26-6EBE-436F-62F0586B4F08");
-            CurrentEncoding = Encoding.BigEndianUnicode;
-        }
+        Encoding currentEncoding;
+        FileSystemType xmlFsType;
+        public virtual FileSystemType XmlFsType => xmlFsType;
 
-        public AppleHFSPlus(Encoding encoding)
-        {
-            Name = "Apple HFS+ filesystem";
-            PluginUuid = new Guid("36405F8D-0D26-6EBE-436F-62F0586B4F08");
-            CurrentEncoding = Encoding.BigEndianUnicode;
-        }
+        public virtual Encoding Encoding => currentEncoding;
+        public virtual string Name => "Apple HFS+ filesystem";
+        public virtual Guid Id => new Guid("36405F8D-0D26-6EBE-436F-62F0586B4F08");
 
-        public AppleHFSPlus(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
-        {
-            Name = "Apple HFS+ filesystem";
-            PluginUuid = new Guid("36405F8D-0D26-6EBE-436F-62F0586B4F08");
-            CurrentEncoding = Encoding.BigEndianUnicode;
-        }
-
-        public override bool Identify(ImagePlugin imagePlugin, Partition partition)
+        public virtual bool Identify(IMediaImage imagePlugin, Partition partition)
         {
+            currentEncoding = Encoding.BigEndianUnicode;
             if(2 + partition.Start >= partition.End) return false;
 
             ushort drSigWord;
 
             ulong hfspOffset;
 
-            uint sectorsToRead = 0x800 / imagePlugin.ImageInfo.SectorSize;
-            if(0x800 % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++;
+            uint sectorsToRead = 0x800 / imagePlugin.Info.SectorSize;
+            if(0x800 % imagePlugin.Info.SectorSize > 0) sectorsToRead++;
 
             byte[] vhSector = imagePlugin.ReadSectors(partition.Start, sectorsToRead);
 
@@ -104,7 +92,7 @@ namespace DiscImageChef.Filesystems
 
                     ushort drAlBlSt = BigEndianBitConverter.ToUInt16(vhSector, 0x41C);
 
-                    hfspOffset = (ulong)((drAlBlSt * 512 + xdrStABNt * drAlBlkSiz) / imagePlugin.ImageInfo.SectorSize);
+                    hfspOffset = (ulong)((drAlBlSt * 512 + xdrStABNt * drAlBlkSiz) / imagePlugin.Info.SectorSize);
                 }
                 else hfspOffset = 0;
             }
@@ -116,7 +104,8 @@ namespace DiscImageChef.Filesystems
             return drSigWord == HFSP_MAGIC || drSigWord == HFSX_MAGIC;
         }
 
-        public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information)
+        public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
+                                            Encoding encoding)
         {
             information = "";
 
@@ -126,8 +115,8 @@ namespace DiscImageChef.Filesystems
             ulong hfspOffset;
             bool wrapped;
 
-            uint sectorsToRead = 0x800 / imagePlugin.ImageInfo.SectorSize;
-            if(0x800 % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++;
+            uint sectorsToRead = 0x800 / imagePlugin.Info.SectorSize;
+            if(0x800 % imagePlugin.Info.SectorSize > 0) sectorsToRead++;
 
             byte[] vhSector = imagePlugin.ReadSectors(partition.Start, sectorsToRead);
 
@@ -145,7 +134,7 @@ namespace DiscImageChef.Filesystems
 
                     ushort drAlBlSt = BigEndianBitConverter.ToUInt16(vhSector, 0x41C);
 
-                    hfspOffset = (ulong)((drAlBlSt * 512 + xdrStABNt * drAlBlkSiz) / imagePlugin.ImageInfo.SectorSize);
+                    hfspOffset = (ulong)((drAlBlSt * 512 + xdrStABNt * drAlBlkSiz) / imagePlugin.Info.SectorSize);
                     wrapped = true;
                 }
                 else
@@ -230,35 +219,35 @@ namespace DiscImageChef.Filesystems
                         sb.AppendFormat("Mac OS X Volume ID: {0:X8}{1:X8}", HPVH.drFndrInfo6, HPVH.drFndrInfo7)
                           .AppendLine();
 
-                    XmlFsType = new FileSystemType();
+                    xmlFsType = new FileSystemType();
                     if(HPVH.backupDate > 0)
                     {
-                        XmlFsType.BackupDate = DateHandlers.MacToDateTime(HPVH.backupDate);
-                        XmlFsType.BackupDateSpecified = true;
+                        xmlFsType.BackupDate = DateHandlers.MacToDateTime(HPVH.backupDate);
+                        xmlFsType.BackupDateSpecified = true;
                     }
-                    XmlFsType.Bootable |= HPVH.drFndrInfo0 != 0 || HPVH.drFndrInfo3 != 0 || HPVH.drFndrInfo5 != 0;
-                    XmlFsType.Clusters = HPVH.totalBlocks;
-                    XmlFsType.ClusterSize = (int)HPVH.blockSize;
+                    xmlFsType.Bootable |= HPVH.drFndrInfo0 != 0 || HPVH.drFndrInfo3 != 0 || HPVH.drFndrInfo5 != 0;
+                    xmlFsType.Clusters = HPVH.totalBlocks;
+                    xmlFsType.ClusterSize = (int)HPVH.blockSize;
                     if(HPVH.createDate > 0)
                     {
-                        XmlFsType.CreationDate = DateHandlers.MacToDateTime(HPVH.createDate);
-                        XmlFsType.CreationDateSpecified = true;
+                        xmlFsType.CreationDate = DateHandlers.MacToDateTime(HPVH.createDate);
+                        xmlFsType.CreationDateSpecified = true;
                     }
-                    XmlFsType.Dirty = (HPVH.attributes & 0x100) != 0x100;
-                    XmlFsType.Files = HPVH.fileCount;
-                    XmlFsType.FilesSpecified = true;
-                    XmlFsType.FreeClusters = HPVH.freeBlocks;
-                    XmlFsType.FreeClustersSpecified = true;
+                    xmlFsType.Dirty = (HPVH.attributes & 0x100) != 0x100;
+                    xmlFsType.Files = HPVH.fileCount;
+                    xmlFsType.FilesSpecified = true;
+                    xmlFsType.FreeClusters = HPVH.freeBlocks;
+                    xmlFsType.FreeClustersSpecified = true;
                     if(HPVH.modifyDate > 0)
                     {
-                        XmlFsType.ModificationDate = DateHandlers.MacToDateTime(HPVH.modifyDate);
-                        XmlFsType.ModificationDateSpecified = true;
+                        xmlFsType.ModificationDate = DateHandlers.MacToDateTime(HPVH.modifyDate);
+                        xmlFsType.ModificationDateSpecified = true;
                     }
-                    if(HPVH.signature == 0x482B) XmlFsType.Type = "HFS+";
-                    if(HPVH.signature == 0x4858) XmlFsType.Type = "HFSX";
+                    if(HPVH.signature == 0x482B) xmlFsType.Type = "HFS+";
+                    if(HPVH.signature == 0x4858) xmlFsType.Type = "HFSX";
                     if(HPVH.drFndrInfo6 != 0 && HPVH.drFndrInfo7 != 0)
-                        XmlFsType.VolumeSerial = $"{HPVH.drFndrInfo6:X8}{HPVH.drFndrInfo7:X8}";
-                    XmlFsType.SystemIdentifier = Encoding.ASCII.GetString(HPVH.lastMountedVersion);
+                        xmlFsType.VolumeSerial = $"{HPVH.drFndrInfo6:X8}{HPVH.drFndrInfo7:X8}";
+                    xmlFsType.SystemIdentifier = Encoding.ASCII.GetString(HPVH.lastMountedVersion);
                 }
                 else
                 {
@@ -271,62 +260,57 @@ namespace DiscImageChef.Filesystems
             else return;
         }
 
-        public override Errno Mount()
+        public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Mount(bool debug)
+        public virtual Errno Unmount()
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Unmount()
+        public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
+        public virtual Errno GetAttributes(string path, ref FileAttributes attributes)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno GetAttributes(string path, ref FileAttributes attributes)
+        public virtual Errno ListXAttr(string path, ref List xattrs)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno ListXAttr(string path, ref List xattrs)
+        public virtual Errno GetXattr(string path, string xattr, ref byte[] buf)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno GetXattr(string path, string xattr, ref byte[] buf)
+        public virtual Errno Read(string path, long offset, long size, ref byte[] buf)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Read(string path, long offset, long size, ref byte[] buf)
+        public virtual Errno ReadDir(string path, ref List contents)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno ReadDir(string path, ref List contents)
+        public virtual Errno StatFs(ref FileSystemInfo stat)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno StatFs(ref FileSystemInfo stat)
+        public virtual Errno Stat(string path, ref FileEntryInfo stat)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Stat(string path, ref FileEntryInfo stat)
-        {
-            return Errno.NotImplemented;
-        }
-
-        public override Errno ReadLink(string path, ref string dest)
+        public virtual Errno ReadLink(string path, ref string dest)
         {
             return Errno.NotImplemented;
         }
diff --git a/DiscImageChef.Filesystems/AppleMFS/AppleMFS.cs b/DiscImageChef.Filesystems/AppleMFS/AppleMFS.cs
index 2627f532..c0608150 100644
--- a/DiscImageChef.Filesystems/AppleMFS/AppleMFS.cs
+++ b/DiscImageChef.Filesystems/AppleMFS/AppleMFS.cs
@@ -35,15 +35,16 @@ using System.Collections.Generic;
 using System.Text;
 using DiscImageChef.CommonTypes;
 using DiscImageChef.DiscImages;
+using Schemas;
 
 namespace DiscImageChef.Filesystems.AppleMFS
 {
     // Information from Inside Macintosh Volume II
-    public partial class AppleMFS : Filesystem
+    public partial class AppleMFS : IFilesystem
     {
         bool mounted;
         bool debug;
-        ImagePlugin device;
+        IMediaImage device;
         ulong partitionStart;
 
         Dictionary idToFilename;
@@ -61,28 +62,29 @@ namespace DiscImageChef.Filesystems.AppleMFS
         byte[] mdbTags;
         byte[] directoryTags;
         byte[] bitmapTags;
+        Encoding currentEncoding;
+
+        FileSystemType xmlFsType;
+        public virtual FileSystemType XmlFsType => xmlFsType;
+        public virtual string Name => "Apple Macintosh File System";
+        public virtual Guid Id => new Guid("36405F8D-0D26-4066-6538-5DBF5D065C3A");
+        public virtual Encoding Encoding => currentEncoding;
 
         public AppleMFS()
         {
-            Name = "Apple Macintosh File System";
-            PluginUuid = new Guid("36405F8D-0D26-4066-6538-5DBF5D065C3A");
-            CurrentEncoding = Encoding.GetEncoding("macintosh");
+            currentEncoding = Encoding.GetEncoding("macintosh");
         }
 
         public AppleMFS(Encoding encoding)
         {
-            Name = "Apple Macintosh File System";
-            PluginUuid = new Guid("36405F8D-0D26-4066-6538-5DBF5D065C3A");
-            CurrentEncoding = encoding ?? Encoding.GetEncoding("macintosh");
+            currentEncoding = encoding ?? Encoding.GetEncoding("macintosh");
         }
 
-        public AppleMFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
+        public AppleMFS(IMediaImage imagePlugin, Partition partition, Encoding encoding)
         {
-            Name = "Apple Macintosh File System";
-            PluginUuid = new Guid("36405F8D-0D26-4066-6538-5DBF5D065C3A");
             device = imagePlugin;
             partitionStart = partition.Start;
-            CurrentEncoding = encoding ?? Encoding.GetEncoding("macintosh");
+            currentEncoding = encoding ?? Encoding.GetEncoding("macintosh");
         }
     }
 }
\ No newline at end of file
diff --git a/DiscImageChef.Filesystems/AppleMFS/Dir.cs b/DiscImageChef.Filesystems/AppleMFS/Dir.cs
index a79b6ec6..813624da 100644
--- a/DiscImageChef.Filesystems/AppleMFS/Dir.cs
+++ b/DiscImageChef.Filesystems/AppleMFS/Dir.cs
@@ -40,7 +40,7 @@ namespace DiscImageChef.Filesystems.AppleMFS
     // Information from Inside Macintosh Volume II
     public partial class AppleMFS
     {
-        public override Errno ReadDir(string path, ref List contents)
+        public virtual Errno ReadDir(string path, ref List contents)
         {
             if(!mounted) return Errno.AccessDenied;
 
@@ -92,7 +92,7 @@ namespace DiscImageChef.Filesystems.AppleMFS
                 entry.flNam = new byte[directoryBlocks[offset + 50] + 1];
                 Array.Copy(directoryBlocks, offset + 50, entry.flNam, 0, entry.flNam.Length);
                 string lowerFilename = StringHandlers
-                    .PascalToString(entry.flNam, CurrentEncoding).ToLowerInvariant().Replace('/', ':');
+                    .PascalToString(entry.flNam, currentEncoding).ToLowerInvariant().Replace('/', ':');
 
                 if(entry.flFlags.HasFlag(MFS_FileFlags.Used) && !idToFilename.ContainsKey(entry.flFlNum) &&
                    !idToEntry.ContainsKey(entry.flFlNum) && !filenameToId.ContainsKey(lowerFilename) &&
@@ -100,7 +100,7 @@ namespace DiscImageChef.Filesystems.AppleMFS
                 {
                     idToEntry.Add(entry.flFlNum, entry);
                     idToFilename.Add(entry.flFlNum,
-                                     StringHandlers.PascalToString(entry.flNam, CurrentEncoding).Replace('/', ':'));
+                                     StringHandlers.PascalToString(entry.flNam, currentEncoding).Replace('/', ':'));
                     filenameToId.Add(lowerFilename, entry.flFlNum);
 
                     DicConsole.DebugWriteLine("DEBUG (AppleMFS plugin)", "entry.flFlags = {0}", entry.flFlags);
@@ -117,7 +117,7 @@ namespace DiscImageChef.Filesystems.AppleMFS
                     DicConsole.DebugWriteLine("DEBUG (AppleMFS plugin)", "entry.flMdDat = {0}",
                                               DateHandlers.MacToDateTime(entry.flMdDat));
                     DicConsole.DebugWriteLine("DEBUG (AppleMFS plugin)", "entry.flNam0 = {0}",
-                                              StringHandlers.PascalToString(entry.flNam, CurrentEncoding));
+                                              StringHandlers.PascalToString(entry.flNam, currentEncoding));
                 }
 
                 offset += 50 + entry.flNam.Length;
diff --git a/DiscImageChef.Filesystems/AppleMFS/File.cs b/DiscImageChef.Filesystems/AppleMFS/File.cs
index 069c4e02..61180576 100644
--- a/DiscImageChef.Filesystems/AppleMFS/File.cs
+++ b/DiscImageChef.Filesystems/AppleMFS/File.cs
@@ -40,7 +40,7 @@ namespace DiscImageChef.Filesystems.AppleMFS
     // Information from Inside Macintosh Volume II
     public partial class AppleMFS
     {
-        public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
+        public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
         {
             deviceBlock = new long();
 
@@ -75,7 +75,7 @@ namespace DiscImageChef.Filesystems.AppleMFS
             return Errno.InOutError;
         }
 
-        public override Errno GetAttributes(string path, ref FileAttributes attributes)
+        public virtual Errno GetAttributes(string path, ref FileAttributes attributes)
         {
             if(!mounted) return Errno.AccessDenied;
 
@@ -108,7 +108,7 @@ namespace DiscImageChef.Filesystems.AppleMFS
             return Errno.NoError;
         }
 
-        public override Errno Read(string path, long offset, long size, ref byte[] buf)
+        public virtual Errno Read(string path, long offset, long size, ref byte[] buf)
         {
             if(!mounted) return Errno.AccessDenied;
 
@@ -142,7 +142,7 @@ namespace DiscImageChef.Filesystems.AppleMFS
             return Errno.NoError;
         }
 
-        public override Errno Stat(string path, ref FileEntryInfo stat)
+        public virtual Errno Stat(string path, ref FileEntryInfo stat)
         {
             if(!mounted) return Errno.AccessDenied;
 
@@ -157,7 +157,7 @@ namespace DiscImageChef.Filesystems.AppleMFS
                 {
                     stat = new FileEntryInfo
                     {
-                        BlockSize = device.ImageInfo.SectorSize,
+                        BlockSize = device.Info.SectorSize,
                         DeviceNo = 0,
                         GID = 0,
                         Inode = 0,
@@ -219,7 +219,7 @@ namespace DiscImageChef.Filesystems.AppleMFS
             return Errno.NoError;
         }
 
-        public override Errno ReadLink(string path, ref string dest)
+        public virtual Errno ReadLink(string path, ref string dest)
         {
             return Errno.NotImplemented;
         }
diff --git a/DiscImageChef.Filesystems/AppleMFS/Info.cs b/DiscImageChef.Filesystems/AppleMFS/Info.cs
index ac5e66b9..e06f33cc 100644
--- a/DiscImageChef.Filesystems/AppleMFS/Info.cs
+++ b/DiscImageChef.Filesystems/AppleMFS/Info.cs
@@ -41,7 +41,7 @@ namespace DiscImageChef.Filesystems.AppleMFS
     // Information from Inside Macintosh Volume II
     public partial class AppleMFS
     {
-        public override bool Identify(ImagePlugin imagePlugin, Partition partition)
+        public virtual bool Identify(IMediaImage imagePlugin, Partition partition)
         {
             ushort drSigWord;
 
@@ -56,7 +56,7 @@ namespace DiscImageChef.Filesystems.AppleMFS
             return drSigWord == MFS_MAGIC;
         }
 
-        public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information)
+        public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding)
         {
             information = "";
 
@@ -90,7 +90,7 @@ namespace DiscImageChef.Filesystems.AppleMFS
             MDB.drVNSiz = mdbSector[0x024];
             byte[] variableSize = new byte[MDB.drVNSiz + 1];
             Array.Copy(mdbSector, 0x024, variableSize, 0, MDB.drVNSiz + 1);
-            MDB.drVN = StringHandlers.PascalToString(variableSize, CurrentEncoding);
+            MDB.drVN = StringHandlers.PascalToString(variableSize, currentEncoding);
 
             BB.signature = BigEndianBitConverter.ToUInt16(bbSector, 0x000);
 
@@ -103,19 +103,19 @@ namespace DiscImageChef.Filesystems.AppleMFS
                 BB.sec_sv_pages = BigEndianBitConverter.ToInt16(bbSector, 0x008);
 
                 Array.Copy(mdbSector, 0x00A, pString, 0, 16);
-                BB.system_name = StringHandlers.PascalToString(pString, CurrentEncoding);
+                BB.system_name = StringHandlers.PascalToString(pString, currentEncoding);
                 Array.Copy(mdbSector, 0x01A, pString, 0, 16);
-                BB.finder_name = StringHandlers.PascalToString(pString, CurrentEncoding);
+                BB.finder_name = StringHandlers.PascalToString(pString, currentEncoding);
                 Array.Copy(mdbSector, 0x02A, pString, 0, 16);
-                BB.debug_name = StringHandlers.PascalToString(pString, CurrentEncoding);
+                BB.debug_name = StringHandlers.PascalToString(pString, currentEncoding);
                 Array.Copy(mdbSector, 0x03A, pString, 0, 16);
-                BB.disasm_name = StringHandlers.PascalToString(pString, CurrentEncoding);
+                BB.disasm_name = StringHandlers.PascalToString(pString, currentEncoding);
                 Array.Copy(mdbSector, 0x04A, pString, 0, 16);
-                BB.stupscr_name = StringHandlers.PascalToString(pString, CurrentEncoding);
+                BB.stupscr_name = StringHandlers.PascalToString(pString, currentEncoding);
                 Array.Copy(mdbSector, 0x05A, pString, 0, 16);
-                BB.bootup_name = StringHandlers.PascalToString(pString, CurrentEncoding);
+                BB.bootup_name = StringHandlers.PascalToString(pString, currentEncoding);
                 Array.Copy(mdbSector, 0x06A, pString, 0, 16);
-                BB.clipbrd_name = StringHandlers.PascalToString(pString, CurrentEncoding);
+                BB.clipbrd_name = StringHandlers.PascalToString(pString, currentEncoding);
 
                 BB.max_files = BigEndianBitConverter.ToUInt16(bbSector, 0x07A);
                 BB.queue_size = BigEndianBitConverter.ToUInt16(bbSector, 0x07C);
@@ -173,26 +173,26 @@ namespace DiscImageChef.Filesystems.AppleMFS
 
             information = sb.ToString();
 
-            XmlFsType = new FileSystemType();
+            xmlFsType = new FileSystemType();
             if(MDB.drLsBkUp > 0)
             {
-                XmlFsType.BackupDate = DateHandlers.MacToDateTime(MDB.drLsBkUp);
-                XmlFsType.BackupDateSpecified = true;
+                xmlFsType.BackupDate = DateHandlers.MacToDateTime(MDB.drLsBkUp);
+                xmlFsType.BackupDateSpecified = true;
             }
-            XmlFsType.Bootable = BB.signature == MFSBB_MAGIC;
-            XmlFsType.Clusters = MDB.drNmAlBlks;
-            XmlFsType.ClusterSize = (int)MDB.drAlBlkSiz;
+            xmlFsType.Bootable = BB.signature == MFSBB_MAGIC;
+            xmlFsType.Clusters = MDB.drNmAlBlks;
+            xmlFsType.ClusterSize = (int)MDB.drAlBlkSiz;
             if(MDB.drCrDate > 0)
             {
-                XmlFsType.CreationDate = DateHandlers.MacToDateTime(MDB.drCrDate);
-                XmlFsType.CreationDateSpecified = true;
+                xmlFsType.CreationDate = DateHandlers.MacToDateTime(MDB.drCrDate);
+                xmlFsType.CreationDateSpecified = true;
             }
-            XmlFsType.Files = MDB.drNmFls;
-            XmlFsType.FilesSpecified = true;
-            XmlFsType.FreeClusters = MDB.drFreeBks;
-            XmlFsType.FreeClustersSpecified = true;
-            XmlFsType.Type = "MFS";
-            XmlFsType.VolumeName = MDB.drVN;
+            xmlFsType.Files = MDB.drNmFls;
+            xmlFsType.FilesSpecified = true;
+            xmlFsType.FreeClusters = MDB.drFreeBks;
+            xmlFsType.FreeClustersSpecified = true;
+            xmlFsType.Type = "MFS";
+            xmlFsType.VolumeName = MDB.drVN;
         }
     }
 }
\ No newline at end of file
diff --git a/DiscImageChef.Filesystems/AppleMFS/Super.cs b/DiscImageChef.Filesystems/AppleMFS/Super.cs
index f6b13167..f58d89cd 100644
--- a/DiscImageChef.Filesystems/AppleMFS/Super.cs
+++ b/DiscImageChef.Filesystems/AppleMFS/Super.cs
@@ -31,6 +31,8 @@
 // ****************************************************************************/
 
 using System;
+using System.Text;
+using DiscImageChef.CommonTypes;
 using DiscImageChef.DiscImages;
 using Schemas;
 
@@ -39,8 +41,11 @@ namespace DiscImageChef.Filesystems.AppleMFS
     // Information from Inside Macintosh Volume II
     public partial class AppleMFS
     {
-        public override Errno Mount(bool debug)
+        public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug)
         {
+            device = imagePlugin;
+            partitionStart = partition.Start;
+            currentEncoding = encoding ?? Encoding.GetEncoding("macintosh");
             this.debug = debug;
             volMDB = new MFS_MasterDirectoryBlock();
 
@@ -67,14 +72,14 @@ namespace DiscImageChef.Filesystems.AppleMFS
             volMDB.drVNSiz = mdbBlocks[0x024];
             byte[] variableSize = new byte[volMDB.drVNSiz + 1];
             Array.Copy(mdbBlocks, 0x024, variableSize, 0, volMDB.drVNSiz + 1);
-            volMDB.drVN = StringHandlers.PascalToString(variableSize, CurrentEncoding);
+            volMDB.drVN = StringHandlers.PascalToString(variableSize, currentEncoding);
 
             directoryBlocks = device.ReadSectors(volMDB.drDirSt + partitionStart, volMDB.drBlLen);
             int bytesInBlockMap = volMDB.drNmAlBlks * 12 / 8 + volMDB.drNmAlBlks * 12 % 8;
             const int BYTES_BEFORE_BLOCK_MAP = 64;
             int bytesInWholeMdb = bytesInBlockMap + BYTES_BEFORE_BLOCK_MAP;
-            int sectorsInWholeMdb = bytesInWholeMdb / (int)device.ImageInfo.SectorSize +
-                                    bytesInWholeMdb % (int)device.ImageInfo.SectorSize;
+            int sectorsInWholeMdb = bytesInWholeMdb / (int)device.Info.SectorSize +
+                                    bytesInWholeMdb % (int)device.Info.SectorSize;
             byte[] wholeMdb = device.ReadSectors(partitionStart + 2, (uint)sectorsInWholeMdb);
             blockMapBytes = new byte[bytesInBlockMap];
             Array.Copy(wholeMdb, BYTES_BEFORE_BLOCK_MAP, blockMapBytes, 0, blockMapBytes.Length);
@@ -105,7 +110,7 @@ namespace DiscImageChef.Filesystems.AppleMFS
                 offset += 12;
             }
 
-            if(device.ImageInfo.ReadableSectorTags.Contains(SectorTagType.AppleSectorTag))
+            if(device.Info.ReadableSectorTags.Contains(SectorTagType.AppleSectorTag))
             {
                 mdbTags = device.ReadSectorTag(2 + partitionStart, SectorTagType.AppleSectorTag);
                 bootTags = device.ReadSectorTag(0 + partitionStart, SectorTagType.AppleSectorTag);
@@ -115,7 +120,7 @@ namespace DiscImageChef.Filesystems.AppleMFS
                                                    SectorTagType.AppleSectorTag);
             }
 
-            sectorsPerBlock = (int)(volMDB.drAlBlkSiz / device.ImageInfo.SectorSize);
+            sectorsPerBlock = (int)(volMDB.drAlBlkSiz / device.Info.SectorSize);
 
             if(!FillDirectory()) return Errno.InvalidArgument;
 
@@ -125,36 +130,31 @@ namespace DiscImageChef.Filesystems.AppleMFS
 
             if(bbSig != MFSBB_MAGIC) bootBlocks = null;
 
-            XmlFsType = new FileSystemType();
+            xmlFsType = new FileSystemType();
             if(volMDB.drLsBkUp > 0)
             {
-                XmlFsType.BackupDate = DateHandlers.MacToDateTime(volMDB.drLsBkUp);
-                XmlFsType.BackupDateSpecified = true;
+                xmlFsType.BackupDate = DateHandlers.MacToDateTime(volMDB.drLsBkUp);
+                xmlFsType.BackupDateSpecified = true;
             }
-            XmlFsType.Bootable = bbSig == MFSBB_MAGIC;
-            XmlFsType.Clusters = volMDB.drNmAlBlks;
-            XmlFsType.ClusterSize = (int)volMDB.drAlBlkSiz;
+            xmlFsType.Bootable = bbSig == MFSBB_MAGIC;
+            xmlFsType.Clusters = volMDB.drNmAlBlks;
+            xmlFsType.ClusterSize = (int)volMDB.drAlBlkSiz;
             if(volMDB.drCrDate > 0)
             {
-                XmlFsType.CreationDate = DateHandlers.MacToDateTime(volMDB.drCrDate);
-                XmlFsType.CreationDateSpecified = true;
+                xmlFsType.CreationDate = DateHandlers.MacToDateTime(volMDB.drCrDate);
+                xmlFsType.CreationDateSpecified = true;
             }
-            XmlFsType.Files = volMDB.drNmFls;
-            XmlFsType.FilesSpecified = true;
-            XmlFsType.FreeClusters = volMDB.drFreeBks;
-            XmlFsType.FreeClustersSpecified = true;
-            XmlFsType.Type = "MFS";
-            XmlFsType.VolumeName = volMDB.drVN;
+            xmlFsType.Files = volMDB.drNmFls;
+            xmlFsType.FilesSpecified = true;
+            xmlFsType.FreeClusters = volMDB.drFreeBks;
+            xmlFsType.FreeClustersSpecified = true;
+            xmlFsType.Type = "MFS";
+            xmlFsType.VolumeName = volMDB.drVN;
 
             return Errno.NoError;
         }
 
-        public override Errno Mount()
-        {
-            return Mount(false);
-        }
-
-        public override Errno Unmount()
+        public virtual Errno Unmount()
         {
             mounted = false;
             idToFilename = null;
@@ -165,7 +165,7 @@ namespace DiscImageChef.Filesystems.AppleMFS
             return Errno.NoError;
         }
 
-        public override Errno StatFs(ref FileSystemInfo stat)
+        public virtual Errno StatFs(ref FileSystemInfo stat)
         {
             stat = new FileSystemInfo
             {
@@ -173,7 +173,7 @@ namespace DiscImageChef.Filesystems.AppleMFS
                 FilenameLength = 255,
                 Files = volMDB.drNmFls,
                 FreeBlocks = volMDB.drFreeBks,
-                PluginId = PluginUuid,
+                PluginId = Id,
                 Type = "Apple MFS"
             };
             stat.FreeFiles = uint.MaxValue - stat.Files;
diff --git a/DiscImageChef.Filesystems/AppleMFS/Xattr.cs b/DiscImageChef.Filesystems/AppleMFS/Xattr.cs
index 250bfbdd..a0273233 100644
--- a/DiscImageChef.Filesystems/AppleMFS/Xattr.cs
+++ b/DiscImageChef.Filesystems/AppleMFS/Xattr.cs
@@ -40,7 +40,7 @@ namespace DiscImageChef.Filesystems.AppleMFS
     // Information from Inside Macintosh Volume II
     public partial class AppleMFS
     {
-        public override Errno ListXAttr(string path, ref List xattrs)
+        public virtual Errno ListXAttr(string path, ref List xattrs)
         {
             if(!mounted) return Errno.AccessDenied;
 
@@ -55,7 +55,7 @@ namespace DiscImageChef.Filesystems.AppleMFS
                    string.Compare(path, "$Boot", StringComparison.InvariantCulture) == 0 ||
                    string.Compare(path, "$MDB", StringComparison.InvariantCulture) == 0)
                 {
-                    if(device.ImageInfo.ReadableSectorTags.Contains(SectorTagType.AppleSectorTag))
+                    if(device.Info.ReadableSectorTags.Contains(SectorTagType.AppleSectorTag))
                         xattrs.Add("com.apple.macintosh.tags");
 
                     return Errno.NoError;
@@ -68,13 +68,13 @@ namespace DiscImageChef.Filesystems.AppleMFS
             if(entry.flRLgLen > 0)
             {
                 xattrs.Add("com.apple.ResourceFork");
-                if(debug && device.ImageInfo.ReadableSectorTags.Contains(SectorTagType.AppleSectorTag))
+                if(debug && device.Info.ReadableSectorTags.Contains(SectorTagType.AppleSectorTag))
                     xattrs.Add("com.apple.ResourceFork.tags");
             }
 
             if(!ArrayHelpers.ArrayIsNullOrEmpty(entry.flUsrWds)) xattrs.Add("com.apple.FinderInfo");
 
-            if(debug && device.ImageInfo.ReadableSectorTags.Contains(SectorTagType.AppleSectorTag) && entry.flLgLen > 0)
+            if(debug && device.Info.ReadableSectorTags.Contains(SectorTagType.AppleSectorTag) && entry.flLgLen > 0)
                 xattrs.Add("com.apple.macintosh.tags");
 
             xattrs.Sort();
@@ -82,7 +82,7 @@ namespace DiscImageChef.Filesystems.AppleMFS
             return Errno.NoError;
         }
 
-        public override Errno GetXattr(string path, string xattr, ref byte[] buf)
+        public virtual Errno GetXattr(string path, string xattr, ref byte[] buf)
         {
             if(!mounted) return Errno.AccessDenied;
 
@@ -94,7 +94,7 @@ namespace DiscImageChef.Filesystems.AppleMFS
                    string.Compare(path, "$Bitmap", StringComparison.InvariantCulture) == 0 ||
                    string.Compare(path, "$Boot", StringComparison.InvariantCulture) == 0 ||
                    string.Compare(path, "$MDB", StringComparison.InvariantCulture) == 0)
-                    if(device.ImageInfo.ReadableSectorTags.Contains(SectorTagType.AppleSectorTag) &&
+                    if(device.Info.ReadableSectorTags.Contains(SectorTagType.AppleSectorTag) &&
                        string.Compare(xattr, "com.apple.macintosh.tags", StringComparison.InvariantCulture) == 0)
                     {
                         if(string.Compare(path, "$", StringComparison.InvariantCulture) == 0)
@@ -155,7 +155,7 @@ namespace DiscImageChef.Filesystems.AppleMFS
                 return Errno.NoError;
             }
 
-            if(!debug || !device.ImageInfo.ReadableSectorTags.Contains(SectorTagType.AppleSectorTag) ||
+            if(!debug || !device.Info.ReadableSectorTags.Contains(SectorTagType.AppleSectorTag) ||
                string.Compare(xattr, "com.apple.macintosh.tags", StringComparison.InvariantCulture) != 0)
                 return Errno.NoSuchExtendedAttribute;
 
diff --git a/DiscImageChef.Filesystems/AtheOS.cs b/DiscImageChef.Filesystems/AtheOS.cs
index 18b033b1..498d77ed 100644
--- a/DiscImageChef.Filesystems/AtheOS.cs
+++ b/DiscImageChef.Filesystems/AtheOS.cs
@@ -40,7 +40,7 @@ using Schemas;
 
 namespace DiscImageChef.Filesystems
 {
-    public class AtheOS : Filesystem
+    public class AtheOS : IFilesystem
     {
         // Little endian constants (that is, as read by .NET :p)
         const uint AFS_MAGIC1 = 0x41465331;
@@ -49,36 +49,22 @@ namespace DiscImageChef.Filesystems
         // Common constants
         const uint AFS_SUPERBLOCK_SIZE = 1024;
         const uint AFS_BOOTBLOCK_SIZE = AFS_SUPERBLOCK_SIZE;
+        Encoding currentEncoding;
+        FileSystemType xmlFsType;
+        public virtual FileSystemType XmlFsType => xmlFsType;
 
-        public AtheOS()
-        {
-            Name = "AtheOS Filesystem";
-            PluginUuid = new Guid("AAB2C4F1-DC07-49EE-A948-576CC51B58C5");
-            CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
-        }
+        public virtual Encoding Encoding => currentEncoding;
+        public virtual string Name => "AtheOS Filesystem";
+        public virtual Guid Id => new Guid("AAB2C4F1-DC07-49EE-A948-576CC51B58C5");
 
-        public AtheOS(Encoding encoding)
+        public virtual bool Identify(IMediaImage imagePlugin, Partition partition)
         {
-            Name = "AtheOS Filesystem";
-            PluginUuid = new Guid("AAB2C4F1-DC07-49EE-A948-576CC51B58C5");
-            CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
-        }
-
-        public AtheOS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
-        {
-            Name = "AtheOS Filesystem";
-            PluginUuid = new Guid("AAB2C4F1-DC07-49EE-A948-576CC51B58C5");
-            CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
-        }
-
-        public override bool Identify(ImagePlugin imagePlugin, Partition partition)
-        {
-            ulong sector = AFS_BOOTBLOCK_SIZE / imagePlugin.ImageInfo.SectorSize;
-            uint offset = AFS_BOOTBLOCK_SIZE % imagePlugin.ImageInfo.SectorSize;
+            ulong sector = AFS_BOOTBLOCK_SIZE / imagePlugin.Info.SectorSize;
+            uint offset = AFS_BOOTBLOCK_SIZE % imagePlugin.Info.SectorSize;
             uint run = 1;
 
-            if(imagePlugin.ImageInfo.SectorSize < AFS_SUPERBLOCK_SIZE)
-                run = AFS_SUPERBLOCK_SIZE / imagePlugin.ImageInfo.SectorSize;
+            if(imagePlugin.Info.SectorSize < AFS_SUPERBLOCK_SIZE)
+                run = AFS_SUPERBLOCK_SIZE / imagePlugin.Info.SectorSize;
 
             if(sector + partition.Start >= partition.End) return false;
 
@@ -93,18 +79,20 @@ namespace DiscImageChef.Filesystems
             return magic == AFS_MAGIC1;
         }
 
-        public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information)
+        public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
+                                            Encoding encoding)
         {
+            currentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
             information = "";
 
             StringBuilder sb = new StringBuilder();
 
-            ulong sector = AFS_BOOTBLOCK_SIZE / imagePlugin.ImageInfo.SectorSize;
-            uint offset = AFS_BOOTBLOCK_SIZE % imagePlugin.ImageInfo.SectorSize;
+            ulong sector = AFS_BOOTBLOCK_SIZE / imagePlugin.Info.SectorSize;
+            uint offset = AFS_BOOTBLOCK_SIZE % imagePlugin.Info.SectorSize;
             uint run = 1;
 
-            if(imagePlugin.ImageInfo.SectorSize < AFS_SUPERBLOCK_SIZE)
-                run = AFS_SUPERBLOCK_SIZE / imagePlugin.ImageInfo.SectorSize;
+            if(imagePlugin.Info.SectorSize < AFS_SUPERBLOCK_SIZE)
+                run = AFS_SUPERBLOCK_SIZE / imagePlugin.Info.SectorSize;
 
             byte[] tmp = imagePlugin.ReadSectors(sector + partition.Start, run);
             byte[] sbSector = new byte[AFS_SUPERBLOCK_SIZE];
@@ -119,7 +107,7 @@ namespace DiscImageChef.Filesystems
 
             if(afsSb.flags == 1) sb.AppendLine("Filesystem is read-only");
 
-            sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(afsSb.name, CurrentEncoding)).AppendLine();
+            sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(afsSb.name, currentEncoding)).AppendLine();
             sb.AppendFormat("{0} bytes per block", afsSb.block_size).AppendLine();
             sb.AppendFormat("{0} blocks in volume ({1} bytes)", afsSb.num_blocks, afsSb.num_blocks * afsSb.block_size)
               .AppendLine();
@@ -151,7 +139,7 @@ namespace DiscImageChef.Filesystems
 
             information = sb.ToString();
 
-            XmlFsType = new FileSystemType
+            xmlFsType = new FileSystemType
             {
                 Clusters = afsSb.num_blocks,
                 ClusterSize = (int)afsSb.block_size,
@@ -159,66 +147,61 @@ namespace DiscImageChef.Filesystems
                 FreeClusters = afsSb.num_blocks - afsSb.used_blocks,
                 FreeClustersSpecified = true,
                 Type = "AtheOS filesystem",
-                VolumeName = StringHandlers.CToString(afsSb.name, CurrentEncoding)
+                VolumeName = StringHandlers.CToString(afsSb.name, currentEncoding)
             };
         }
 
-        public override Errno Mount()
+        public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Mount(bool debug)
+        public virtual Errno Unmount()
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Unmount()
+        public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
+        public virtual Errno GetAttributes(string path, ref FileAttributes attributes)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno GetAttributes(string path, ref FileAttributes attributes)
+        public virtual Errno ListXAttr(string path, ref List xattrs)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno ListXAttr(string path, ref List xattrs)
+        public virtual Errno GetXattr(string path, string xattr, ref byte[] buf)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno GetXattr(string path, string xattr, ref byte[] buf)
+        public virtual Errno Read(string path, long offset, long size, ref byte[] buf)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Read(string path, long offset, long size, ref byte[] buf)
+        public virtual Errno ReadDir(string path, ref List contents)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno ReadDir(string path, ref List contents)
+        public virtual Errno StatFs(ref FileSystemInfo stat)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno StatFs(ref FileSystemInfo stat)
+        public virtual Errno Stat(string path, ref FileEntryInfo stat)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Stat(string path, ref FileEntryInfo stat)
-        {
-            return Errno.NotImplemented;
-        }
-
-        public override Errno ReadLink(string path, ref string dest)
+        public virtual Errno ReadLink(string path, ref string dest)
         {
             return Errno.NotImplemented;
         }
diff --git a/DiscImageChef.Filesystems/BFS.cs b/DiscImageChef.Filesystems/BFS.cs
index 7fd75385..7a7f781c 100644
--- a/DiscImageChef.Filesystems/BFS.cs
+++ b/DiscImageChef.Filesystems/BFS.cs
@@ -41,7 +41,7 @@ using Schemas;
 namespace DiscImageChef.Filesystems
 {
     // Information from Practical Filesystem Design, ISBN 1-55860-497-9
-    public class BeFS : Filesystem
+    public class BeFS : IFilesystem
     {
         // Little endian constants (that is, as read by .NET :p)
         const uint BEFS_MAGIC1 = 0x42465331;
@@ -54,29 +54,15 @@ namespace DiscImageChef.Filesystems
         // Common constants
         const uint BEFS_CLEAN = 0x434C454E;
         const uint BEFS_DIRTY = 0x44495254;
+        Encoding currentEncoding;
+        FileSystemType xmlFsType;
+        public virtual FileSystemType XmlFsType => xmlFsType;
 
-        public BeFS()
-        {
-            Name = "Be Filesystem";
-            PluginUuid = new Guid("dc8572b3-b6ad-46e4-8de9-cbe123ff6672");
-            CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
-        }
+        public virtual Encoding Encoding => currentEncoding;
+        public virtual string Name => "Be Filesystem";
+        public virtual Guid Id => new Guid("dc8572b3-b6ad-46e4-8de9-cbe123ff6672");
 
-        public BeFS(Encoding encoding)
-        {
-            Name = "Be Filesystem";
-            PluginUuid = new Guid("dc8572b3-b6ad-46e4-8de9-cbe123ff6672");
-            CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
-        }
-
-        public BeFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
-        {
-            Name = "Be Filesystem";
-            PluginUuid = new Guid("dc8572b3-b6ad-46e4-8de9-cbe123ff6672");
-            CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
-        }
-
-        public override bool Identify(ImagePlugin imagePlugin, Partition partition)
+        public virtual bool Identify(IMediaImage imagePlugin, Partition partition)
         {
             if(2 + partition.Start >= partition.End) return false;
 
@@ -106,8 +92,9 @@ namespace DiscImageChef.Filesystems
             return magic == BEFS_MAGIC1 || magicBe == BEFS_MAGIC1;
         }
 
-        public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information)
+        public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding)
         {
+            currentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
             information = "";
 
             StringBuilder sb = new StringBuilder();
@@ -183,7 +170,7 @@ namespace DiscImageChef.Filesystems
                     break;
             }
 
-            sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(besb.name, CurrentEncoding)).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();
@@ -209,7 +196,7 @@ namespace DiscImageChef.Filesystems
 
             information = sb.ToString();
 
-            XmlFsType = new FileSystemType
+            xmlFsType = new FileSystemType
             {
                 Clusters = besb.num_blocks,
                 ClusterSize = (int)besb.block_size,
@@ -217,66 +204,61 @@ namespace DiscImageChef.Filesystems
                 FreeClusters = besb.num_blocks - besb.used_blocks,
                 FreeClustersSpecified = true,
                 Type = "BeFS",
-                VolumeName = StringHandlers.CToString(besb.name, CurrentEncoding)
+                VolumeName = StringHandlers.CToString(besb.name, currentEncoding)
             };
         }
 
-        public override Errno Mount()
+        public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Mount(bool debug)
+        public virtual Errno Unmount()
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Unmount()
+        public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
+        public virtual Errno GetAttributes(string path, ref FileAttributes attributes)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno GetAttributes(string path, ref FileAttributes attributes)
+        public virtual Errno ListXAttr(string path, ref List xattrs)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno ListXAttr(string path, ref List xattrs)
+        public virtual Errno GetXattr(string path, string xattr, ref byte[] buf)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno GetXattr(string path, string xattr, ref byte[] buf)
+        public virtual Errno Read(string path, long offset, long size, ref byte[] buf)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Read(string path, long offset, long size, ref byte[] buf)
+        public virtual Errno ReadDir(string path, ref List contents)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno ReadDir(string path, ref List contents)
+        public virtual Errno StatFs(ref FileSystemInfo stat)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno StatFs(ref FileSystemInfo stat)
+        public virtual Errno Stat(string path, ref FileEntryInfo stat)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Stat(string path, ref FileEntryInfo stat)
-        {
-            return Errno.NotImplemented;
-        }
-
-        public override Errno ReadLink(string path, ref string dest)
+        public virtual Errno ReadLink(string path, ref string dest)
         {
             return Errno.NotImplemented;
         }
diff --git a/DiscImageChef.Filesystems/BTRFS.cs b/DiscImageChef.Filesystems/BTRFS.cs
index 5192d3ac..99ddb188 100644
--- a/DiscImageChef.Filesystems/BTRFS.cs
+++ b/DiscImageChef.Filesystems/BTRFS.cs
@@ -41,40 +41,26 @@ using Schemas;
 
 namespace DiscImageChef.Filesystems
 {
-    public class BTRFS : Filesystem
+    public class BTRFS : IFilesystem
     {
         /// 
         ///     BTRFS magic "_BHRfS_M"
         /// 
         const ulong btrfsMagic = 0x4D5F53665248425F;
+        FileSystemType xmlFsType;
+        public virtual FileSystemType XmlFsType => xmlFsType;
 
-        public BTRFS()
-        {
-            Name = "B-tree file system";
-            PluginUuid = new Guid("C904CF15-5222-446B-B7DB-02EAC5D781B3");
-            CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
-        }
+        Encoding currentEncoding;
+        public virtual Encoding Encoding => currentEncoding;
+        public virtual string Name => "B-tree file system";
+        public virtual Guid Id => new Guid("C904CF15-5222-446B-B7DB-02EAC5D781B3");
 
-        public BTRFS(Encoding encoding)
-        {
-            Name = "B-tree file system";
-            PluginUuid = new Guid("C904CF15-5222-446B-B7DB-02EAC5D781B3");
-            CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
-        }
-
-        public BTRFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
-        {
-            Name = "B-tree file system";
-            PluginUuid = new Guid("C904CF15-5222-446B-B7DB-02EAC5D781B3");
-            CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
-        }
-
-        public override bool Identify(ImagePlugin imagePlugin, Partition partition)
+        public virtual bool Identify(IMediaImage imagePlugin, Partition partition)
         {
             if(partition.Start >= partition.End) return false;
 
-            ulong sbSectorOff = 0x10000 / imagePlugin.ImageInfo.SectorSize;
-            uint sbSectorSize = 0x1000 / imagePlugin.ImageInfo.SectorSize;
+            ulong sbSectorOff = 0x10000 / imagePlugin.Info.SectorSize;
+            uint sbSectorSize = 0x1000 / imagePlugin.Info.SectorSize;
 
             if(sbSectorOff + partition.Start >= partition.End) return false;
 
@@ -97,14 +83,16 @@ namespace DiscImageChef.Filesystems
             return btrfsSb.magic == btrfsMagic;
         }
 
-        public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information)
+        public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
+                                            Encoding encoding)
         {
+            currentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
             StringBuilder sbInformation = new StringBuilder();
-            XmlFsType = new FileSystemType();
+            xmlFsType = new FileSystemType();
             information = "";
 
-            ulong sbSectorOff = 0x10000 / imagePlugin.ImageInfo.SectorSize;
-            uint sbSectorSize = 0x1000 / imagePlugin.ImageInfo.SectorSize;
+            ulong sbSectorOff = 0x10000 / imagePlugin.Info.SectorSize;
+            uint sbSectorSize = 0x1000 / imagePlugin.Info.SectorSize;
 
             byte[] sector = imagePlugin.ReadSectors(sbSectorOff + partition.Start, sbSectorSize);
 
@@ -183,7 +171,7 @@ namespace DiscImageChef.Filesystems
 
             information = sbInformation.ToString();
 
-            XmlFsType = new FileSystemType
+            xmlFsType = new FileSystemType
             {
                 Clusters = (long)(btrfsSb.total_bytes / btrfsSb.sectorsize),
                 ClusterSize = (int)btrfsSb.sectorsize,
@@ -193,65 +181,60 @@ namespace DiscImageChef.Filesystems
                 VolumeSetIdentifier = $"{btrfsSb.dev_item.device_uuid}",
                 Type = Name
             };
-            XmlFsType.FreeClusters = XmlFsType.Clusters - (long)(btrfsSb.bytes_used / btrfsSb.sectorsize);
+            xmlFsType.FreeClusters = xmlFsType.Clusters - (long)(btrfsSb.bytes_used / btrfsSb.sectorsize);
         }
 
-        public override Errno Mount()
+        public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Mount(bool debug)
+        public virtual Errno Unmount()
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Unmount()
+        public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
+        public virtual Errno GetAttributes(string path, ref FileAttributes attributes)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno GetAttributes(string path, ref FileAttributes attributes)
+        public virtual Errno ListXAttr(string path, ref List xattrs)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno ListXAttr(string path, ref List xattrs)
+        public virtual Errno GetXattr(string path, string xattr, ref byte[] buf)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno GetXattr(string path, string xattr, ref byte[] buf)
+        public virtual Errno Read(string path, long offset, long size, ref byte[] buf)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Read(string path, long offset, long size, ref byte[] buf)
+        public virtual Errno ReadDir(string path, ref List contents)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno ReadDir(string path, ref List contents)
+        public virtual Errno StatFs(ref FileSystemInfo stat)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno StatFs(ref FileSystemInfo stat)
+        public virtual Errno Stat(string path, ref FileEntryInfo stat)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Stat(string path, ref FileEntryInfo stat)
-        {
-            return Errno.NotImplemented;
-        }
-
-        public override Errno ReadLink(string path, ref string dest)
+        public virtual Errno ReadLink(string path, ref string dest)
         {
             return Errno.NotImplemented;
         }
diff --git a/DiscImageChef.Filesystems/CBM.cs b/DiscImageChef.Filesystems/CBM.cs
index 92f3e9d1..3a2007d9 100644
--- a/DiscImageChef.Filesystems/CBM.cs
+++ b/DiscImageChef.Filesystems/CBM.cs
@@ -42,41 +42,28 @@ using Encoding = System.Text.Encoding;
 
 namespace DiscImageChef.Filesystems
 {
-    public class CBM : Filesystem
+    public class CBM : IFilesystem
     {
-        public CBM()
-        {
-            Name = "Commodore file system";
-            PluginUuid = new Guid("D104744E-A376-450C-BAC0-1347C93F983B");
-            CurrentEncoding = new PETSCII();
-        }
+        Encoding currentEncoding;
+        FileSystemType xmlFsType;
+        public virtual FileSystemType XmlFsType => xmlFsType;
 
-        public CBM(Encoding encoding)
-        {
-            Name = "Commodore file system";
-            PluginUuid = new Guid("D104744E-A376-450C-BAC0-1347C93F983B");
-            CurrentEncoding = new PETSCII();
-        }
+        public virtual string Name => "Commodore file system";
+        public virtual Guid Id => new Guid("D104744E-A376-450C-BAC0-1347C93F983B");
+        public virtual Encoding Encoding => currentEncoding;
 
-        public CBM(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
-        {
-            Name = "Commodore file system";
-            PluginUuid = new Guid("D104744E-A376-450C-BAC0-1347C93F983B");
-            CurrentEncoding = new PETSCII();
-        }
-
-        public override bool Identify(ImagePlugin imagePlugin, Partition partition)
+        public virtual bool Identify(IMediaImage imagePlugin, Partition partition)
         {
             if(partition.Start > 0) return false;
 
-            if(imagePlugin.ImageInfo.SectorSize != 256) return false;
+            if(imagePlugin.Info.SectorSize != 256) return false;
 
-            if(imagePlugin.ImageInfo.Sectors != 683 && imagePlugin.ImageInfo.Sectors != 768 &&
-               imagePlugin.ImageInfo.Sectors != 1366 && imagePlugin.ImageInfo.Sectors != 3200) return false;
+            if(imagePlugin.Info.Sectors != 683 && imagePlugin.Info.Sectors != 768 && imagePlugin.Info.Sectors != 1366 &&
+               imagePlugin.Info.Sectors != 3200) return false;
 
             byte[] sector;
 
-            if(imagePlugin.ImageInfo.Sectors == 3200)
+            if(imagePlugin.Info.Sectors == 3200)
             {
                 sector = imagePlugin.ReadSector(1560);
                 CommodoreHeader cbmHdr = new CommodoreHeader();
@@ -104,22 +91,23 @@ namespace DiscImageChef.Filesystems
             return false;
         }
 
-        public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information)
+        public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding)
         {
+            currentEncoding = new PETSCII();
             byte[] sector;
 
             StringBuilder sbInformation = new StringBuilder();
 
             sbInformation.AppendLine("Commodore file system");
 
-            XmlFsType = new FileSystemType
+            xmlFsType = new FileSystemType
             {
                 Type = "Commodore file system",
-                Clusters = (long)imagePlugin.ImageInfo.Sectors,
+                Clusters = (long)imagePlugin.Info.Sectors,
                 ClusterSize = 256
             };
 
-            if(imagePlugin.ImageInfo.Sectors == 3200)
+            if(imagePlugin.Info.Sectors == 3200)
             {
                 sector = imagePlugin.ReadSector(1560);
                 CommodoreHeader cbmHdr = new CommodoreHeader();
@@ -138,11 +126,11 @@ namespace DiscImageChef.Filesystems
                 sbInformation.AppendFormat("Disk Version: {0}", Encoding.ASCII.GetString(new[] {cbmHdr.diskVersion}))
                              .AppendLine();
                 sbInformation.AppendFormat("Disk ID: {0}", cbmHdr.diskId).AppendLine();
-                sbInformation.AppendFormat("Disk name: {0}", StringHandlers.CToString(cbmHdr.name, CurrentEncoding))
+                sbInformation.AppendFormat("Disk name: {0}", StringHandlers.CToString(cbmHdr.name, currentEncoding))
                              .AppendLine();
 
-                XmlFsType.VolumeName = StringHandlers.CToString(cbmHdr.name, CurrentEncoding);
-                XmlFsType.VolumeSerial = $"{cbmHdr.diskId}";
+                xmlFsType.VolumeName = StringHandlers.CToString(cbmHdr.name, currentEncoding);
+                xmlFsType.VolumeSerial = $"{cbmHdr.diskId}";
             }
             else
             {
@@ -161,72 +149,67 @@ namespace DiscImageChef.Filesystems
                 sbInformation.AppendFormat("DOS Version: {0}", Encoding.ASCII.GetString(new[] {cbmBam.dosVersion}))
                              .AppendLine();
                 sbInformation.AppendFormat("Disk ID: {0}", cbmBam.diskId).AppendLine();
-                sbInformation.AppendFormat("Disk name: {0}", StringHandlers.CToString(cbmBam.name, CurrentEncoding))
+                sbInformation.AppendFormat("Disk name: {0}", StringHandlers.CToString(cbmBam.name, currentEncoding))
                              .AppendLine();
 
-                XmlFsType.VolumeName = StringHandlers.CToString(cbmBam.name, CurrentEncoding);
-                XmlFsType.VolumeSerial = $"{cbmBam.diskId}";
+                xmlFsType.VolumeName = StringHandlers.CToString(cbmBam.name, currentEncoding);
+                xmlFsType.VolumeSerial = $"{cbmBam.diskId}";
             }
 
             information = sbInformation.ToString();
         }
 
-        public override Errno Mount()
+        public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Mount(bool debug)
+        public virtual Errno Unmount()
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Unmount()
+        public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
+        public virtual Errno GetAttributes(string path, ref FileAttributes attributes)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno GetAttributes(string path, ref FileAttributes attributes)
+        public virtual Errno ListXAttr(string path, ref List xattrs)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno ListXAttr(string path, ref List xattrs)
+        public virtual Errno GetXattr(string path, string xattr, ref byte[] buf)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno GetXattr(string path, string xattr, ref byte[] buf)
+        public virtual Errno Read(string path, long offset, long size, ref byte[] buf)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Read(string path, long offset, long size, ref byte[] buf)
+        public virtual Errno ReadDir(string path, ref List contents)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno ReadDir(string path, ref List contents)
+        public virtual Errno StatFs(ref FileSystemInfo stat)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno StatFs(ref FileSystemInfo stat)
+        public virtual Errno Stat(string path, ref FileEntryInfo stat)
         {
             return Errno.NotImplemented;
         }
 
-        public override Errno Stat(string path, ref FileEntryInfo stat)
-        {
-            return Errno.NotImplemented;
-        }
-
-        public override Errno ReadLink(string path, ref string dest)
+        public virtual Errno ReadLink(string path, ref string dest)
         {
             return Errno.NotImplemented;
         }
diff --git a/DiscImageChef.Filesystems/CPM/CPM.cs b/DiscImageChef.Filesystems/CPM/CPM.cs
index b7b3e15e..b69668c7 100644
--- a/DiscImageChef.Filesystems/CPM/CPM.cs
+++ b/DiscImageChef.Filesystems/CPM/CPM.cs
@@ -35,12 +35,12 @@ using System.Collections.Generic;
 using System.Text;
 using DiscImageChef.CommonTypes;
 using DiscImageChef.DiscImages;
+using Schemas;
 
 namespace DiscImageChef.Filesystems.CPM
 {
-    partial class CPM : Filesystem
+    partial class CPM : IFilesystem
     {
-        readonly ImagePlugin device;
         /// 
         ///     True if  thinks this is a CP/M filesystem
         /// 
@@ -50,6 +50,8 @@ namespace DiscImageChef.Filesystems.CPM
         ///     Cached 
         /// 
         FileSystemInfo cpmStat;
+
+        Encoding currentEncoding;
         /// 
         ///     Cached file passwords, decoded
         /// 
@@ -59,6 +61,7 @@ namespace DiscImageChef.Filesystems.CPM
         ///     Stores all known CP/M disk definitions
         /// 
         CpmDefinitions definitions;
+        IMediaImage device;
         /// 
         ///     Cached directory listing
         /// 
@@ -109,28 +112,10 @@ namespace DiscImageChef.Filesystems.CPM
         ///     If  thinks this is a CP/M filesystem, this is the definition for it
         /// 
         CpmDefinition workingDefinition;
-
-        public CPM()
-        {
-            Name = "CP/M File System";
-            PluginUuid = new Guid("AA2B8585-41DF-4E3B-8A35-D1A935E2F8A1");
-            CurrentEncoding = Encoding.GetEncoding("IBM437");
-        }
-
-        public CPM(Encoding encoding)
-        {
-            Name = "CP/M File System";
-            PluginUuid = new Guid("AA2B8585-41DF-4E3B-8A35-D1A935E2F8A1");
-            CurrentEncoding = encoding ?? Encoding.GetEncoding("IBM437");
-        }
-
-        public CPM(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
-        {
-            device = imagePlugin;
-            this.partition = partition;
-            Name = "CP/M File System";
-            PluginUuid = new Guid("AA2B8585-41DF-4E3B-8A35-D1A935E2F8A1");
-            CurrentEncoding = encoding ?? Encoding.GetEncoding("IBM437");
-        }
+        FileSystemType xmlFsType;
+        public virtual FileSystemType XmlFsType => xmlFsType;
+        public virtual Encoding Encoding => currentEncoding;
+        public virtual string Name => "CP/M File System";
+        public virtual Guid Id => new Guid("AA2B8585-41DF-4E3B-8A35-D1A935E2F8A1");
     }
 }
\ No newline at end of file
diff --git a/DiscImageChef.Filesystems/CPM/Dir.cs b/DiscImageChef.Filesystems/CPM/Dir.cs
index aa59092f..0f35ff29 100644
--- a/DiscImageChef.Filesystems/CPM/Dir.cs
+++ b/DiscImageChef.Filesystems/CPM/Dir.cs
@@ -39,7 +39,7 @@ namespace DiscImageChef.Filesystems.CPM
 {
     partial class CPM
     {
-        public override Errno ReadDir(string path, ref List contents)
+        public virtual Errno ReadDir(string path, ref List contents)
         {
             if(!mounted) return Errno.AccessDenied;
 
diff --git a/DiscImageChef.Filesystems/CPM/File.cs b/DiscImageChef.Filesystems/CPM/File.cs
index 7d9551aa..d9f3fa23 100644
--- a/DiscImageChef.Filesystems/CPM/File.cs
+++ b/DiscImageChef.Filesystems/CPM/File.cs
@@ -36,7 +36,7 @@ namespace DiscImageChef.Filesystems.CPM
 {
     partial class CPM
     {
-        public override Errno GetAttributes(string path, ref FileAttributes attributes)
+        public virtual Errno GetAttributes(string path, ref FileAttributes attributes)
         {
             if(!mounted) return Errno.AccessDenied;
 
@@ -59,12 +59,12 @@ namespace DiscImageChef.Filesystems.CPM
         }
 
         // TODO: Implementing this would require storing the interleaving
-        public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
+        public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
         {
             return !mounted ? Errno.AccessDenied : Errno.NotImplemented;
         }
 
-        public override Errno Read(string path, long offset, long size, ref byte[] buf)
+        public virtual Errno Read(string path, long offset, long size, ref byte[] buf)
         {
             if(!mounted) return Errno.AccessDenied;
 
@@ -90,12 +90,12 @@ namespace DiscImageChef.Filesystems.CPM
             return Errno.NoError;
         }
 
-        public override Errno ReadLink(string path, ref string dest)
+        public virtual Errno ReadLink(string path, ref string dest)
         {
             return !mounted ? Errno.AccessDenied : Errno.NotSupported;
         }
 
-        public override Errno Stat(string path, ref FileEntryInfo stat)
+        public virtual Errno Stat(string path, ref FileEntryInfo stat)
         {
             if(!mounted) return Errno.AccessDenied;
 
@@ -107,7 +107,7 @@ namespace DiscImageChef.Filesystems.CPM
                 if(labelCreationDate != null) stat.CreationTime = DateHandlers.CpmToDateTime(labelCreationDate);
                 if(labelUpdateDate != null) stat.StatusChangeTime = DateHandlers.CpmToDateTime(labelUpdateDate);
                 stat.Attributes = FileAttributes.Directory;
-                stat.BlockSize = XmlFsType.ClusterSize;
+                stat.BlockSize = xmlFsType.ClusterSize;
                 return Errno.NoError;
             }
 
diff --git a/DiscImageChef.Filesystems/CPM/Info.cs b/DiscImageChef.Filesystems/CPM/Info.cs
index 72a86924..514ca445 100644
--- a/DiscImageChef.Filesystems/CPM/Info.cs
+++ b/DiscImageChef.Filesystems/CPM/Info.cs
@@ -44,11 +44,11 @@ namespace DiscImageChef.Filesystems.CPM
 {
     partial class CPM
     {
-        public override bool Identify(ImagePlugin imagePlugin, Partition partition)
+        public virtual bool Identify(IMediaImage imagePlugin, Partition partition)
         {
             // This will only continue on devices with a chance to have ever been used by CP/M while failing on all others
             // It's ugly, but will stop a lot of false positives
-            switch(imagePlugin.ImageInfo.MediaType)
+            switch(imagePlugin.Info.MediaType)
             {
                 case MediaType.Unknown:
                 case MediaType.Apple32SS:
@@ -203,8 +203,8 @@ namespace DiscImageChef.Filesystems.CPM
                         sectorSize = (ulong)(128 << amsSb.psh);
 
                         // Compare device limits from superblock to real limits
-                        if(sectorSize == imagePlugin.ImageInfo.SectorSize &&
-                           sectorCount == imagePlugin.ImageInfo.Sectors)
+                        if(sectorSize == imagePlugin.Info.SectorSize &&
+                           sectorCount == imagePlugin.Info.Sectors)
                         {
                             cpmFound = true;
                             firstDirectorySector = (ulong)(amsSb.off * amsSb.spt);
@@ -319,7 +319,7 @@ namespace DiscImageChef.Filesystems.CPM
                             (ulong)((hddSb.firstCylinder * hddSb.heads + hddSb.heads) * hddSb.sectorsPerTrack);
 
                         // If volume size corresponds with working partition (this variant will be inside MBR partitioning)
-                        if(sectorSize == imagePlugin.ImageInfo.SectorSize && startingSector == partition.Start &&
+                        if(sectorSize == imagePlugin.Info.SectorSize && startingSector == partition.Start &&
                            sectorsInPartition + partition.Start <= partition.End)
                         {
                             cpmFound = true;
@@ -405,7 +405,7 @@ namespace DiscImageChef.Filesystems.CPM
                     switch((FormatByte)formatByte)
                     {
                         case FormatByte.k160:
-                            if(imagePlugin.ImageInfo.SectorSize == 512 && imagePlugin.ImageInfo.Sectors == 320)
+                            if(imagePlugin.Info.SectorSize == 512 && imagePlugin.Info.Sectors == 320)
                             {
                                 cpmFound = true;
                                 firstDirectorySector86 = 8;
@@ -453,7 +453,7 @@ namespace DiscImageChef.Filesystems.CPM
 
                             break;
                         case FormatByte.k320:
-                            if(imagePlugin.ImageInfo.SectorSize == 512 && imagePlugin.ImageInfo.Sectors == 640)
+                            if(imagePlugin.Info.SectorSize == 512 && imagePlugin.Info.Sectors == 640)
                             {
                                 cpmFound = true;
                                 firstDirectorySector86 = 16;
@@ -506,7 +506,7 @@ namespace DiscImageChef.Filesystems.CPM
                         case FormatByte.k360:
                         case FormatByte.k360Alt:
                         case FormatByte.k360Alt2:
-                            if(imagePlugin.ImageInfo.SectorSize == 512 && imagePlugin.ImageInfo.Sectors == 720)
+                            if(imagePlugin.Info.SectorSize == 512 && imagePlugin.Info.Sectors == 720)
                             {
                                 cpmFound = true;
                                 firstDirectorySector86 = 36;
@@ -558,7 +558,7 @@ namespace DiscImageChef.Filesystems.CPM
                             break;
                         case FormatByte.k720:
                         case FormatByte.k720Alt:
-                            if(imagePlugin.ImageInfo.SectorSize == 512 && imagePlugin.ImageInfo.Sectors == 1440)
+                            if(imagePlugin.Info.SectorSize == 512 && imagePlugin.Info.Sectors == 1440)
                             {
                                 cpmFound = true;
                                 firstDirectorySector86 = 36;
@@ -609,7 +609,7 @@ namespace DiscImageChef.Filesystems.CPM
 
                             break;
                         case FormatByte.f720:
-                            if(imagePlugin.ImageInfo.SectorSize == 512 && imagePlugin.ImageInfo.Sectors == 1440)
+                            if(imagePlugin.Info.SectorSize == 512 && imagePlugin.Info.Sectors == 1440)
                             {
                                 cpmFound = true;
                                 firstDirectorySector86 = 18;
@@ -660,7 +660,7 @@ namespace DiscImageChef.Filesystems.CPM
 
                             break;
                         case FormatByte.f1200:
-                            if(imagePlugin.ImageInfo.SectorSize == 512 && imagePlugin.ImageInfo.Sectors == 2400)
+                            if(imagePlugin.Info.SectorSize == 512 && imagePlugin.Info.Sectors == 2400)
                             {
                                 cpmFound = true;
                                 firstDirectorySector86 = 30;
@@ -711,7 +711,7 @@ namespace DiscImageChef.Filesystems.CPM
 
                             break;
                         case FormatByte.f1440:
-                            if(imagePlugin.ImageInfo.SectorSize == 512 && imagePlugin.ImageInfo.Sectors == 2880)
+                            if(imagePlugin.Info.SectorSize == 512 && imagePlugin.Info.Sectors == 2880)
                             {
                                 cpmFound = true;
                                 firstDirectorySector86 = 36;
@@ -765,7 +765,7 @@ namespace DiscImageChef.Filesystems.CPM
 
                     if(cpmFound)
                     {
-                        uint directoryLength = (uint)(((ulong)dpb.drm + 1) * 32 / imagePlugin.ImageInfo.SectorSize);
+                        uint directoryLength = (uint)(((ulong)dpb.drm + 1) * 32 / imagePlugin.Info.SectorSize);
                         directory = imagePlugin.ReadSectors(firstDirectorySector86 + partition.Start, directoryLength);
                         DicConsole.DebugWriteLine("CP/M Plugin", "Found CP/M-86 floppy identifier.");
                     }
@@ -794,8 +794,8 @@ namespace DiscImageChef.Filesystems.CPM
                         foreach(CpmDefinition def in from def in definitions.definitions
                                                      let sectors =
                                                          (ulong)(def.cylinders * def.sides * def.sectorsPerTrack)
-                                                     where sectors == imagePlugin.ImageInfo.Sectors &&
-                                                           def.bytesPerSector == imagePlugin.ImageInfo.SectorSize
+                                                     where sectors == imagePlugin.Info.Sectors &&
+                                                           def.bytesPerSector == imagePlugin.Info.SectorSize
                                                      select def)
                         {
                             // Definition seems to describe current disk, at least, same number of volume sectors and bytes per sector
@@ -976,8 +976,9 @@ namespace DiscImageChef.Filesystems.CPM
             }
         }
 
-        public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information)
+        public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding)
         {
+            currentEncoding = encoding ?? Encoding.GetEncoding("IBM437");
             information = "";
             // As the identification is so complex, just call Identify() and relay on its findings
             if(!Identify(imagePlugin, partition) || !cpmFound || workingDefinition == null || dpb == null) return;
@@ -1050,23 +1051,23 @@ namespace DiscImageChef.Filesystems.CPM
             if(labelUpdateDate != null)
                 sb.AppendFormat("Volume updated on {0}", DateHandlers.CpmToDateTime(labelUpdateDate)).AppendLine();
 
-            XmlFsType = new FileSystemType();
-            XmlFsType.Bootable |= workingDefinition.sofs > 0 || workingDefinition.ofs > 0;
-            XmlFsType.ClusterSize = 128 << dpb.bsh;
-            if(dpb.dsm > 0) XmlFsType.Clusters = dpb.dsm;
-            else XmlFsType.Clusters = (long)(partition.End - partition.Start);
+            xmlFsType = new FileSystemType();
+            xmlFsType.Bootable |= workingDefinition.sofs > 0 || workingDefinition.ofs > 0;
+            xmlFsType.ClusterSize = 128 << dpb.bsh;
+            if(dpb.dsm > 0) xmlFsType.Clusters = dpb.dsm;
+            else xmlFsType.Clusters = (long)(partition.End - partition.Start);
             if(labelCreationDate != null)
             {
-                XmlFsType.CreationDate = DateHandlers.CpmToDateTime(labelCreationDate);
-                XmlFsType.CreationDateSpecified = true;
+                xmlFsType.CreationDate = DateHandlers.CpmToDateTime(labelCreationDate);
+                xmlFsType.CreationDateSpecified = true;
             }
             if(labelUpdateDate != null)
             {
-                XmlFsType.ModificationDate = DateHandlers.CpmToDateTime(labelUpdateDate);
-                XmlFsType.ModificationDateSpecified = true;
+                xmlFsType.ModificationDate = DateHandlers.CpmToDateTime(labelUpdateDate);
+                xmlFsType.ModificationDateSpecified = true;
             }
-            XmlFsType.Type = "CP/M";
-            XmlFsType.VolumeName = label;
+            xmlFsType.Type = "CP/M";
+            xmlFsType.VolumeName = label;
 
             information = sb.ToString();
         }
diff --git a/DiscImageChef.Filesystems/CPM/Super.cs b/DiscImageChef.Filesystems/CPM/Super.cs
index 466de378..3db88b9c 100644
--- a/DiscImageChef.Filesystems/CPM/Super.cs
+++ b/DiscImageChef.Filesystems/CPM/Super.cs
@@ -38,20 +38,21 @@ using System.IO;
 using System.Linq;
 using System.Runtime.InteropServices;
 using System.Text;
+using DiscImageChef.CommonTypes;
 using DiscImageChef.Console;
+using DiscImageChef.DiscImages;
 using Schemas;
 
 namespace DiscImageChef.Filesystems.CPM
 {
     partial class CPM
     {
-        public override Errno Mount()
+        public virtual Errno Mount(IMediaImage imagePlugin, Partition partition1, Encoding encoding, bool debug)
         {
-            return Mount(false);
-        }
+            device = imagePlugin;
+            this.partition = partition;
+            currentEncoding = encoding ?? Encoding.GetEncoding("IBM437");
 
-        public override Errno Mount(bool debug)
-        {
             // As the identification is so complex, just call Identify() and relay on its findings
             if(!Identify(device, partition) || !cpmFound || workingDefinition == null || dpb == null)
                 return Errno.InvalidArgument;
@@ -651,11 +652,11 @@ namespace DiscImageChef.Filesystems.CPM
             cpmStat.FilenameLength = 11;
             cpmStat.Files = (ulong)fileCache.Count;
             cpmStat.FreeBlocks = cpmStat.Blocks - usedBlocks;
-            cpmStat.PluginId = PluginUuid;
+            cpmStat.PluginId = Id;
             cpmStat.Type = "CP/M filesystem";
 
             // Generate XML info
-            XmlFsType = new FileSystemType
+            xmlFsType = new FileSystemType
             {
                 Clusters = cpmStat.Blocks,
                 ClusterSize = blockSize,
@@ -667,15 +668,15 @@ namespace DiscImageChef.Filesystems.CPM
             };
             if(labelCreationDate != null)
             {
-                XmlFsType.CreationDate = DateHandlers.CpmToDateTime(labelCreationDate);
-                XmlFsType.CreationDateSpecified = true;
+                xmlFsType.CreationDate = DateHandlers.CpmToDateTime(labelCreationDate);
+                xmlFsType.CreationDateSpecified = true;
             }
             if(labelUpdateDate != null)
             {
-                XmlFsType.ModificationDate = DateHandlers.CpmToDateTime(labelUpdateDate);
-                XmlFsType.ModificationDateSpecified = true;
+                xmlFsType.ModificationDate = DateHandlers.CpmToDateTime(labelUpdateDate);
+                xmlFsType.ModificationDateSpecified = true;
             }
-            if(!string.IsNullOrEmpty(label)) XmlFsType.VolumeName = label;
+            if(!string.IsNullOrEmpty(label)) xmlFsType.VolumeName = label;
 
             mounted = true;
             return Errno.NoError;
@@ -685,7 +686,7 @@ namespace DiscImageChef.Filesystems.CPM
         ///     Gets information about the mounted volume.
         /// 
/// Information about the mounted volume. - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno StatFs(ref FileSystemInfo stat) { if(!mounted) return Errno.AccessDenied; @@ -694,7 +695,7 @@ namespace DiscImageChef.Filesystems.CPM return Errno.NoError; } - public override Errno Unmount() + public virtual Errno Unmount() { mounted = false; definitions = null; diff --git a/DiscImageChef.Filesystems/CPM/Xattr.cs b/DiscImageChef.Filesystems/CPM/Xattr.cs index 0e8440d1..be6cd4d1 100644 --- a/DiscImageChef.Filesystems/CPM/Xattr.cs +++ b/DiscImageChef.Filesystems/CPM/Xattr.cs @@ -44,7 +44,7 @@ namespace DiscImageChef.Filesystems.CPM /// File path. /// Extendad attribute, alternate data stream or fork name. /// Buffer. - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { if(!mounted) return Errno.AccessDenied; @@ -70,7 +70,7 @@ namespace DiscImageChef.Filesystems.CPM /// Error number. /// Path. /// List of extended attributes, alternate data streams and forks. - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno ListXAttr(string path, ref List xattrs) { if(!mounted) return Errno.AccessDenied; diff --git a/DiscImageChef.Filesystems/Cram.cs b/DiscImageChef.Filesystems/Cram.cs index 44d9a1a4..c220478e 100644 --- a/DiscImageChef.Filesystems/Cram.cs +++ b/DiscImageChef.Filesystems/Cram.cs @@ -40,36 +40,22 @@ using Schemas; namespace DiscImageChef.Filesystems { - public class Cram : Filesystem + public class Cram : IFilesystem { /// /// Identifier for Cram /// const uint CRAM_MAGIC = 0x28CD3D45; const uint CRAM_CIGAM = 0x453DCD28; + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public Cram() - { - Name = "Cram filesystem"; - PluginUuid = new Guid("F8F6E46F-7A2A-48E3-9C0A-46AF4DC29E09"); - CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); - } + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "Cram filesystem"; + public virtual Guid Id => new Guid("F8F6E46F-7A2A-48E3-9C0A-46AF4DC29E09"); - public Cram(Encoding encoding) - { - Name = "Cram filesystem"; - PluginUuid = new Guid("F8F6E46F-7A2A-48E3-9C0A-46AF4DC29E09"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } - - public Cram(ImagePlugin imagePlugin, Partition partition, Encoding encoding) - { - Name = "Cram filesystem"; - PluginUuid = new Guid("F8F6E46F-7A2A-48E3-9C0A-46AF4DC29E09"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { if(partition.Start >= partition.End) return false; @@ -80,8 +66,9 @@ namespace DiscImageChef.Filesystems return magic == CRAM_MAGIC || magic == CRAM_CIGAM; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { + currentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); byte[] sector = imagePlugin.ReadSector(partition.Start); uint magic = BitConverter.ToUInt32(sector, 0x00); @@ -107,7 +94,7 @@ namespace DiscImageChef.Filesystems sbInformation.AppendLine("Cram file system"); sbInformation.AppendLine(littleEndian ? "Little-endian" : "Big-endian"); sbInformation.AppendFormat("Volume edition {0}", crSb.edition).AppendLine(); - sbInformation.AppendFormat("Volume name: {0}", StringHandlers.CToString(crSb.name, CurrentEncoding)) + sbInformation.AppendFormat("Volume name: {0}", StringHandlers.CToString(crSb.name, currentEncoding)) .AppendLine(); sbInformation.AppendFormat("Volume has {0} bytes", crSb.size).AppendLine(); sbInformation.AppendFormat("Volume has {0} blocks", crSb.blocks).AppendLine(); @@ -115,9 +102,9 @@ namespace DiscImageChef.Filesystems information = sbInformation.ToString(); - XmlFsType = new FileSystemType + xmlFsType = new FileSystemType { - VolumeName = StringHandlers.CToString(crSb.name, CurrentEncoding), + VolumeName = StringHandlers.CToString(crSb.name, currentEncoding), Type = "Cram file system", Clusters = crSb.blocks, Files = crSb.files, @@ -127,62 +114,57 @@ namespace DiscImageChef.Filesystems }; } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/DiscImageChef.Filesystems.csproj b/DiscImageChef.Filesystems/DiscImageChef.Filesystems.csproj index 355ae0a4..37d8112c 100644 --- a/DiscImageChef.Filesystems/DiscImageChef.Filesystems.csproj +++ b/DiscImageChef.Filesystems/DiscImageChef.Filesystems.csproj @@ -53,7 +53,7 @@ - + diff --git a/DiscImageChef.Filesystems/ECMA67.cs b/DiscImageChef.Filesystems/ECMA67.cs index aae0b90b..2a3703be 100644 --- a/DiscImageChef.Filesystems/ECMA67.cs +++ b/DiscImageChef.Filesystems/ECMA67.cs @@ -41,32 +41,18 @@ using Schemas; namespace DiscImageChef.Filesystems { - public class ECMA67 : Filesystem + public class ECMA67 : IFilesystem { readonly byte[] ECMA67_Magic = {0x56, 0x4F, 0x4C}; - public ECMA67() - { - Name = "ECMA-67"; - PluginUuid = new Guid("62A2D44A-CBC1-4377-B4B6-28C5C92034A1"); - CurrentEncoding = Encoding.GetEncoding("iso-8859-1"); - } + Encoding currentEncoding; + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "ECMA-67"; + public virtual Guid Id => new Guid("62A2D44A-CBC1-4377-B4B6-28C5C92034A1"); + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public ECMA67(Encoding encoding) - { - Name = "ECMA-67"; - PluginUuid = new Guid("62A2D44A-CBC1-4377-B4B6-28C5C92034A1"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1"); - } - - public ECMA67(ImagePlugin imagePlugin, Partition partition, Encoding encoding) - { - Name = "ECMA-67"; - PluginUuid = new Guid("62A2D44A-CBC1-4377-B4B6-28C5C92034A1"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1"); - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { if(partition.Start > 0) return false; @@ -85,8 +71,10 @@ namespace DiscImageChef.Filesystems return ECMA67_Magic.SequenceEqual(vol.labelIdentifier) && vol.labelNumber == 1 && vol.recordLength == 0x31; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, + Encoding encoding) { + currentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1"); byte[] sector = imagePlugin.ReadSector(6); StringBuilder sbInformation = new StringBuilder(); @@ -102,7 +90,7 @@ namespace DiscImageChef.Filesystems sbInformation.AppendFormat("Volume name: {0}", Encoding.ASCII.GetString(vol.volumeIdentifier)).AppendLine(); sbInformation.AppendFormat("Volume owner: {0}", Encoding.ASCII.GetString(vol.owner)).AppendLine(); - XmlFsType = new FileSystemType + xmlFsType = new FileSystemType { Type = "ECMA-67", ClusterSize = 256, @@ -113,62 +101,57 @@ namespace DiscImageChef.Filesystems information = sbInformation.ToString(); } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/EFS.cs b/DiscImageChef.Filesystems/EFS.cs index 7c5645d7..6a0b81e6 100644 --- a/DiscImageChef.Filesystems/EFS.cs +++ b/DiscImageChef.Filesystems/EFS.cs @@ -42,43 +42,29 @@ using Schemas; namespace DiscImageChef.Filesystems { - public class EFS : Filesystem + public class EFS : IFilesystem { const uint EFS_MAGIC = 0x00072959; const uint EFS_MAGIC_NEW = 0x0007295A; + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public EFS() - { - Name = "Extent File System Plugin"; - PluginUuid = new Guid("52A43F90-9AF3-4391-ADFE-65598DEEABAB"); - CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); - } + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "Extent File System Plugin"; + public virtual Guid Id => new Guid("52A43F90-9AF3-4391-ADFE-65598DEEABAB"); - public EFS(Encoding encoding) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { - Name = "Extent File System Plugin"; - PluginUuid = new Guid("52A43F90-9AF3-4391-ADFE-65598DEEABAB"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } - - public EFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) - { - Name = "Extent File System Plugin"; - PluginUuid = new Guid("52A43F90-9AF3-4391-ADFE-65598DEEABAB"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) - { - if(imagePlugin.ImageInfo.SectorSize < 512) return false; + if(imagePlugin.Info.SectorSize < 512) return false; // Misaligned - if(imagePlugin.ImageInfo.XmlMediaType == XmlMediaType.OpticalDisc) + if(imagePlugin.Info.XmlMediaType == XmlMediaType.OpticalDisc) { EFS_Superblock efsSb = new EFS_Superblock(); - uint sbSize = (uint)((Marshal.SizeOf(efsSb) + 0x200) / imagePlugin.ImageInfo.SectorSize); - if((Marshal.SizeOf(efsSb) + 0x200) % imagePlugin.ImageInfo.SectorSize != 0) sbSize++; + uint sbSize = (uint)((Marshal.SizeOf(efsSb) + 0x200) / imagePlugin.Info.SectorSize); + if((Marshal.SizeOf(efsSb) + 0x200) % imagePlugin.Info.SectorSize != 0) sbSize++; byte[] sector = imagePlugin.ReadSectors(partition.Start, sbSize); if(sector.Length < Marshal.SizeOf(efsSb)) return false; @@ -98,8 +84,8 @@ namespace DiscImageChef.Filesystems { EFS_Superblock efsSb = new EFS_Superblock(); - uint sbSize = (uint)(Marshal.SizeOf(efsSb) / imagePlugin.ImageInfo.SectorSize); - if(Marshal.SizeOf(efsSb) % imagePlugin.ImageInfo.SectorSize != 0) sbSize++; + uint sbSize = (uint)(Marshal.SizeOf(efsSb) / imagePlugin.Info.SectorSize); + if(Marshal.SizeOf(efsSb) % imagePlugin.Info.SectorSize != 0) sbSize++; byte[] sector = imagePlugin.ReadSectors(partition.Start + 1, sbSize); if(sector.Length < Marshal.SizeOf(efsSb)) return false; @@ -115,18 +101,19 @@ namespace DiscImageChef.Filesystems return false; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { + currentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); information = ""; - if(imagePlugin.ImageInfo.SectorSize < 512) return; + if(imagePlugin.Info.SectorSize < 512) return; EFS_Superblock efsSb = new EFS_Superblock(); // Misaligned - if(imagePlugin.ImageInfo.XmlMediaType == XmlMediaType.OpticalDisc) + if(imagePlugin.Info.XmlMediaType == XmlMediaType.OpticalDisc) { - uint sbSize = (uint)((Marshal.SizeOf(efsSb) + 0x400) / imagePlugin.ImageInfo.SectorSize); - if((Marshal.SizeOf(efsSb) + 0x400) % imagePlugin.ImageInfo.SectorSize != 0) sbSize++; + uint sbSize = (uint)((Marshal.SizeOf(efsSb) + 0x400) / imagePlugin.Info.SectorSize); + if((Marshal.SizeOf(efsSb) + 0x400) % imagePlugin.Info.SectorSize != 0) sbSize++; byte[] sector = imagePlugin.ReadSectors(partition.Start, sbSize); if(sector.Length < Marshal.SizeOf(efsSb)) return; @@ -142,8 +129,8 @@ namespace DiscImageChef.Filesystems } else { - uint sbSize = (uint)(Marshal.SizeOf(efsSb) / imagePlugin.ImageInfo.SectorSize); - if(Marshal.SizeOf(efsSb) % imagePlugin.ImageInfo.SectorSize != 0) sbSize++; + uint sbSize = (uint)(Marshal.SizeOf(efsSb) / imagePlugin.Info.SectorSize); + if(Marshal.SizeOf(efsSb) % imagePlugin.Info.SectorSize != 0) sbSize++; byte[] sector = imagePlugin.ReadSectors(partition.Start + 1, sbSize); if(sector.Length < Marshal.SizeOf(efsSb)) return; @@ -177,12 +164,12 @@ namespace DiscImageChef.Filesystems if(efsSb.sb_lastinode > 0) sb.AppendFormat("Last inode allocated: {0}", efsSb.sb_lastinode).AppendLine(); if(efsSb.sb_dirty > 0) sb.AppendLine("Volume is dirty"); sb.AppendFormat("Checksum: 0x{0:X8}", efsSb.sb_checksum).AppendLine(); - sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(efsSb.sb_fname, CurrentEncoding)).AppendLine(); - sb.AppendFormat("Volume pack: {0}", StringHandlers.CToString(efsSb.sb_fpack, CurrentEncoding)).AppendLine(); + sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(efsSb.sb_fname, currentEncoding)).AppendLine(); + sb.AppendFormat("Volume pack: {0}", StringHandlers.CToString(efsSb.sb_fpack, currentEncoding)).AppendLine(); information = sb.ToString(); - XmlFsType = new FileSystemType + xmlFsType = new FileSystemType { Type = "Extent File System", ClusterSize = 512, @@ -190,69 +177,64 @@ namespace DiscImageChef.Filesystems FreeClusters = efsSb.sb_tfree, FreeClustersSpecified = true, Dirty = efsSb.sb_dirty > 0, - VolumeName = StringHandlers.CToString(efsSb.sb_fname, CurrentEncoding), + VolumeName = StringHandlers.CToString(efsSb.sb_fname, currentEncoding), VolumeSerial = $"{efsSb.sb_checksum:X8}", CreationDate = DateHandlers.UnixToDateTime(efsSb.sb_time), CreationDateSpecified = true }; } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/F2FS.cs b/DiscImageChef.Filesystems/F2FS.cs index 5444181a..80644877 100644 --- a/DiscImageChef.Filesystems/F2FS.cs +++ b/DiscImageChef.Filesystems/F2FS.cs @@ -41,7 +41,7 @@ using Schemas; namespace DiscImageChef.Filesystems { - public class F2FS : Filesystem + public class F2FS : IFilesystem { const uint F2FS_MAGIC = 0xF2F52010; const uint F2FS_SUPER_OFFSET = 1024; @@ -49,39 +49,26 @@ namespace DiscImageChef.Filesystems const uint F2FS_MAX_SECTOR = 4096; const uint F2FS_BLOCK_SIZE = 4096; - public F2FS() - { - Name = "F2FS Plugin"; - PluginUuid = new Guid("82B0920F-5F0D-4063-9F57-ADE0AE02ECE5"); - CurrentEncoding = Encoding.Unicode; - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public F2FS(Encoding encoding) - { - Name = "F2FS Plugin"; - PluginUuid = new Guid("82B0920F-5F0D-4063-9F57-ADE0AE02ECE5"); - CurrentEncoding = Encoding.Unicode; - } + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "F2FS Plugin"; + public virtual Guid Id => new Guid("82B0920F-5F0D-4063-9F57-ADE0AE02ECE5"); - public F2FS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { - Name = "F2FS Plugin"; - PluginUuid = new Guid("82B0920F-5F0D-4063-9F57-ADE0AE02ECE5"); - CurrentEncoding = Encoding.Unicode; - } + if(imagePlugin.Info.SectorSize < F2FS_MIN_SECTOR || imagePlugin.Info.SectorSize > F2FS_MAX_SECTOR) + return false; - public override bool Identify(ImagePlugin imagePlugin, Partition partition) - { - if(imagePlugin.ImageInfo.SectorSize < F2FS_MIN_SECTOR || - imagePlugin.ImageInfo.SectorSize > F2FS_MAX_SECTOR) return false; - - uint sbAddr = F2FS_SUPER_OFFSET / imagePlugin.ImageInfo.SectorSize; + uint sbAddr = F2FS_SUPER_OFFSET / imagePlugin.Info.SectorSize; if(sbAddr == 0) sbAddr = 1; F2FS_Superblock f2fsSb = new F2FS_Superblock(); - uint sbSize = (uint)(Marshal.SizeOf(f2fsSb) / imagePlugin.ImageInfo.SectorSize); - if(Marshal.SizeOf(f2fsSb) % imagePlugin.ImageInfo.SectorSize != 0) sbSize++; + uint sbSize = (uint)(Marshal.SizeOf(f2fsSb) / imagePlugin.Info.SectorSize); + if(Marshal.SizeOf(f2fsSb) % imagePlugin.Info.SectorSize != 0) sbSize++; if(partition.Start + sbAddr >= partition.End) return false; @@ -96,19 +83,20 @@ namespace DiscImageChef.Filesystems return f2fsSb.magic == F2FS_MAGIC; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, + Encoding encoding) { + currentEncoding = Encoding.Unicode; information = ""; - if(imagePlugin.ImageInfo.SectorSize < F2FS_MIN_SECTOR || - imagePlugin.ImageInfo.SectorSize > F2FS_MAX_SECTOR) return; + if(imagePlugin.Info.SectorSize < F2FS_MIN_SECTOR || imagePlugin.Info.SectorSize > F2FS_MAX_SECTOR) return; - uint sbAddr = F2FS_SUPER_OFFSET / imagePlugin.ImageInfo.SectorSize; + uint sbAddr = F2FS_SUPER_OFFSET / imagePlugin.Info.SectorSize; if(sbAddr == 0) sbAddr = 1; F2FS_Superblock f2fsSb = new F2FS_Superblock(); - uint sbSize = (uint)(Marshal.SizeOf(f2fsSb) / imagePlugin.ImageInfo.SectorSize); - if(Marshal.SizeOf(f2fsSb) % imagePlugin.ImageInfo.SectorSize != 0) sbSize++; + uint sbSize = (uint)(Marshal.SizeOf(f2fsSb) / imagePlugin.Info.SectorSize); + if(Marshal.SizeOf(f2fsSb) % imagePlugin.Info.SectorSize != 0) sbSize++; byte[] sector = imagePlugin.ReadSectors(partition.Start + sbAddr, sbSize); if(sector.Length < Marshal.SizeOf(f2fsSb)) return; @@ -144,7 +132,7 @@ namespace DiscImageChef.Filesystems information = sb.ToString(); - XmlFsType = new FileSystemType + xmlFsType = new FileSystemType { Type = "F2FS filesystem", SystemIdentifier = Encoding.ASCII.GetString(f2fsSb.version), @@ -156,62 +144,57 @@ namespace DiscImageChef.Filesystems }; } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/FAT.cs b/DiscImageChef.Filesystems/FAT.cs index 7910972b..8e3bf875 100644 --- a/DiscImageChef.Filesystems/FAT.cs +++ b/DiscImageChef.Filesystems/FAT.cs @@ -47,34 +47,21 @@ namespace DiscImageChef.Filesystems { // TODO: Differentiate between Atari and X68k FAT, as this one uses a standard BPB. // X68K uses cdate/adate from direntry for extending filename - public class FAT : Filesystem + public class FAT : IFilesystem { const uint FSINFO_SIGNATURE1 = 0x41615252; const uint FSINFO_SIGNATURE2 = 0x61417272; const uint FSINFO_SIGNATURE3 = 0xAA550000; - public FAT() - { - Name = "Microsoft File Allocation Table"; - PluginUuid = new Guid("33513B2C-0D26-0D2D-32C3-79D8611158E0"); - CurrentEncoding = Encoding.GetEncoding("IBM437"); - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public FAT(Encoding encoding) - { - Name = "Microsoft File Allocation Table"; - PluginUuid = new Guid("33513B2C-0D26-0D2D-32C3-79D8611158E0"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("IBM437"); - } + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "Microsoft File Allocation Table"; + public virtual Guid Id => new Guid("33513B2C-0D26-0D2D-32C3-79D8611158E0"); - public FAT(ImagePlugin imagePlugin, Partition partition, Encoding encoding) - { - Name = "Microsoft File Allocation Table"; - PluginUuid = new Guid("33513B2C-0D26-0D2D-32C3-79D8611158E0"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("IBM437"); - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { if(2 + partition.Start >= partition.End) return false; @@ -118,7 +105,7 @@ namespace DiscImageChef.Filesystems hugeSectors = BitConverter.ToUInt64(bpbSector, 0x052); fatId = fatSector[0]; int bitsInBps = CountBits.Count(bps); - if(imagePlugin.ImageInfo.SectorSize >= 512) bootable = BitConverter.ToUInt16(bpbSector, 0x1FE); + if(imagePlugin.Info.SectorSize >= 512) bootable = BitConverter.ToUInt16(bpbSector, 0x1FE); bool correctSpc = spc == 1 || spc == 2 || spc == 4 || spc == 8 || spc == 16 || spc == 32 || spc == 64; string msxString = Encoding.ASCII.GetString(msxId); @@ -174,7 +161,7 @@ namespace DiscImageChef.Filesystems DicConsole.DebugWriteLine("FAT plugin", "apricot_fat_sectors = {0}", apricotFatSectors); // This is to support FAT partitions on hybrid ISO/USB images - if(imagePlugin.ImageInfo.XmlMediaType == XmlMediaType.OpticalDisc) + if(imagePlugin.Info.XmlMediaType == XmlMediaType.OpticalDisc) { sectors /= 4; bigSectors /= 4; @@ -242,7 +229,7 @@ namespace DiscImageChef.Filesystems if(partition.Start != 0) return false; // DEC Rainbow, lacks a BPB but has a very concrete structure... - if(imagePlugin.ImageInfo.Sectors == 800 && imagePlugin.ImageInfo.SectorSize == 512) + if(imagePlugin.Info.Sectors == 800 && imagePlugin.Info.SectorSize == 512) { // DEC Rainbow boots up with a Z80, first byte should be DI (disable interrupts) byte z80Di = bpbSector[0]; @@ -289,32 +276,22 @@ namespace DiscImageChef.Filesystems switch(fatId) { case 0xE5: - if(imagePlugin.ImageInfo.Sectors == 2002 && imagePlugin.ImageInfo.SectorSize == 128) - fat2SectorNo = 2; + if(imagePlugin.Info.Sectors == 2002 && imagePlugin.Info.SectorSize == 128) fat2SectorNo = 2; break; case 0xFD: - if(imagePlugin.ImageInfo.Sectors == 4004 && imagePlugin.ImageInfo.SectorSize == 128) - fat2SectorNo = 7; - else if(imagePlugin.ImageInfo.Sectors == 2002 && imagePlugin.ImageInfo.SectorSize == 128) - fat2SectorNo = 7; + if(imagePlugin.Info.Sectors == 4004 && imagePlugin.Info.SectorSize == 128) fat2SectorNo = 7; + else if(imagePlugin.Info.Sectors == 2002 && imagePlugin.Info.SectorSize == 128) fat2SectorNo = 7; break; case 0xFE: - if(imagePlugin.ImageInfo.Sectors == 320 && imagePlugin.ImageInfo.SectorSize == 512) - fat2SectorNo = 2; - else if(imagePlugin.ImageInfo.Sectors == 2002 && imagePlugin.ImageInfo.SectorSize == 128) - fat2SectorNo = 7; - else if(imagePlugin.ImageInfo.Sectors == 1232 && imagePlugin.ImageInfo.SectorSize == 1024) - fat2SectorNo = 3; - else if(imagePlugin.ImageInfo.Sectors == 616 && imagePlugin.ImageInfo.SectorSize == 1024) - fat2SectorNo = 2; - else if(imagePlugin.ImageInfo.Sectors == 720 && imagePlugin.ImageInfo.SectorSize == 128) - fat2SectorNo = 5; - else if(imagePlugin.ImageInfo.Sectors == 640 && imagePlugin.ImageInfo.SectorSize == 512) - fat2SectorNo = 2; + if(imagePlugin.Info.Sectors == 320 && imagePlugin.Info.SectorSize == 512) fat2SectorNo = 2; + else if(imagePlugin.Info.Sectors == 2002 && imagePlugin.Info.SectorSize == 128) fat2SectorNo = 7; + else if(imagePlugin.Info.Sectors == 1232 && imagePlugin.Info.SectorSize == 1024) fat2SectorNo = 3; + else if(imagePlugin.Info.Sectors == 616 && imagePlugin.Info.SectorSize == 1024) fat2SectorNo = 2; + else if(imagePlugin.Info.Sectors == 720 && imagePlugin.Info.SectorSize == 128) fat2SectorNo = 5; + else if(imagePlugin.Info.Sectors == 640 && imagePlugin.Info.SectorSize == 512) fat2SectorNo = 2; break; case 0xFF: - if(imagePlugin.ImageInfo.Sectors == 640 && imagePlugin.ImageInfo.SectorSize == 512) - fat2SectorNo = 2; + if(imagePlugin.Info.Sectors == 640 && imagePlugin.Info.SectorSize == 512) fat2SectorNo = 2; break; default: if(fatId < 0xE8) return false; @@ -337,12 +314,13 @@ namespace DiscImageChef.Filesystems return fatId == fat2Sector[0]; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { + currentEncoding = encoding ?? Encoding.GetEncoding("IBM437"); information = ""; StringBuilder sb = new StringBuilder(); - XmlFsType = new FileSystemType(); + xmlFsType = new FileSystemType(); bool useAtariBpb = false; bool useMsxBpb = false; @@ -372,7 +350,7 @@ namespace DiscImageChef.Filesystems byte[] bpbSector = imagePlugin.ReadSectors(partition.Start, 2); - if(imagePlugin.ImageInfo.SectorSize >= 256) + if(imagePlugin.Info.SectorSize >= 256) { IntPtr bpbPtr = Marshal.AllocHGlobal(512); Marshal.Copy(bpbSector, 0, bpbPtr, 512); @@ -439,7 +417,7 @@ namespace DiscImageChef.Filesystems apricotBpb.mainBPB.spc == 64; // This is to support FAT partitions on hybrid ISO/USB images - if(imagePlugin.ImageInfo.XmlMediaType == XmlMediaType.OpticalDisc) + if(imagePlugin.Info.XmlMediaType == XmlMediaType.OpticalDisc) { atariBpb.sectors /= 4; msxBpb.sectors /= 4; @@ -598,9 +576,9 @@ namespace DiscImageChef.Filesystems uint sectorsForRootDirectory = 0; // DEC Rainbow, lacks a BPB but has a very concrete structure... - if(imagePlugin.ImageInfo.Sectors == 800 && imagePlugin.ImageInfo.SectorSize == 512 && !useAtariBpb && - !useMsxBpb && !useDos2Bpb && !useDos3Bpb && !useDos32Bpb && !useDos33Bpb && !userShortExtendedBpb && - !useExtendedBpb && !useShortFat32 && !useLongFat32 && !useApricotBpb) + if(imagePlugin.Info.Sectors == 800 && imagePlugin.Info.SectorSize == 512 && !useAtariBpb && !useMsxBpb && + !useDos2Bpb && !useDos3Bpb && !useDos32Bpb && !useDos33Bpb && !userShortExtendedBpb && !useExtendedBpb && + !useShortFat32 && !useLongFat32 && !useApricotBpb) { // DEC Rainbow boots up with a Z80, first byte should be DI (disable interrupts) byte z80Di = bpbSector[0]; @@ -647,7 +625,7 @@ namespace DiscImageChef.Filesystems fakeBpb.heads = 1; fakeBpb.hsectors = 0; fakeBpb.spfat = 3; - XmlFsType.Bootable = true; + xmlFsType.Bootable = true; fakeBpb.boot_code = bpbSector; isFat12 = true; } @@ -662,7 +640,7 @@ namespace DiscImageChef.Filesystems switch(fatSector[0]) { case 0xE5: - if(imagePlugin.ImageInfo.Sectors == 2002 && imagePlugin.ImageInfo.SectorSize == 128) + if(imagePlugin.Info.Sectors == 2002 && imagePlugin.Info.SectorSize == 128) { DicConsole.DebugWriteLine("FAT plugin", "Using hardcoded BPB."); fakeBpb.bps = 128; @@ -679,7 +657,7 @@ namespace DiscImageChef.Filesystems } break; case 0xFD: - if(imagePlugin.ImageInfo.Sectors == 4004 && imagePlugin.ImageInfo.SectorSize == 128) + if(imagePlugin.Info.Sectors == 4004 && imagePlugin.Info.SectorSize == 128) { DicConsole.DebugWriteLine("FAT plugin", "Using hardcoded BPB."); fakeBpb.bps = 128; @@ -694,7 +672,7 @@ namespace DiscImageChef.Filesystems fakeBpb.hsectors = 0; fakeBpb.spfat = 6; } - else if(imagePlugin.ImageInfo.Sectors == 2002 && imagePlugin.ImageInfo.SectorSize == 128) + else if(imagePlugin.Info.Sectors == 2002 && imagePlugin.Info.SectorSize == 128) { DicConsole.DebugWriteLine("FAT plugin", "Using hardcoded BPB."); fakeBpb.bps = 128; @@ -711,7 +689,7 @@ namespace DiscImageChef.Filesystems } break; case 0xFE: - if(imagePlugin.ImageInfo.Sectors == 320 && imagePlugin.ImageInfo.SectorSize == 512) + if(imagePlugin.Info.Sectors == 320 && imagePlugin.Info.SectorSize == 512) { DicConsole.DebugWriteLine("FAT plugin", "Using hardcoded BPB for 5.25\" SSDD."); fakeBpb.bps = 512; @@ -726,7 +704,7 @@ namespace DiscImageChef.Filesystems fakeBpb.hsectors = 0; fakeBpb.spfat = 1; } - else if(imagePlugin.ImageInfo.Sectors == 2002 && imagePlugin.ImageInfo.SectorSize == 128) + else if(imagePlugin.Info.Sectors == 2002 && imagePlugin.Info.SectorSize == 128) { DicConsole.DebugWriteLine("FAT plugin", "Using hardcoded BPB."); fakeBpb.bps = 128; @@ -741,7 +719,7 @@ namespace DiscImageChef.Filesystems fakeBpb.hsectors = 0; fakeBpb.spfat = 6; } - else if(imagePlugin.ImageInfo.Sectors == 1232 && imagePlugin.ImageInfo.SectorSize == 1024) + else if(imagePlugin.Info.Sectors == 1232 && imagePlugin.Info.SectorSize == 1024) { DicConsole.DebugWriteLine("FAT plugin", "Using hardcoded BPB."); fakeBpb.bps = 1024; @@ -756,7 +734,7 @@ namespace DiscImageChef.Filesystems fakeBpb.hsectors = 0; fakeBpb.spfat = 2; } - else if(imagePlugin.ImageInfo.Sectors == 616 && imagePlugin.ImageInfo.SectorSize == 1024) + else if(imagePlugin.Info.Sectors == 616 && imagePlugin.Info.SectorSize == 1024) { DicConsole.DebugWriteLine("FAT plugin", "Using hardcoded BPB."); fakeBpb.bps = 1024; @@ -770,7 +748,7 @@ namespace DiscImageChef.Filesystems fakeBpb.heads = 2; fakeBpb.hsectors = 0; } - else if(imagePlugin.ImageInfo.Sectors == 720 && imagePlugin.ImageInfo.SectorSize == 128) + else if(imagePlugin.Info.Sectors == 720 && imagePlugin.Info.SectorSize == 128) { DicConsole.DebugWriteLine("FAT plugin", "Using hardcoded BPB."); fakeBpb.bps = 128; @@ -785,7 +763,7 @@ namespace DiscImageChef.Filesystems fakeBpb.hsectors = 0; fakeBpb.spfat = 4; } - else if(imagePlugin.ImageInfo.Sectors == 640 && imagePlugin.ImageInfo.SectorSize == 512) + else if(imagePlugin.Info.Sectors == 640 && imagePlugin.Info.SectorSize == 512) { DicConsole.DebugWriteLine("FAT plugin", "Using hardcoded BPB for 5.25\" DSDD."); fakeBpb.bps = 512; @@ -802,7 +780,7 @@ namespace DiscImageChef.Filesystems } break; case 0xFF: - if(imagePlugin.ImageInfo.Sectors == 640 && imagePlugin.ImageInfo.SectorSize == 512) + if(imagePlugin.Info.Sectors == 640 && imagePlugin.Info.SectorSize == 512) { DicConsole.DebugWriteLine("FAT plugin", "Using hardcoded BPB for 5.25\" DSDD."); fakeBpb.bps = 512; @@ -821,7 +799,7 @@ namespace DiscImageChef.Filesystems } // This assumes a bootable sector will jump somewhere or disable interrupts in x86 code - XmlFsType.Bootable |= bpbSector[0] == 0xFA || bpbSector[0] == 0xEB && bpbSector[1] <= 0x7F; + xmlFsType.Bootable |= bpbSector[0] == 0xFA || bpbSector[0] == 0xEB && bpbSector[1] <= 0x7F; fakeBpb.boot_code = bpbSector; } else if(useShortFat32 || useLongFat32) @@ -829,7 +807,7 @@ namespace DiscImageChef.Filesystems isFat32 = true; // This is to support FAT partitions on hybrid ISO/USB images - if(imagePlugin.ImageInfo.XmlMediaType == XmlMediaType.OpticalDisc) + if(imagePlugin.Info.XmlMediaType == XmlMediaType.OpticalDisc) { fat32Bpb.bps *= 4; fat32Bpb.spc /= 4; @@ -841,38 +819,38 @@ namespace DiscImageChef.Filesystems if(fat32Bpb.version != 0) { sb.AppendLine("FAT+"); - XmlFsType.Type = "FAT+"; + xmlFsType.Type = "FAT+"; } else { sb.AppendLine("Microsoft FAT32"); - XmlFsType.Type = "FAT32"; + xmlFsType.Type = "FAT32"; } if(fat32Bpb.oem_name != null) if(fat32Bpb.oem_name[5] == 0x49 && fat32Bpb.oem_name[6] == 0x48 && fat32Bpb.oem_name[7] == 0x43) sb.AppendLine("Volume has been modified by Windows 9x/Me Volume Tracker."); - else XmlFsType.SystemIdentifier = StringHandlers.CToString(fat32Bpb.oem_name); + else xmlFsType.SystemIdentifier = StringHandlers.CToString(fat32Bpb.oem_name); - if(!string.IsNullOrEmpty(XmlFsType.SystemIdentifier)) - sb.AppendFormat("OEM Name: {0}", XmlFsType.SystemIdentifier.Trim()).AppendLine(); + if(!string.IsNullOrEmpty(xmlFsType.SystemIdentifier)) + sb.AppendFormat("OEM Name: {0}", xmlFsType.SystemIdentifier.Trim()).AppendLine(); sb.AppendFormat("{0} bytes per sector.", fat32Bpb.bps).AppendLine(); sb.AppendFormat("{0} sectors per cluster.", fat32Bpb.spc).AppendLine(); - XmlFsType.ClusterSize = fat32Bpb.bps * fat32Bpb.spc; + xmlFsType.ClusterSize = fat32Bpb.bps * fat32Bpb.spc; sb.AppendFormat("{0} sectors reserved between BPB and FAT.", fat32Bpb.rsectors).AppendLine(); if(fat32Bpb.big_sectors == 0 && fat32Bpb.signature == 0x28) { sb.AppendFormat("{0} sectors on volume ({1} bytes).", shortFat32Bpb.huge_sectors, shortFat32Bpb.huge_sectors * shortFat32Bpb.bps).AppendLine(); - XmlFsType.Clusters = (long)(shortFat32Bpb.huge_sectors / shortFat32Bpb.spc); + xmlFsType.Clusters = (long)(shortFat32Bpb.huge_sectors / shortFat32Bpb.spc); } else { sb.AppendFormat("{0} sectors on volume ({1} bytes).", fat32Bpb.big_sectors, fat32Bpb.big_sectors * fat32Bpb.bps).AppendLine(); - XmlFsType.Clusters = fat32Bpb.big_sectors / fat32Bpb.spc; + xmlFsType.Clusters = fat32Bpb.big_sectors / fat32Bpb.spc; } - sb.AppendFormat("{0} clusters on volume.", XmlFsType.Clusters).AppendLine(); + sb.AppendFormat("{0} clusters on volume.", xmlFsType.Clusters).AppendLine(); sb.AppendFormat("Media descriptor: 0x{0:X2}", fat32Bpb.media).AppendLine(); sb.AppendFormat("{0} sectors per FAT.", fat32Bpb.big_spfat).AppendLine(); sb.AppendFormat("{0} sectors per track.", fat32Bpb.sptrk).AppendLine(); @@ -883,14 +861,14 @@ namespace DiscImageChef.Filesystems sb.AppendFormat("Sector of backup FAT32 parameter block: {0}", fat32Bpb.backup_sector).AppendLine(); sb.AppendFormat("Drive number: 0x{0:X2}", fat32Bpb.drive_no).AppendLine(); sb.AppendFormat("Volume Serial Number: 0x{0:X8}", fat32Bpb.serial_no).AppendLine(); - XmlFsType.VolumeSerial = $"{fat32Bpb.serial_no:X8}"; + xmlFsType.VolumeSerial = $"{fat32Bpb.serial_no:X8}"; if((fat32Bpb.flags & 0xF8) == 0x00) { if((fat32Bpb.flags & 0x01) == 0x01) { sb.AppendLine("Volume should be checked on next mount."); - XmlFsType.Dirty = true; + xmlFsType.Dirty = true; } if((fat32Bpb.flags & 0x02) == 0x02) sb.AppendLine("Disk surface should be on next mount."); } @@ -906,7 +884,7 @@ namespace DiscImageChef.Filesystems if(fat32Bpb.signature == 0x29) { - XmlFsType.VolumeName = Encoding.ASCII.GetString(fat32Bpb.volume_label); + xmlFsType.VolumeName = Encoding.ASCII.GetString(fat32Bpb.volume_label); sb.AppendFormat("Filesystem type: {0}", Encoding.ASCII.GetString(fat32Bpb.fs_type)).AppendLine(); bootChk = sha1Ctx.Data(fat32Bpb.boot_code, out _); } @@ -914,10 +892,10 @@ namespace DiscImageChef.Filesystems // Check that jumps to a correct boot code position and has boot signature set. // This will mean that the volume will boot, even if just to say "this is not bootable change disk"...... - XmlFsType.Bootable |= fat32Bpb.jump[0] == 0xEB && fat32Bpb.jump[1] > 0x58 && fat32Bpb.jump[1] < 0x80 && + xmlFsType.Bootable |= fat32Bpb.jump[0] == 0xEB && fat32Bpb.jump[1] > 0x58 && fat32Bpb.jump[1] < 0x80 && fat32Bpb.boot_signature == 0xAA55; - sectorsPerRealSector = fat32Bpb.bps / imagePlugin.ImageInfo.SectorSize; + sectorsPerRealSector = fat32Bpb.bps / imagePlugin.Info.SectorSize; // First root directory sector rootDirectorySector = (ulong)((fat32Bpb.root_cluster - 2) * fat32Bpb.spc + fat32Bpb.big_spfat * fat32Bpb.fats_no + @@ -938,8 +916,8 @@ namespace DiscImageChef.Filesystems if(fsInfo.free_clusters < 0xFFFFFFFF) { sb.AppendFormat("{0} free clusters", fsInfo.free_clusters).AppendLine(); - XmlFsType.FreeClusters = fsInfo.free_clusters; - XmlFsType.FreeClustersSpecified = true; + xmlFsType.FreeClusters = fsInfo.free_clusters; + xmlFsType.FreeClustersSpecified = true; } if(fsInfo.last_cluster > 2 && fsInfo.last_cluster < 0xFFFFFFFF) @@ -1061,7 +1039,7 @@ namespace DiscImageChef.Filesystems fakeBpb.boot_signature = msxBpb.boot_signature; fakeBpb.serial_no = msxBpb.serial_no; // TODO: Is there any way to check this? - XmlFsType.Bootable = true; + xmlFsType.Bootable = true; } else if(useAtariBpb) { @@ -1086,7 +1064,7 @@ namespace DiscImageChef.Filesystems // TODO: Check this if(sum == 0x1234) { - XmlFsType.Bootable = true; + xmlFsType.Bootable = true; StringBuilder atariSb = new StringBuilder(); atariSb.AppendFormat("cmdload will be loaded with value {0:X4}h", BigEndianBitConverter.ToUInt16(bpbSector, 0x01E)).AppendLine(); @@ -1129,19 +1107,19 @@ namespace DiscImageChef.Filesystems fakeBpb.media = apricotBpb.mainBPB.media; fakeBpb.spfat = apricotBpb.mainBPB.spfat; fakeBpb.sptrk = apricotBpb.spt; - XmlFsType.Bootable = apricotBpb.bootType > 0; + xmlFsType.Bootable = apricotBpb.bootType > 0; if(apricotBpb.bootLocation > 0 && - apricotBpb.bootLocation + apricotBpb.bootSize < imagePlugin.ImageInfo.Sectors) + apricotBpb.bootLocation + apricotBpb.bootSize < imagePlugin.Info.Sectors) fakeBpb.boot_code = imagePlugin.ReadSectors(apricotBpb.bootLocation, (uint)(apricotBpb.sectorSize * apricotBpb.bootSize) / - imagePlugin.ImageInfo.SectorSize); + imagePlugin.Info.SectorSize); } if(!isFat32) { // This is to support FAT partitions on hybrid ISO/USB images - if(imagePlugin.ImageInfo.XmlMediaType == XmlMediaType.OpticalDisc) + if(imagePlugin.Info.XmlMediaType == XmlMediaType.OpticalDisc) { fakeBpb.bps *= 4; fakeBpb.spc /= 4; @@ -1174,12 +1152,12 @@ namespace DiscImageChef.Filesystems if(useAtariBpb) sb.AppendLine("Atari FAT12"); else if(useApricotBpb) sb.AppendLine("Apricot FAT12"); else sb.AppendLine("Microsoft FAT12"); - XmlFsType.Type = "FAT12"; + xmlFsType.Type = "FAT12"; } else if(isFat16) { sb.AppendLine(useAtariBpb ? "Atari FAT16" : "Microsoft FAT16"); - XmlFsType.Type = "FAT16"; + xmlFsType.Type = "FAT16"; } if(useAtariBpb) @@ -1187,11 +1165,11 @@ namespace DiscImageChef.Filesystems if(atariBpb.serial_no[0] == 0x49 && atariBpb.serial_no[1] == 0x48 && atariBpb.serial_no[2] == 0x43) sb.AppendLine("Volume has been modified by Windows 9x/Me Volume Tracker."); else - XmlFsType.VolumeSerial = + xmlFsType.VolumeSerial = $"{atariBpb.serial_no[0]:X2}{atariBpb.serial_no[1]:X2}{atariBpb.serial_no[2]:X2}"; - XmlFsType.SystemIdentifier = StringHandlers.CToString(atariBpb.oem_name); - if(string.IsNullOrEmpty(XmlFsType.SystemIdentifier)) XmlFsType.SystemIdentifier = null; + xmlFsType.SystemIdentifier = StringHandlers.CToString(atariBpb.oem_name); + if(string.IsNullOrEmpty(xmlFsType.SystemIdentifier)) xmlFsType.SystemIdentifier = null; } else if(fakeBpb.oem_name != null) { @@ -1207,7 +1185,7 @@ namespace DiscImageChef.Filesystems fakeBpb.oem_name[4] <= 0x7F && fakeBpb.oem_name[5] >= 0x20 && fakeBpb.oem_name[5] <= 0x7F && fakeBpb.oem_name[6] >= 0x20 && fakeBpb.oem_name[6] <= 0x7F && fakeBpb.oem_name[7] >= 0x20 && fakeBpb.oem_name[7] <= 0x7F) - XmlFsType.SystemIdentifier = StringHandlers.CToString(fakeBpb.oem_name); + xmlFsType.SystemIdentifier = StringHandlers.CToString(fakeBpb.oem_name); else if(fakeBpb.oem_name[0] < 0x20 && fakeBpb.oem_name[1] >= 0x20 && fakeBpb.oem_name[1] <= 0x7F && fakeBpb.oem_name[2] >= 0x20 && fakeBpb.oem_name[2] <= 0x7F && fakeBpb.oem_name[3] >= 0x20 && @@ -1216,33 +1194,33 @@ namespace DiscImageChef.Filesystems fakeBpb.oem_name[5] <= 0x7F && fakeBpb.oem_name[6] >= 0x20 && fakeBpb.oem_name[6] <= 0x7F && fakeBpb.oem_name[7] >= 0x20 && fakeBpb.oem_name[7] <= 0x7F) - XmlFsType.SystemIdentifier = - StringHandlers.CToString(fakeBpb.oem_name, CurrentEncoding, start: 1); + xmlFsType.SystemIdentifier = + StringHandlers.CToString(fakeBpb.oem_name, currentEncoding, start: 1); } if(fakeBpb.signature == 0x28 || fakeBpb.signature == 0x29) - XmlFsType.VolumeSerial = $"{fakeBpb.serial_no:X8}"; + xmlFsType.VolumeSerial = $"{fakeBpb.serial_no:X8}"; } - if(XmlFsType.SystemIdentifier != null) - sb.AppendFormat("OEM Name: {0}", XmlFsType.SystemIdentifier.Trim()).AppendLine(); + if(xmlFsType.SystemIdentifier != null) + sb.AppendFormat("OEM Name: {0}", xmlFsType.SystemIdentifier.Trim()).AppendLine(); sb.AppendFormat("{0} bytes per sector.", fakeBpb.bps).AppendLine(); if(fakeBpb.sectors == 0) { sb.AppendFormat("{0} sectors on volume ({1} bytes).", fakeBpb.big_sectors, fakeBpb.big_sectors * fakeBpb.bps).AppendLine(); - XmlFsType.Clusters = fakeBpb.spc == 0 ? fakeBpb.big_sectors : fakeBpb.big_sectors / fakeBpb.spc; + xmlFsType.Clusters = fakeBpb.spc == 0 ? fakeBpb.big_sectors : fakeBpb.big_sectors / fakeBpb.spc; } else { sb.AppendFormat("{0} sectors on volume ({1} bytes).", fakeBpb.sectors, fakeBpb.sectors * fakeBpb.bps).AppendLine(); - XmlFsType.Clusters = fakeBpb.spc == 0 ? fakeBpb.sectors : fakeBpb.sectors / fakeBpb.spc; + xmlFsType.Clusters = fakeBpb.spc == 0 ? fakeBpb.sectors : fakeBpb.sectors / fakeBpb.spc; } sb.AppendFormat("{0} sectors per cluster.", fakeBpb.spc).AppendLine(); - sb.AppendFormat("{0} clusters on volume.", XmlFsType.Clusters).AppendLine(); - XmlFsType.ClusterSize = fakeBpb.bps * fakeBpb.spc; + sb.AppendFormat("{0} clusters on volume.", xmlFsType.Clusters).AppendLine(); + xmlFsType.ClusterSize = fakeBpb.bps * fakeBpb.spc; sb.AppendFormat("{0} sectors reserved between BPB and FAT.", fakeBpb.rsectors).AppendLine(); sb.AppendFormat("{0} FATs.", fakeBpb.fats_no).AppendLine(); sb.AppendFormat("{0} entries on root directory.", fakeBpb.root_ent).AppendLine(); @@ -1263,47 +1241,47 @@ namespace DiscImageChef.Filesystems { sb.AppendFormat("Drive number: 0x{0:X2}", fakeBpb.drive_no).AppendLine(); - if(XmlFsType.VolumeSerial != null) - sb.AppendFormat("Volume Serial Number: {0}", XmlFsType.VolumeSerial).AppendLine(); + if(xmlFsType.VolumeSerial != null) + sb.AppendFormat("Volume Serial Number: {0}", xmlFsType.VolumeSerial).AppendLine(); if((fakeBpb.flags & 0xF8) == 0x00) { if((fakeBpb.flags & 0x01) == 0x01) { sb.AppendLine("Volume should be checked on next mount."); - XmlFsType.Dirty = true; + xmlFsType.Dirty = true; } if((fakeBpb.flags & 0x02) == 0x02) sb.AppendLine("Disk surface should be on next mount."); } if(fakeBpb.signature == 0x29 || andosOemCorrect) { - XmlFsType.VolumeName = Encoding.ASCII.GetString(fakeBpb.volume_label); + xmlFsType.VolumeName = Encoding.ASCII.GetString(fakeBpb.volume_label); sb.AppendFormat("Filesystem type: {0}", Encoding.ASCII.GetString(fakeBpb.fs_type)).AppendLine(); } } - else if(useAtariBpb && XmlFsType.VolumeSerial != null) - sb.AppendFormat("Volume Serial Number: {0}", XmlFsType.VolumeSerial).AppendLine(); + else if(useAtariBpb && xmlFsType.VolumeSerial != null) + sb.AppendFormat("Volume Serial Number: {0}", xmlFsType.VolumeSerial).AppendLine(); bootChk = sha1Ctx.Data(fakeBpb.boot_code, out _); // Check that jumps to a correct boot code position and has boot signature set. // This will mean that the volume will boot, even if just to say "this is not bootable change disk"...... - if(XmlFsType.Bootable == false && fakeBpb.jump != null) - XmlFsType.Bootable |= fakeBpb.jump[0] == 0xEB && fakeBpb.jump[1] > 0x58 && fakeBpb.jump[1] < 0x80 && + if(xmlFsType.Bootable == false && fakeBpb.jump != null) + xmlFsType.Bootable |= fakeBpb.jump[0] == 0xEB && fakeBpb.jump[1] > 0x58 && fakeBpb.jump[1] < 0x80 && fakeBpb.boot_signature == 0xAA55; - sectorsPerRealSector = fakeBpb.bps / imagePlugin.ImageInfo.SectorSize; + sectorsPerRealSector = fakeBpb.bps / imagePlugin.Info.SectorSize; // First root directory sector rootDirectorySector = (ulong)(fakeBpb.spfat * fakeBpb.fats_no + fakeBpb.rsectors) * sectorsPerRealSector; - sectorsForRootDirectory = (uint)(fakeBpb.root_ent * 32 / imagePlugin.ImageInfo.SectorSize); + sectorsForRootDirectory = (uint)(fakeBpb.root_ent * 32 / imagePlugin.Info.SectorSize); } if(extraInfo != null) sb.Append(extraInfo); if(rootDirectorySector + partition.Start < partition.End && - imagePlugin.ImageInfo.XmlMediaType != XmlMediaType.OpticalDisc) + imagePlugin.Info.XmlMediaType != XmlMediaType.OpticalDisc) { byte[] rootDirectory = imagePlugin.ReadSectors(rootDirectorySector + partition.Start, sectorsForRootDirectory); @@ -1336,24 +1314,24 @@ namespace DiscImageChef.Filesystems byte[] fullname = new byte[11]; Array.Copy(entry.filename, 0, fullname, 0, 8); Array.Copy(entry.extension, 0, fullname, 8, 3); - string volname = CurrentEncoding.GetString(fullname).Trim(); + string volname = currentEncoding.GetString(fullname).Trim(); if(!string.IsNullOrEmpty(volname)) - XmlFsType.VolumeName = (entry.caseinfo & 0x0C) > 0 ? volname.ToLower() : volname; + xmlFsType.VolumeName = (entry.caseinfo & 0x0C) > 0 ? volname.ToLower() : volname; if(entry.ctime > 0 && entry.cdate > 0) { - XmlFsType.CreationDate = DateHandlers.DosToDateTime(entry.cdate, entry.ctime); + xmlFsType.CreationDate = DateHandlers.DosToDateTime(entry.cdate, entry.ctime); if(entry.ctime_ms > 0) - XmlFsType.CreationDate = XmlFsType.CreationDate.AddMilliseconds(entry.ctime_ms * 10); - XmlFsType.CreationDateSpecified = true; - sb.AppendFormat("Volume created on {0}", XmlFsType.CreationDate).AppendLine(); + xmlFsType.CreationDate = xmlFsType.CreationDate.AddMilliseconds(entry.ctime_ms * 10); + xmlFsType.CreationDateSpecified = true; + sb.AppendFormat("Volume created on {0}", xmlFsType.CreationDate).AppendLine(); } if(entry.mtime > 0 && entry.mdate > 0) { - XmlFsType.ModificationDate = DateHandlers.DosToDateTime(entry.mdate, entry.mtime); - XmlFsType.ModificationDateSpecified = true; - sb.AppendFormat("Volume last modified on {0}", XmlFsType.ModificationDate).AppendLine(); + xmlFsType.ModificationDate = DateHandlers.DosToDateTime(entry.mdate, entry.mtime); + xmlFsType.ModificationDateSpecified = true; + sb.AppendFormat("Volume last modified on {0}", xmlFsType.ModificationDate).AppendLine(); } if(entry.adate > 0) @@ -1364,9 +1342,9 @@ namespace DiscImageChef.Filesystems } } - if(!string.IsNullOrEmpty(XmlFsType.VolumeName)) - sb.AppendFormat("Volume label: {0}", XmlFsType.VolumeName).AppendLine(); - if(XmlFsType.Bootable) + if(!string.IsNullOrEmpty(xmlFsType.VolumeName)) + sb.AppendFormat("Volume label: {0}", xmlFsType.VolumeName).AppendLine(); + if(xmlFsType.Bootable) { sb.AppendLine("Volume is bootable"); sb.AppendFormat("Boot code's SHA1: {0}", bootChk).AppendLine(); @@ -1375,62 +1353,57 @@ namespace DiscImageChef.Filesystems information = sb.ToString(); } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/FATX.cs b/DiscImageChef.Filesystems/FATX.cs index becaea97..9bbd2795 100644 --- a/DiscImageChef.Filesystems/FATX.cs +++ b/DiscImageChef.Filesystems/FATX.cs @@ -40,34 +40,21 @@ using Schemas; namespace DiscImageChef.Filesystems { - public class FATX : Filesystem + public class FATX : IFilesystem { const uint FATX_MAGIC = 0x58544146; - public FATX() - { - Name = "FATX Filesystem Plugin"; - PluginUuid = new Guid("ED27A721-4A17-4649-89FD-33633B46E228"); - CurrentEncoding = Encoding.UTF8; - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public FATX(Encoding encoding) - { - Name = "FATX Filesystem Plugin"; - PluginUuid = new Guid("ED27A721-4A17-4649-89FD-33633B46E228"); - CurrentEncoding = Encoding.UTF8; - } + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "FATX Filesystem Plugin"; + public virtual Guid Id => new Guid("ED27A721-4A17-4649-89FD-33633B46E228"); - public FATX(ImagePlugin imagePlugin, Partition partition, Encoding encoding) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { - Name = "FATX Filesystem Plugin"; - PluginUuid = new Guid("ED27A721-4A17-4649-89FD-33633B46E228"); - CurrentEncoding = Encoding.UTF8; - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) - { - if(imagePlugin.ImageInfo.SectorSize < 512) return false; + if(imagePlugin.Info.SectorSize < 512) return false; FATX_Superblock fatxSb; byte[] sector = imagePlugin.ReadSector(partition.Start); @@ -77,10 +64,12 @@ namespace DiscImageChef.Filesystems return fatxSb.magic == FATX_MAGIC; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, + Encoding encoding) { + currentEncoding = Encoding.UTF8; information = ""; - if(imagePlugin.ImageInfo.SectorSize < 512) return; + if(imagePlugin.Info.SectorSize < 512) return; FATX_Superblock fatxSb; @@ -95,76 +84,71 @@ namespace DiscImageChef.Filesystems sb.AppendLine("FATX filesystem"); sb.AppendFormat("Filesystem id {0}", fatxSb.id).AppendLine(); sb.AppendFormat("{0} sectors ({1} bytes) per cluster", fatxSb.sectorsPerCluster, - fatxSb.sectorsPerCluster * imagePlugin.ImageInfo.SectorSize).AppendLine(); + fatxSb.sectorsPerCluster * imagePlugin.Info.SectorSize).AppendLine(); sb.AppendFormat("Root directory starts on cluster {0}", fatxSb.rootDirectoryCluster).AppendLine(); information = sb.ToString(); - XmlFsType = new FileSystemType + xmlFsType = new FileSystemType { Type = "FATX filesystem", - ClusterSize = (int)(fatxSb.sectorsPerCluster * imagePlugin.ImageInfo.SectorSize) + ClusterSize = (int)(fatxSb.sectorsPerCluster * imagePlugin.Info.SectorSize) }; - XmlFsType.Clusters = (long)((partition.End - partition.Start + 1) * imagePlugin.ImageInfo.SectorSize / - (ulong)XmlFsType.ClusterSize); + xmlFsType.Clusters = (long)((partition.End - partition.Start + 1) * imagePlugin.Info.SectorSize / + (ulong)xmlFsType.ClusterSize); } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/FFS.cs b/DiscImageChef.Filesystems/FFS.cs index fb12eaa3..50d1c3a3 100644 --- a/DiscImageChef.Filesystems/FFS.cs +++ b/DiscImageChef.Filesystems/FFS.cs @@ -47,7 +47,7 @@ namespace DiscImageChef.Filesystems { // Using information from Linux kernel headers [SuppressMessage("ReSharper", "InconsistentNaming")] - public class FFSPlugin : Filesystem + public class FFSPlugin : IFilesystem { const uint block_size = 8192; @@ -81,42 +81,29 @@ namespace DiscImageChef.Filesystems // Big-endian incomplete newfs const uint UFS_BAD_CIGAM = 0x08049619; - public FFSPlugin() - { - Name = "BSD Fast File System (aka UNIX File System, UFS)"; - PluginUuid = new Guid("CC90D342-05DB-48A8-988C-C1FE000034A3"); - CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public FFSPlugin(Encoding encoding) - { - Name = "BSD Fast File System (aka UNIX File System, UFS)"; - PluginUuid = new Guid("CC90D342-05DB-48A8-988C-C1FE000034A3"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "BSD Fast File System (aka UNIX File System, UFS)"; + public virtual Guid Id => new Guid("CC90D342-05DB-48A8-988C-C1FE000034A3"); - public FFSPlugin(ImagePlugin imagePlugin, Partition partition, Encoding encoding) - { - Name = "BSD Fast File System (aka UNIX File System, UFS)"; - PluginUuid = new Guid("CC90D342-05DB-48A8-988C-C1FE000034A3"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { if(2 + partition.Start >= partition.End) return false; uint sbSizeInSectors; - if(imagePlugin.ImageInfo.SectorSize == 2336 || imagePlugin.ImageInfo.SectorSize == 2352 || - imagePlugin.ImageInfo.SectorSize == 2448) sbSizeInSectors = block_size / 2048; - else sbSizeInSectors = block_size / imagePlugin.ImageInfo.SectorSize; + if(imagePlugin.Info.SectorSize == 2336 || imagePlugin.Info.SectorSize == 2352 || + imagePlugin.Info.SectorSize == 2448) sbSizeInSectors = block_size / 2048; + else sbSizeInSectors = block_size / imagePlugin.Info.SectorSize; ulong[] locations = { sb_start_floppy, sb_start_boot, sb_start_long_boot, sb_start_piggy, sb_start_att_dsdd, - 8192 / imagePlugin.ImageInfo.SectorSize, 65536 / imagePlugin.ImageInfo.SectorSize, - 262144 / imagePlugin.ImageInfo.SectorSize + 8192 / imagePlugin.Info.SectorSize, 65536 / imagePlugin.Info.SectorSize, + 262144 / imagePlugin.Info.SectorSize }; return locations.Where(loc => partition.End > partition.Start + loc + sbSizeInSectors) @@ -127,8 +114,9 @@ namespace DiscImageChef.Filesystems magic == UFS_BAD_MAGIC || magic == UFS_BAD_CIGAM); } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { + currentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); information = ""; StringBuilder sbInformation = new StringBuilder(); @@ -144,15 +132,15 @@ namespace DiscImageChef.Filesystems bool fs_type_sun = false; bool fs_type_sun86 = false; - if(imagePlugin.ImageInfo.SectorSize == 2336 || imagePlugin.ImageInfo.SectorSize == 2352 || - imagePlugin.ImageInfo.SectorSize == 2448) sb_size_in_sectors = block_size / 2048; - else sb_size_in_sectors = block_size / imagePlugin.ImageInfo.SectorSize; + if(imagePlugin.Info.SectorSize == 2336 || imagePlugin.Info.SectorSize == 2352 || + imagePlugin.Info.SectorSize == 2448) sb_size_in_sectors = block_size / 2048; + else sb_size_in_sectors = block_size / imagePlugin.Info.SectorSize; ulong[] locations = { sb_start_floppy, sb_start_boot, sb_start_long_boot, sb_start_piggy, sb_start_att_dsdd, - 8192 / imagePlugin.ImageInfo.SectorSize, 65536 / imagePlugin.ImageInfo.SectorSize, - 262144 / imagePlugin.ImageInfo.SectorSize + 8192 / imagePlugin.Info.SectorSize, 65536 / imagePlugin.Info.SectorSize, + 262144 / imagePlugin.Info.SectorSize }; foreach(ulong loc in locations.Where(loc => partition.End > partition.Start + loc + sb_size_in_sectors)) @@ -176,43 +164,43 @@ namespace DiscImageChef.Filesystems return; } - XmlFsType = new FileSystemType(); + xmlFsType = new FileSystemType(); switch(magic) { case UFS_MAGIC: sbInformation.AppendLine("UFS filesystem"); - XmlFsType.Type = "UFS"; + xmlFsType.Type = "UFS"; break; case UFS_CIGAM: sbInformation.AppendLine("Big-endian UFS filesystem"); - XmlFsType.Type = "UFS"; + xmlFsType.Type = "UFS"; break; case UFS_MAGIC_BW: sbInformation.AppendLine("BorderWare UFS filesystem"); - XmlFsType.Type = "UFS"; + xmlFsType.Type = "UFS"; break; case UFS_CIGAM_BW: sbInformation.AppendLine("Big-endian BorderWare UFS filesystem"); - XmlFsType.Type = "UFS"; + xmlFsType.Type = "UFS"; break; case UFS2_MAGIC: sbInformation.AppendLine("UFS2 filesystem"); - XmlFsType.Type = "UFS2"; + xmlFsType.Type = "UFS2"; break; case UFS2_CIGAM: sbInformation.AppendLine("Big-endian UFS2 filesystem"); - XmlFsType.Type = "UFS2"; + xmlFsType.Type = "UFS2"; break; case UFS_BAD_MAGIC: sbInformation.AppendLine("Incompletely initialized UFS filesystem"); sbInformation.AppendLine("BEWARE!!! Following information may be completely wrong!"); - XmlFsType.Type = "UFS"; + xmlFsType.Type = "UFS"; break; case UFS_BAD_CIGAM: sbInformation.AppendLine("Incompletely initialized big-endian UFS filesystem"); sbInformation.AppendLine("BEWARE!!! Following information may be completely wrong!"); - XmlFsType.Type = "UFS"; + xmlFsType.Type = "UFS"; break; } @@ -358,12 +346,12 @@ namespace DiscImageChef.Filesystems sbInformation.AppendFormat("Cylinder group offset in cylinder: {0}", ufs_sb.fs_old_cgoffset).AppendLine(); sbInformation.AppendFormat("Volume last written on {0}", DateHandlers.UnixToDateTime(ufs_sb.fs_old_time)) .AppendLine(); - XmlFsType.ModificationDate = DateHandlers.UnixToDateTime(ufs_sb.fs_old_time); - XmlFsType.ModificationDateSpecified = true; + xmlFsType.ModificationDate = DateHandlers.UnixToDateTime(ufs_sb.fs_old_time); + xmlFsType.ModificationDateSpecified = true; sbInformation.AppendFormat("{0} blocks in volume ({1} bytes)", ufs_sb.fs_old_size, (long)ufs_sb.fs_old_size * ufs_sb.fs_fsize).AppendLine(); - XmlFsType.Clusters = ufs_sb.fs_old_size; - XmlFsType.ClusterSize = ufs_sb.fs_fsize; + xmlFsType.Clusters = ufs_sb.fs_old_size; + xmlFsType.ClusterSize = ufs_sb.fs_fsize; sbInformation.AppendFormat("{0} data blocks in volume ({1} bytes)", ufs_sb.fs_old_dsize, (long)ufs_sb.fs_old_dsize * ufs_sb.fs_fsize).AppendLine(); sbInformation.AppendFormat("{0} cylinder groups in volume", ufs_sb.fs_ncg).AppendLine(); @@ -423,14 +411,14 @@ namespace DiscImageChef.Filesystems sbInformation.AppendFormat("{0} directories", ufs_sb.fs_old_cstotal.cs_ndir).AppendLine(); sbInformation.AppendFormat("{0} free blocks ({1} bytes)", ufs_sb.fs_old_cstotal.cs_nbfree, (long)ufs_sb.fs_old_cstotal.cs_nbfree * ufs_sb.fs_fsize).AppendLine(); - XmlFsType.FreeClusters = ufs_sb.fs_old_cstotal.cs_nbfree; - XmlFsType.FreeClustersSpecified = true; + xmlFsType.FreeClusters = ufs_sb.fs_old_cstotal.cs_nbfree; + xmlFsType.FreeClustersSpecified = true; sbInformation.AppendFormat("{0} free inodes", ufs_sb.fs_old_cstotal.cs_nifree).AppendLine(); sbInformation.AppendFormat("{0} free frags", ufs_sb.fs_old_cstotal.cs_nffree).AppendLine(); if(ufs_sb.fs_fmod == 1) { sbInformation.AppendLine("Superblock is under modification"); - XmlFsType.Dirty = true; + xmlFsType.Dirty = true; } if(ufs_sb.fs_clean == 1) sbInformation.AppendLine("Volume is clean"); if(ufs_sb.fs_ronly == 1) sbInformation.AppendLine("Volume is read-only"); @@ -444,7 +432,7 @@ namespace DiscImageChef.Filesystems .AppendLine(); sbInformation.AppendFormat("Volume name: \"{0}\"", StringHandlers.CToString(ufs_sb.fs_volname)) .AppendLine(); - XmlFsType.VolumeName = StringHandlers.CToString(ufs_sb.fs_volname); + xmlFsType.VolumeName = StringHandlers.CToString(ufs_sb.fs_volname); sbInformation.AppendFormat("Volume ID: 0x{0:X16}", ufs_sb.fs_swuid).AppendLine(); //xmlFSType.VolumeSerial = string.Format("{0:X16}", ufs_sb.fs_swuid); sbInformation.AppendFormat("Last searched cylinder group: {0}", ufs_sb.fs_cgrotor).AppendLine(); @@ -453,18 +441,18 @@ namespace DiscImageChef.Filesystems sbInformation.AppendFormat("{0} directories", ufs_sb.fs_cstotal.cs_ndir).AppendLine(); sbInformation.AppendFormat("{0} free blocks ({1} bytes)", ufs_sb.fs_cstotal.cs_nbfree, ufs_sb.fs_cstotal.cs_nbfree * ufs_sb.fs_fsize).AppendLine(); - XmlFsType.FreeClusters = ufs_sb.fs_cstotal.cs_nbfree; - XmlFsType.FreeClustersSpecified = true; + xmlFsType.FreeClusters = ufs_sb.fs_cstotal.cs_nbfree; + xmlFsType.FreeClustersSpecified = true; sbInformation.AppendFormat("{0} free inodes", ufs_sb.fs_cstotal.cs_nifree).AppendLine(); sbInformation.AppendFormat("{0} free frags", ufs_sb.fs_cstotal.cs_nffree).AppendLine(); sbInformation.AppendFormat("{0} free clusters", ufs_sb.fs_cstotal.cs_numclusters).AppendLine(); sbInformation.AppendFormat("Volume last written on {0}", DateHandlers.UnixToDateTime(ufs_sb.fs_time)) .AppendLine(); - XmlFsType.ModificationDate = DateHandlers.UnixToDateTime(ufs_sb.fs_time); - XmlFsType.ModificationDateSpecified = true; + xmlFsType.ModificationDate = DateHandlers.UnixToDateTime(ufs_sb.fs_time); + xmlFsType.ModificationDateSpecified = true; sbInformation.AppendFormat("{0} blocks ({1} bytes)", ufs_sb.fs_size, ufs_sb.fs_size * ufs_sb.fs_fsize) .AppendLine(); - XmlFsType.Clusters = ufs_sb.fs_size; + xmlFsType.Clusters = ufs_sb.fs_size; sbInformation .AppendFormat("{0} data blocks ({1} bytes)", ufs_sb.fs_dsize, ufs_sb.fs_dsize * ufs_sb.fs_fsize) .AppendLine(); @@ -493,62 +481,57 @@ namespace DiscImageChef.Filesystems information = sbInformation.ToString(); } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/Fossil.cs b/DiscImageChef.Filesystems/Fossil.cs index fcaabc46..a3aa8919 100644 --- a/DiscImageChef.Filesystems/Fossil.cs +++ b/DiscImageChef.Filesystems/Fossil.cs @@ -41,43 +41,28 @@ using Schemas; namespace DiscImageChef.Filesystems { - public class Fossil : Filesystem + public class Fossil : IFilesystem { const uint FOSSIL_HDR_MAGIC = 0x3776AE89; const uint FOSSIL_SB_MAGIC = 0x2340A3B1; // Fossil header starts at 128KiB const ulong HEADER_POS = 128 * 1024; - public Fossil() - { - Name = "Fossil Filesystem Plugin"; - PluginUuid = new Guid("932BF104-43F6-494F-973C-45EF58A51DA9"); - CurrentEncoding = Encoding.UTF8; - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public Fossil(Encoding encoding) - { - Name = "Fossil Filesystem Plugin"; - PluginUuid = new Guid("932BF104-43F6-494F-973C-45EF58A51DA9"); - // Technically everything on Plan 9 from Bell Labs is in UTF-8 - CurrentEncoding = Encoding.UTF8; - } + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "Fossil Filesystem Plugin"; + public virtual Guid Id => new Guid("932BF104-43F6-494F-973C-45EF58A51DA9"); - public Fossil(ImagePlugin imagePlugin, Partition partition, Encoding encoding) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { - Name = "Fossil Filesystem Plugin"; - PluginUuid = new Guid("932BF104-43F6-494F-973C-45EF58A51DA9"); - // Technically everything on Plan 9 from Bell Labs is in UTF-8 - CurrentEncoding = Encoding.UTF8; - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) - { - ulong hdrSector = HEADER_POS / imagePlugin.ImageInfo.SectorSize; + ulong hdrSector = HEADER_POS / imagePlugin.Info.SectorSize; FossilHeader hdr; - if(partition.Start + hdrSector > imagePlugin.ImageInfo.Sectors) return false; + if(partition.Start + hdrSector > imagePlugin.Info.Sectors) return false; byte[] sector = imagePlugin.ReadSector(partition.Start + hdrSector); hdr = BigEndianMarshal.ByteArrayToStructureBigEndian(sector); @@ -88,12 +73,14 @@ namespace DiscImageChef.Filesystems return hdr.magic == FOSSIL_HDR_MAGIC; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { + // Technically everything on Plan 9 from Bell Labs is in UTF-8 + currentEncoding = Encoding.UTF8; information = ""; - if(imagePlugin.ImageInfo.SectorSize < 512) return; + if(imagePlugin.Info.SectorSize < 512) return; - ulong hdrSector = HEADER_POS / imagePlugin.ImageInfo.SectorSize; + ulong hdrSector = HEADER_POS / imagePlugin.Info.SectorSize; FossilHeader hdr; @@ -113,9 +100,9 @@ namespace DiscImageChef.Filesystems sb.AppendFormat("Data starts at block {0}", hdr.data).AppendLine(); sb.AppendFormat("Volume has {0} blocks", hdr.end).AppendLine(); - ulong sbLocation = hdr.super * (hdr.blockSize / imagePlugin.ImageInfo.SectorSize) + partition.Start; + ulong sbLocation = hdr.super * (hdr.blockSize / imagePlugin.Info.SectorSize) + partition.Start; - XmlFsType = new FileSystemType + xmlFsType = new FileSystemType { Type = "Fossil filesystem", ClusterSize = hdr.blockSize, @@ -138,71 +125,66 @@ namespace DiscImageChef.Filesystems sb.AppendFormat("Active root block {0}", fsb.active).AppendLine(); sb.AppendFormat("Next root block {0}", fsb.next).AppendLine(); sb.AppendFormat("Curren root block {0}", fsb.current).AppendLine(); - sb.AppendFormat("Volume label: \"{0}\"", StringHandlers.CToString(fsb.name, CurrentEncoding)) + sb.AppendFormat("Volume label: \"{0}\"", StringHandlers.CToString(fsb.name, currentEncoding)) .AppendLine(); - XmlFsType.VolumeName = StringHandlers.CToString(fsb.name, CurrentEncoding); + xmlFsType.VolumeName = StringHandlers.CToString(fsb.name, currentEncoding); } } information = sb.ToString(); } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/HAMMER.cs b/DiscImageChef.Filesystems/HAMMER.cs index 2195830f..0287f3c0 100644 --- a/DiscImageChef.Filesystems/HAMMER.cs +++ b/DiscImageChef.Filesystems/HAMMER.cs @@ -46,39 +46,26 @@ using hammer_tid_t = System.UInt64; namespace DiscImageChef.Filesystems { - public class HAMMER : Filesystem + public class HAMMER : IFilesystem { const ulong HAMMER_FSBUF_VOLUME = 0xC8414D4DC5523031; const ulong HAMMER_FSBUF_VOLUME_REV = 0x313052C54D4D41C8; const uint HAMMER_VOLHDR_SIZE = 1928; const int HAMMER_BIGBLOCK_SIZE = 8192 * 1024; - public HAMMER() - { - Name = "HAMMER Filesystem"; - PluginUuid = new Guid("91A188BF-5FD7-4677-BBD3-F59EBA9C864D"); - CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public HAMMER(Encoding encoding) - { - Name = "HAMMER Filesystem"; - PluginUuid = new Guid("91A188BF-5FD7-4677-BBD3-F59EBA9C864D"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "HAMMER Filesystem"; + public virtual Guid Id => new Guid("91A188BF-5FD7-4677-BBD3-F59EBA9C864D"); - public HAMMER(ImagePlugin imagePlugin, Partition partition, Encoding encoding) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { - Name = "HAMMER Filesystem"; - PluginUuid = new Guid("91A188BF-5FD7-4677-BBD3-F59EBA9C864D"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } + uint run = HAMMER_VOLHDR_SIZE / imagePlugin.Info.SectorSize; - public override bool Identify(ImagePlugin imagePlugin, Partition partition) - { - uint run = HAMMER_VOLHDR_SIZE / imagePlugin.ImageInfo.SectorSize; - - if(HAMMER_VOLHDR_SIZE % imagePlugin.ImageInfo.SectorSize > 0) run++; + if(HAMMER_VOLHDR_SIZE % imagePlugin.Info.SectorSize > 0) run++; if(run + partition.Start >= partition.End) return false; @@ -91,17 +78,18 @@ namespace DiscImageChef.Filesystems return magic == HAMMER_FSBUF_VOLUME || magic == HAMMER_FSBUF_VOLUME_REV; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { + currentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); information = ""; StringBuilder sb = new StringBuilder(); HammerSuperBlock hammerSb; - uint run = HAMMER_VOLHDR_SIZE / imagePlugin.ImageInfo.SectorSize; + uint run = HAMMER_VOLHDR_SIZE / imagePlugin.Info.SectorSize; - if(HAMMER_VOLHDR_SIZE % imagePlugin.ImageInfo.SectorSize > 0) run++; + if(HAMMER_VOLHDR_SIZE % imagePlugin.Info.SectorSize > 0) run++; ulong magic; @@ -123,7 +111,7 @@ namespace DiscImageChef.Filesystems sb.AppendFormat("Volume version: {0}", hammerSb.vol_version).AppendLine(); sb.AppendFormat("Volume {0} of {1} on this filesystem", hammerSb.vol_no + 1, hammerSb.vol_count) .AppendLine(); - sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(hammerSb.vol_label, CurrentEncoding)) + sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(hammerSb.vol_label, currentEncoding)) .AppendLine(); sb.AppendFormat("Volume serial: {0}", hammerSb.vol_fsid).AppendLine(); sb.AppendFormat("Filesystem type: {0}", hammerSb.vol_fstype).AppendLine(); @@ -132,13 +120,13 @@ namespace DiscImageChef.Filesystems sb.AppendFormat("First volume buffer starts at {0}", hammerSb.vol_buf_beg).AppendLine(); sb.AppendFormat("Volume ends at {0}", hammerSb.vol_buf_end).AppendLine(); - XmlFsType = new FileSystemType + xmlFsType = new FileSystemType { Clusters = (long)(partition.Size / HAMMER_BIGBLOCK_SIZE), ClusterSize = HAMMER_BIGBLOCK_SIZE, Dirty = false, Type = "HAMMER", - VolumeName = StringHandlers.CToString(hammerSb.vol_label, CurrentEncoding), + VolumeName = StringHandlers.CToString(hammerSb.vol_label, currentEncoding), VolumeSerial = hammerSb.vol_fsid.ToString() }; @@ -150,11 +138,11 @@ namespace DiscImageChef.Filesystems hammerSb.vol0_stat_freebigblocks * HAMMER_BIGBLOCK_SIZE).AppendLine(); sb.AppendFormat("Filesystem has {0} inode used", hammerSb.vol0_stat_inodes).AppendLine(); - XmlFsType.Clusters = hammerSb.vol0_stat_bigblocks; - XmlFsType.FreeClusters = hammerSb.vol0_stat_freebigblocks; - XmlFsType.FreeClustersSpecified = true; - XmlFsType.Files = hammerSb.vol0_stat_inodes; - XmlFsType.FilesSpecified = true; + xmlFsType.Clusters = hammerSb.vol0_stat_bigblocks; + xmlFsType.FreeClusters = hammerSb.vol0_stat_freebigblocks; + xmlFsType.FreeClustersSpecified = true; + xmlFsType.Files = hammerSb.vol0_stat_inodes; + xmlFsType.FilesSpecified = true; } // 0 ? //sb.AppendFormat("Volume header CRC: 0x{0:X8}", afs_sb.vol_crc).AppendLine(); @@ -162,62 +150,57 @@ namespace DiscImageChef.Filesystems information = sb.ToString(); } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/HPFS.cs b/DiscImageChef.Filesystems/HPFS.cs index 23da8d03..07751e57 100644 --- a/DiscImageChef.Filesystems/HPFS.cs +++ b/DiscImageChef.Filesystems/HPFS.cs @@ -42,30 +42,17 @@ using Schemas; namespace DiscImageChef.Filesystems { // Information from an old unnamed document - public class HPFS : Filesystem + public class HPFS : IFilesystem { - public HPFS() - { - Name = "OS/2 High Performance File System"; - PluginUuid = new Guid("33513B2C-f590-4acb-8bf2-0b1d5e19dec5"); - CurrentEncoding = Encoding.GetEncoding("ibm850"); - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public HPFS(Encoding encoding) - { - Name = "OS/2 High Performance File System"; - PluginUuid = new Guid("33513B2C-f590-4acb-8bf2-0b1d5e19dec5"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("ibm850"); - } + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "OS/2 High Performance File System"; + public virtual Guid Id => new Guid("33513B2C-f590-4acb-8bf2-0b1d5e19dec5"); - public HPFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) - { - Name = "OS/2 High Performance File System"; - PluginUuid = new Guid("33513B2C-f590-4acb-8bf2-0b1d5e19dec5"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("ibm850"); - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { if(16 + partition.Start >= partition.End) return false; @@ -79,8 +66,9 @@ namespace DiscImageChef.Filesystems return magic1 == 0xF995E849 && magic2 == 0xFA53E9C5; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { + currentEncoding = encoding ?? Encoding.GetEncoding("ibm850"); information = ""; StringBuilder sb = new StringBuilder(); @@ -138,7 +126,7 @@ namespace DiscImageChef.Filesystems sb.AppendFormat("NT Flags: 0x{0:X2}", hpfsBpb.nt_flags).AppendLine(); sb.AppendFormat("Signature: 0x{0:X2}", hpfsBpb.signature).AppendLine(); sb.AppendFormat("Serial number: 0x{0:X8}", hpfsBpb.serial_no).AppendLine(); - sb.AppendFormat("Volume label: {0}", StringHandlers.CToString(hpfsBpb.volume_label, CurrentEncoding)) + sb.AppendFormat("Volume label: {0}", StringHandlers.CToString(hpfsBpb.volume_label, currentEncoding)) .AppendLine(); // sb.AppendFormat("Filesystem type: \"{0}\"", hpfs_bpb.fs_type).AppendLine(); @@ -189,13 +177,13 @@ namespace DiscImageChef.Filesystems if((hpfsSp.flags2 & 0x40) == 0x40) sb.AppendLine("Unknown flag 0x40 on flags2 is active"); if((hpfsSp.flags2 & 0x80) == 0x80) sb.AppendLine("Unknown flag 0x80 on flags2 is active"); - XmlFsType = new FileSystemType(); + xmlFsType = new FileSystemType(); // Theoretically everything from BPB to SB is boot code, should I hash everything or only the sector loaded by BIOS itself? if(hpfsBpb.jump[0] == 0xEB && hpfsBpb.jump[1] > 0x3C && hpfsBpb.jump[1] < 0x80 && hpfsBpb.signature2 == 0xAA55) { - XmlFsType.Bootable = true; + xmlFsType.Bootable = true; Sha1Context sha1Ctx = new Sha1Context(); sha1Ctx.Init(); string bootChk = sha1Ctx.Data(hpfsBpb.boot_code, out byte[] sha1_out); @@ -203,73 +191,68 @@ namespace DiscImageChef.Filesystems sb.AppendFormat("Boot code's SHA1: {0}", bootChk).AppendLine(); } - XmlFsType.Dirty |= (hpfsSp.flags1 & 0x01) == 0x01; - XmlFsType.Clusters = hpfsSb.sectors; - XmlFsType.ClusterSize = hpfsBpb.bps; - XmlFsType.Type = "HPFS"; - XmlFsType.VolumeName = StringHandlers.CToString(hpfsBpb.volume_label, CurrentEncoding); - XmlFsType.VolumeSerial = $"{hpfsBpb.serial_no:X8}"; - XmlFsType.SystemIdentifier = StringHandlers.CToString(hpfsBpb.oem_name); + xmlFsType.Dirty |= (hpfsSp.flags1 & 0x01) == 0x01; + xmlFsType.Clusters = hpfsSb.sectors; + xmlFsType.ClusterSize = hpfsBpb.bps; + xmlFsType.Type = "HPFS"; + xmlFsType.VolumeName = StringHandlers.CToString(hpfsBpb.volume_label, currentEncoding); + xmlFsType.VolumeSerial = $"{hpfsBpb.serial_no:X8}"; + xmlFsType.SystemIdentifier = StringHandlers.CToString(hpfsBpb.oem_name); information = sb.ToString(); } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/Filesystem.cs b/DiscImageChef.Filesystems/IFilesystem.cs similarity index 70% rename from DiscImageChef.Filesystems/Filesystem.cs rename to DiscImageChef.Filesystems/IFilesystem.cs index 6bf0ccd3..97c84a66 100644 --- a/DiscImageChef.Filesystems/Filesystem.cs +++ b/DiscImageChef.Filesystems/IFilesystem.cs @@ -2,14 +2,14 @@ // The Disc Image Chef // ---------------------------------------------------------------------------- // -// Filename : Filesystem.cs +// Filename : IFilesystem.cs // Author(s) : Natalia Portillo // // Component : Filesystem plugins. // // --[ Description ] ---------------------------------------------------------- // -// Skeleton and interface for filesystem plugins. +// Interface for filesystem plugins. // // --[ License ] -------------------------------------------------------------- // @@ -40,35 +40,20 @@ using Schemas; namespace DiscImageChef.Filesystems { /// - /// Abstract class to implement filesystem plugins. + /// Interface to implement filesystem plugins. /// - public abstract class Filesystem + public interface IFilesystem { - protected Encoding CurrentEncoding; + Encoding Encoding { get; } /// Plugin name. - public string Name; + string Name { get; } /// Plugin UUID. - public Guid PluginUuid; - internal FileSystemType XmlFsType; - - protected Filesystem() { } - - // TODO: Call other constructors - protected Filesystem(Encoding encoding) { } - - /// - /// Initializes a filesystem instance prepared for reading contents - /// - /// Image plugin. - /// Partition. - /// Which encoding to use for this filesystem. - protected Filesystem(ImagePlugin imagePlugin, Partition partition, Encoding encoding) { } - + Guid Id { get; } /// /// Information about the filesystem as expected by CICM Metadata XML /// /// Information about the filesystem as expected by CICM Metadata XML - public FileSystemType XmlFSType => XmlFsType; + FileSystemType XmlFsType { get; } /// /// Identifies the filesystem in the specified LBA @@ -76,7 +61,7 @@ namespace DiscImageChef.Filesystems /// Disk image. /// Partition. /// true, if the filesystem is recognized, false otherwise. - public abstract bool Identify(ImagePlugin imagePlugin, Partition partition); + bool Identify(IMediaImage imagePlugin, Partition partition); /// /// Gets information about the identified filesystem. @@ -84,24 +69,25 @@ namespace DiscImageChef.Filesystems /// Disk image. /// Partition. /// Filesystem information. - public abstract void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information); + /// Which encoding to use for this filesystem. + void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding); /// /// Initializates whatever internal structures the filesystem plugin needs to be able to read files and directories /// from the filesystem. /// - public abstract Errno Mount(); + /// + /// + /// Which encoding to use for this filesystem. + /// If true enable debug. + Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug); /// - /// Initializates whatever internal structures the filesystem plugin needs to be able to read files and directories - /// from the filesystem. + /// Frees all internal structures created by + /// /// - public abstract Errno Mount(bool debug); - - /// - /// Frees all internal structures created by - /// - public abstract Errno Unmount(); + Errno Unmount(); /// /// Maps a filesystem block from a file to a block from the underlying device. @@ -110,7 +96,7 @@ namespace DiscImageChef.Filesystems /// File path. /// File block. /// Device block. - public abstract Errno MapBlock(string path, long fileBlock, ref long deviceBlock); + Errno MapBlock(string path, long fileBlock, ref long deviceBlock); /// /// Gets the attributes of a file or directory @@ -118,7 +104,7 @@ namespace DiscImageChef.Filesystems /// Error number. /// File path. /// File attributes. - public abstract Errno GetAttributes(string path, ref FileAttributes attributes); + Errno GetAttributes(string path, ref FileAttributes attributes); /// /// Lists all extended attributes, alternate data streams and forks of the given file. @@ -126,7 +112,7 @@ namespace DiscImageChef.Filesystems /// Error number. /// Path. /// List of extended attributes, alternate data streams and forks. - public abstract Errno ListXAttr(string path, ref List xattrs); + Errno ListXAttr(string path, ref List xattrs); /// /// Reads an extended attribute, alternate data stream or fork from the given file. @@ -135,7 +121,7 @@ namespace DiscImageChef.Filesystems /// File path. /// Extendad attribute, alternate data stream or fork name. /// Buffer. - public abstract Errno GetXattr(string path, string xattr, ref byte[] buf); + Errno GetXattr(string path, string xattr, ref byte[] buf); /// /// Reads data from a file (main/only data stream or data fork). @@ -144,33 +130,33 @@ namespace DiscImageChef.Filesystems /// Offset. /// Bytes to read. /// Buffer. - public abstract Errno Read(string path, long offset, long size, ref byte[] buf); + Errno Read(string path, long offset, long size, ref byte[] buf); /// /// Lists contents from a directory. /// /// Directory path. /// Directory contents. - public abstract Errno ReadDir(string path, ref List contents); + Errno ReadDir(string path, ref List contents); /// /// Gets information about the mounted volume. /// /// Information about the mounted volume. - public abstract Errno StatFs(ref FileSystemInfo stat); + Errno StatFs(ref FileSystemInfo stat); /// /// Gets information about a file or directory. /// /// File path. /// File information. - public abstract Errno Stat(string path, ref FileEntryInfo stat); + Errno Stat(string path, ref FileEntryInfo stat); /// /// Solves a symbolic link. /// /// Link path. /// Link destination. - public abstract Errno ReadLink(string path, ref string dest); + Errno ReadLink(string path, ref string dest); } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/ISO9660/Dir.cs b/DiscImageChef.Filesystems/ISO9660/Dir.cs index 77cf8c4c..3d964061 100644 --- a/DiscImageChef.Filesystems/ISO9660/Dir.cs +++ b/DiscImageChef.Filesystems/ISO9660/Dir.cs @@ -36,12 +36,12 @@ namespace DiscImageChef.Filesystems.ISO9660 { public partial class ISO9660 { - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/ISO9660/Extent.cs b/DiscImageChef.Filesystems/ISO9660/Extent.cs index cd8618aa..a49c2143 100644 --- a/DiscImageChef.Filesystems/ISO9660/Extent.cs +++ b/DiscImageChef.Filesystems/ISO9660/Extent.cs @@ -34,7 +34,7 @@ namespace DiscImageChef.Filesystems.ISO9660 { public partial class ISO9660 { - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/ISO9660/File.cs b/DiscImageChef.Filesystems/ISO9660/File.cs index cb26095c..75cdf939 100644 --- a/DiscImageChef.Filesystems/ISO9660/File.cs +++ b/DiscImageChef.Filesystems/ISO9660/File.cs @@ -34,17 +34,17 @@ namespace DiscImageChef.Filesystems.ISO9660 { public partial class ISO9660 { - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/ISO9660/ISO9660.cs b/DiscImageChef.Filesystems/ISO9660/ISO9660.cs index 3c93ce64..8107a765 100644 --- a/DiscImageChef.Filesystems/ISO9660/ISO9660.cs +++ b/DiscImageChef.Filesystems/ISO9660/ISO9660.cs @@ -34,31 +34,19 @@ using System; using System.Text; using DiscImageChef.CommonTypes; using DiscImageChef.DiscImages; +using Schemas; namespace DiscImageChef.Filesystems.ISO9660 { // This is coded following ECMA-119. - public partial class ISO9660 : Filesystem + public partial class ISO9660 : IFilesystem { - public ISO9660() - { - Name = "ISO9660 Filesystem"; - PluginUuid = new Guid("d812f4d3-c357-400d-90fd-3b22ef786aa8"); - CurrentEncoding = Encoding.ASCII; - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public ISO9660(Encoding encoding) - { - Name = "ISO9660 Filesystem"; - PluginUuid = new Guid("d812f4d3-c357-400d-90fd-3b22ef786aa8"); - CurrentEncoding = encoding ?? Encoding.ASCII; - } - - public ISO9660(ImagePlugin imagePlugin, Partition partition, Encoding encoding) - { - Name = "ISO9660 Filesystem"; - PluginUuid = new Guid("d812f4d3-c357-400d-90fd-3b22ef786aa8"); - CurrentEncoding = encoding ?? Encoding.ASCII; - } + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "ISO9660 Filesystem"; + public virtual Guid Id => new Guid("d812f4d3-c357-400d-90fd-3b22ef786aa8"); } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/ISO9660/Info.cs b/DiscImageChef.Filesystems/ISO9660/Info.cs index 05791432..aabe5fa3 100644 --- a/DiscImageChef.Filesystems/ISO9660/Info.cs +++ b/DiscImageChef.Filesystems/ISO9660/Info.cs @@ -45,10 +45,10 @@ namespace DiscImageChef.Filesystems.ISO9660 { public partial class ISO9660 { - public override bool Identify(ImagePlugin imagePlugin, Partition partition) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { // ISO9660 is designed for 2048 bytes/sector devices - if(imagePlugin.ImageInfo.SectorSize < 2048) return false; + if(imagePlugin.Info.SectorSize < 2048) return false; // ISO9660 Primary Volume Descriptor starts at sector 16, so that's minimal size. if(partition.End <= 16 + partition.Start) return false; @@ -69,16 +69,17 @@ namespace DiscImageChef.Filesystems.ISO9660 Array.Copy(vdSector, 0x001 + xaOff, vdMagic, 0, 5); Array.Copy(vdSector, 0x009 + xaOff, hsMagic, 0, 5); - DicConsole.DebugWriteLine("ISO9660 plugin", "VDMagic = {0}", CurrentEncoding.GetString(vdMagic)); - DicConsole.DebugWriteLine("ISO9660 plugin", "HSMagic = {0}", CurrentEncoding.GetString(hsMagic)); + DicConsole.DebugWriteLine("ISO9660 plugin", "VDMagic = {0}", currentEncoding.GetString(vdMagic)); + DicConsole.DebugWriteLine("ISO9660 plugin", "HSMagic = {0}", currentEncoding.GetString(hsMagic)); - return CurrentEncoding.GetString(vdMagic) == ISO_MAGIC || - CurrentEncoding.GetString(hsMagic) == HIGH_SIERRA_MAGIC || - CurrentEncoding.GetString(vdMagic) == CDI_MAGIC; + return currentEncoding.GetString(vdMagic) == ISO_MAGIC || + currentEncoding.GetString(hsMagic) == HIGH_SIERRA_MAGIC || + currentEncoding.GetString(vdMagic) == CDI_MAGIC; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { + currentEncoding = encoding ?? Encoding.ASCII; information = ""; StringBuilder isoMetadata = new StringBuilder(); byte[] vdMagic = new byte[5]; // Volume Descriptor magic "CD001" @@ -94,7 +95,7 @@ namespace DiscImageChef.Filesystems.ISO9660 ElToritoBootRecord? torito = null; // ISO9660 is designed for 2048 bytes/sector devices - if(imagePlugin.ImageInfo.SectorSize < 2048) return; + if(imagePlugin.Info.SectorSize < 2048) return; // ISO9660 Primary Volume Descriptor starts at sector 16, so that's minimal size. if(partition.End < 16) return; @@ -104,7 +105,7 @@ namespace DiscImageChef.Filesystems.ISO9660 byte[] vdSector = imagePlugin.ReadSector(16 + counter + partition.Start); int xaOff = vdSector.Length == 2336 ? 8 : 0; Array.Copy(vdSector, 0x009 + xaOff, hsMagic, 0, 5); - bool highSierra = CurrentEncoding.GetString(hsMagic) == HIGH_SIERRA_MAGIC; + bool highSierra = currentEncoding.GetString(hsMagic) == HIGH_SIERRA_MAGIC; int hsOff = 0; if(highSierra) hsOff = 8; bool cdi = false; @@ -131,9 +132,9 @@ namespace DiscImageChef.Filesystems.ISO9660 Array.Copy(vdSector, 0x001, vdMagic, 0, 5); Array.Copy(vdSector, 0x009, hsMagic, 0, 5); - if(CurrentEncoding.GetString(vdMagic) != ISO_MAGIC && - CurrentEncoding.GetString(hsMagic) != HIGH_SIERRA_MAGIC && - CurrentEncoding.GetString(vdMagic) != CDI_MAGIC + if(currentEncoding.GetString(vdMagic) != ISO_MAGIC && + currentEncoding.GetString(hsMagic) != HIGH_SIERRA_MAGIC && + currentEncoding.GetString(vdMagic) != CDI_MAGIC ) // Recognized, it is an ISO9660, now check for rest of data. { if(counter == 0) return; @@ -141,7 +142,7 @@ namespace DiscImageChef.Filesystems.ISO9660 break; } - cdi |= CurrentEncoding.GetString(vdMagic) == CDI_MAGIC; + cdi |= currentEncoding.GetString(vdMagic) == CDI_MAGIC; switch(vdType) { @@ -154,7 +155,7 @@ namespace DiscImageChef.Filesystems.ISO9660 bootSpec = "Unknown"; - if(CurrentEncoding.GetString(bvd.Value.system_id).Substring(0, 23) == "EL TORITO SPECIFICATION") + if(currentEncoding.GetString(bvd.Value.system_id).Substring(0, 23) == "EL TORITO SPECIFICATION") { bootSpec = "El Torito"; ptr = Marshal.AllocHGlobal(2048); @@ -213,7 +214,7 @@ namespace DiscImageChef.Filesystems.ISO9660 DecodedVolumeDescriptor decodedVd; DecodedVolumeDescriptor decodedJolietVd = new DecodedVolumeDescriptor(); - XmlFsType = new FileSystemType(); + xmlFsType = new FileSystemType(); if(pvd == null && hsvd == null && fsvd == null) { @@ -448,10 +449,10 @@ namespace DiscImageChef.Filesystems.ISO9660 foreach(byte[] erb in refareas) { ReferenceArea er = BigEndianMarshal.ByteArrayToStructureBigEndian(erb); - string extId = CurrentEncoding.GetString(erb, Marshal.SizeOf(er), er.id_len); - string extDes = CurrentEncoding.GetString(erb, Marshal.SizeOf(er) + er.id_len, er.des_len); + string extId = currentEncoding.GetString(erb, Marshal.SizeOf(er), er.id_len); + string extDes = currentEncoding.GetString(erb, Marshal.SizeOf(er) + er.id_len, er.des_len); string extSrc = - CurrentEncoding.GetString(erb, Marshal.SizeOf(er) + er.id_len + er.des_len, er.src_len); + 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}", extId, er.ext_ver).AppendLine(); suspInformation.AppendFormat("\tDescription: {0}", extDes).AppendLine(); @@ -581,7 +582,7 @@ namespace DiscImageChef.Filesystems.ISO9660 isoMetadata.AppendLine("----------------------"); isoMetadata.AppendLine("Initial entry:"); - isoMetadata.AppendFormat("\tDeveloper ID: {0}", CurrentEncoding.GetString(valentry.developer_id)) + isoMetadata.AppendFormat("\tDeveloper ID: {0}", currentEncoding.GetString(valentry.developer_id)) .AppendLine(); if(initialEntry.bootable == ElToritoIndicator.Bootable) { @@ -636,7 +637,7 @@ namespace DiscImageChef.Filesystems.ISO9660 toritoOff += EL_TORITO_ENTRY_SIZE; isoMetadata.AppendFormat("Boot section {0}:", SECTION_COUNTER); - isoMetadata.AppendFormat("\tSection ID: {0}", CurrentEncoding.GetString(sectionHeader.identifier)) + isoMetadata.AppendFormat("\tSection ID: {0}", currentEncoding.GetString(sectionHeader.identifier)) .AppendLine(); for(int entryCounter = 1; entryCounter <= sectionHeader.entries && toritoOff < vdSector.Length; @@ -724,85 +725,85 @@ namespace DiscImageChef.Filesystems.ISO9660 exit_torito: if(refareas.Count > 0) isoMetadata.Append(suspInformation); - XmlFsType.Type = fsFormat; + xmlFsType.Type = fsFormat; if(jolietvd != null) { - XmlFsType.VolumeName = decodedJolietVd.VolumeIdentifier; + xmlFsType.VolumeName = decodedJolietVd.VolumeIdentifier; if(decodedJolietVd.SystemIdentifier == null || decodedVd.SystemIdentifier.Length > decodedJolietVd.SystemIdentifier.Length) - XmlFsType.SystemIdentifier = decodedVd.SystemIdentifier; - else XmlFsType.SystemIdentifier = decodedJolietVd.SystemIdentifier; + xmlFsType.SystemIdentifier = decodedVd.SystemIdentifier; + else xmlFsType.SystemIdentifier = decodedJolietVd.SystemIdentifier; if(decodedJolietVd.VolumeSetIdentifier == null || decodedVd.VolumeSetIdentifier.Length > decodedJolietVd.VolumeSetIdentifier.Length) - XmlFsType.VolumeSetIdentifier = decodedVd.VolumeSetIdentifier; - else XmlFsType.VolumeSetIdentifier = decodedJolietVd.VolumeSetIdentifier; + xmlFsType.VolumeSetIdentifier = decodedVd.VolumeSetIdentifier; + else xmlFsType.VolumeSetIdentifier = decodedJolietVd.VolumeSetIdentifier; if(decodedJolietVd.PublisherIdentifier == null || decodedVd.PublisherIdentifier.Length > decodedJolietVd.PublisherIdentifier.Length) - XmlFsType.PublisherIdentifier = decodedVd.PublisherIdentifier; - else XmlFsType.PublisherIdentifier = decodedJolietVd.PublisherIdentifier; + xmlFsType.PublisherIdentifier = decodedVd.PublisherIdentifier; + else xmlFsType.PublisherIdentifier = decodedJolietVd.PublisherIdentifier; if(decodedJolietVd.DataPreparerIdentifier == null || decodedVd.DataPreparerIdentifier.Length > decodedJolietVd.DataPreparerIdentifier.Length) - XmlFsType.DataPreparerIdentifier = decodedVd.DataPreparerIdentifier; - else XmlFsType.DataPreparerIdentifier = decodedJolietVd.SystemIdentifier; + xmlFsType.DataPreparerIdentifier = decodedVd.DataPreparerIdentifier; + else xmlFsType.DataPreparerIdentifier = decodedJolietVd.SystemIdentifier; if(decodedJolietVd.ApplicationIdentifier == null || decodedVd.ApplicationIdentifier.Length > decodedJolietVd.ApplicationIdentifier.Length) - XmlFsType.ApplicationIdentifier = decodedVd.ApplicationIdentifier; - else XmlFsType.ApplicationIdentifier = decodedJolietVd.SystemIdentifier; + xmlFsType.ApplicationIdentifier = decodedVd.ApplicationIdentifier; + else xmlFsType.ApplicationIdentifier = decodedJolietVd.SystemIdentifier; - XmlFsType.CreationDate = decodedJolietVd.CreationTime; - XmlFsType.CreationDateSpecified = true; + xmlFsType.CreationDate = decodedJolietVd.CreationTime; + xmlFsType.CreationDateSpecified = true; if(decodedJolietVd.HasModificationTime) { - XmlFsType.ModificationDate = decodedJolietVd.ModificationTime; - XmlFsType.ModificationDateSpecified = true; + xmlFsType.ModificationDate = decodedJolietVd.ModificationTime; + xmlFsType.ModificationDateSpecified = true; } if(decodedJolietVd.HasExpirationTime) { - XmlFsType.ExpirationDate = decodedJolietVd.ExpirationTime; - XmlFsType.ExpirationDateSpecified = true; + xmlFsType.ExpirationDate = decodedJolietVd.ExpirationTime; + xmlFsType.ExpirationDateSpecified = true; } if(decodedJolietVd.HasEffectiveTime) { - XmlFsType.EffectiveDate = decodedJolietVd.EffectiveTime; - XmlFsType.EffectiveDateSpecified = true; + xmlFsType.EffectiveDate = decodedJolietVd.EffectiveTime; + xmlFsType.EffectiveDateSpecified = true; } } else { - XmlFsType.SystemIdentifier = decodedVd.SystemIdentifier; - XmlFsType.VolumeName = decodedVd.VolumeIdentifier; - XmlFsType.VolumeSetIdentifier = decodedVd.VolumeSetIdentifier; - XmlFsType.PublisherIdentifier = decodedVd.PublisherIdentifier; - XmlFsType.DataPreparerIdentifier = decodedVd.DataPreparerIdentifier; - XmlFsType.ApplicationIdentifier = decodedVd.ApplicationIdentifier; - XmlFsType.CreationDate = decodedVd.CreationTime; - XmlFsType.CreationDateSpecified = true; + xmlFsType.SystemIdentifier = decodedVd.SystemIdentifier; + xmlFsType.VolumeName = decodedVd.VolumeIdentifier; + xmlFsType.VolumeSetIdentifier = decodedVd.VolumeSetIdentifier; + xmlFsType.PublisherIdentifier = decodedVd.PublisherIdentifier; + xmlFsType.DataPreparerIdentifier = decodedVd.DataPreparerIdentifier; + xmlFsType.ApplicationIdentifier = decodedVd.ApplicationIdentifier; + xmlFsType.CreationDate = decodedVd.CreationTime; + xmlFsType.CreationDateSpecified = true; if(decodedVd.HasModificationTime) { - XmlFsType.ModificationDate = decodedVd.ModificationTime; - XmlFsType.ModificationDateSpecified = true; + xmlFsType.ModificationDate = decodedVd.ModificationTime; + xmlFsType.ModificationDateSpecified = true; } if(decodedVd.HasExpirationTime) { - XmlFsType.ExpirationDate = decodedVd.ExpirationTime; - XmlFsType.ExpirationDateSpecified = true; + xmlFsType.ExpirationDate = decodedVd.ExpirationTime; + xmlFsType.ExpirationDateSpecified = true; } if(decodedVd.HasEffectiveTime) { - XmlFsType.EffectiveDate = decodedVd.EffectiveTime; - XmlFsType.EffectiveDateSpecified = true; + xmlFsType.EffectiveDate = decodedVd.EffectiveTime; + xmlFsType.EffectiveDateSpecified = true; } } - XmlFsType.Bootable |= bvd != null || segaCd != null || saturn != null || dreamcast != null; - XmlFsType.Clusters = decodedVd.Blocks; - XmlFsType.ClusterSize = decodedVd.BlockSize; + xmlFsType.Bootable |= bvd != null || segaCd != null || saturn != null || dreamcast != null; + xmlFsType.Clusters = decodedVd.Blocks; + xmlFsType.ClusterSize = decodedVd.BlockSize; information = isoMetadata.ToString(); } diff --git a/DiscImageChef.Filesystems/ISO9660/Super.cs b/DiscImageChef.Filesystems/ISO9660/Super.cs index 770f4cc5..89c40538 100644 --- a/DiscImageChef.Filesystems/ISO9660/Super.cs +++ b/DiscImageChef.Filesystems/ISO9660/Super.cs @@ -30,26 +30,25 @@ // Copyright © 2011-2018 Natalia Portillo // ****************************************************************************/ +using System.Text; +using DiscImageChef.CommonTypes; +using DiscImageChef.DiscImages; + namespace DiscImageChef.Filesystems.ISO9660 { public partial class ISO9660 { - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() - { - return Errno.NotImplemented; - } - - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/ISO9660/Xattr.cs b/DiscImageChef.Filesystems/ISO9660/Xattr.cs index 558cfe6f..9322d9f9 100644 --- a/DiscImageChef.Filesystems/ISO9660/Xattr.cs +++ b/DiscImageChef.Filesystems/ISO9660/Xattr.cs @@ -36,12 +36,12 @@ namespace DiscImageChef.Filesystems.ISO9660 { public partial class ISO9660 { - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/JFS.cs b/DiscImageChef.Filesystems/JFS.cs index 117dd747..5147c641 100644 --- a/DiscImageChef.Filesystems/JFS.cs +++ b/DiscImageChef.Filesystems/JFS.cs @@ -40,35 +40,22 @@ using Schemas; namespace DiscImageChef.Filesystems { - public class JFS : Filesystem + public class JFS : IFilesystem { const uint JFS_BOOT_BLOCKS_SIZE = 0x8000; const uint JFS_MAGIC = 0x3153464A; - public JFS() - { - Name = "JFS Plugin"; - PluginUuid = new Guid("D3BE2A41-8F28-4055-94DC-BB6C72A0E9C4"); - CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public JFS(Encoding encoding) - { - Name = "JFS Plugin"; - PluginUuid = new Guid("D3BE2A41-8F28-4055-94DC-BB6C72A0E9C4"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "JFS Plugin"; + public virtual Guid Id => new Guid("D3BE2A41-8F28-4055-94DC-BB6C72A0E9C4"); - public JFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { - Name = "JFS Plugin"; - PluginUuid = new Guid("D3BE2A41-8F28-4055-94DC-BB6C72A0E9C4"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) - { - uint bootSectors = JFS_BOOT_BLOCKS_SIZE / imagePlugin.ImageInfo.SectorSize; + uint bootSectors = JFS_BOOT_BLOCKS_SIZE / imagePlugin.Info.SectorSize; if(partition.Start + bootSectors >= partition.End) return false; byte[] sector = imagePlugin.ReadSector(partition.Start + bootSectors); @@ -83,11 +70,12 @@ namespace DiscImageChef.Filesystems return jfsSb.s_magic == JFS_MAGIC; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { + currentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); information = ""; StringBuilder sb = new StringBuilder(); - uint bootSectors = JFS_BOOT_BLOCKS_SIZE / imagePlugin.ImageInfo.SectorSize; + uint bootSectors = JFS_BOOT_BLOCKS_SIZE / imagePlugin.Info.SectorSize; byte[] sector = imagePlugin.ReadSector(partition.Start + bootSectors); if(sector.Length < 512) return; @@ -132,82 +120,77 @@ namespace DiscImageChef.Filesystems DateHandlers.UnixUnsignedToDateTime(jfsSb.s_time.tv_sec, jfsSb.s_time.tv_nsec)) .AppendLine(); if(jfsSb.s_version == 1) - sb.AppendFormat("Volume name: {0}", CurrentEncoding.GetString(jfsSb.s_fpack)).AppendLine(); - else sb.AppendFormat("Volume name: {0}", CurrentEncoding.GetString(jfsSb.s_label)).AppendLine(); + sb.AppendFormat("Volume name: {0}", currentEncoding.GetString(jfsSb.s_fpack)).AppendLine(); + else sb.AppendFormat("Volume name: {0}", currentEncoding.GetString(jfsSb.s_label)).AppendLine(); sb.AppendFormat("Volume UUID: {0}", jfsSb.s_uuid).AppendLine(); - XmlFsType = new FileSystemType + xmlFsType = new FileSystemType { Type = "JFS filesystem", Clusters = (long)jfsSb.s_size, ClusterSize = (int)jfsSb.s_bsize, Bootable = true, - VolumeName = CurrentEncoding.GetString(jfsSb.s_version == 1 ? jfsSb.s_fpack : jfsSb.s_label), + VolumeName = currentEncoding.GetString(jfsSb.s_version == 1 ? jfsSb.s_fpack : jfsSb.s_label), VolumeSerial = $"{jfsSb.s_uuid}", ModificationDate = DateHandlers.UnixUnsignedToDateTime(jfsSb.s_time.tv_sec, jfsSb.s_time.tv_nsec), ModificationDateSpecified = true }; - if(jfsSb.s_state != 0) XmlFsType.Dirty = true; + if(jfsSb.s_state != 0) xmlFsType.Dirty = true; information = sb.ToString(); } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/LIF.cs b/DiscImageChef.Filesystems/LIF.cs index e203fe5b..034c7895 100644 --- a/DiscImageChef.Filesystems/LIF.cs +++ b/DiscImageChef.Filesystems/LIF.cs @@ -42,34 +42,21 @@ using Schemas; namespace DiscImageChef.Filesystems { // Information from http://www.hp9845.net/9845/projects/hpdir/#lif_filesystem - public class LIF : Filesystem + public class LIF : IFilesystem { const uint LIF_MAGIC = 0x8000; - public LIF() - { - Name = "HP Logical Interchange Format Plugin"; - PluginUuid = new Guid("41535647-77A5-477B-9206-DA727ACDC704"); - CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public LIF(Encoding encoding) - { - Name = "HP Logical Interchange Format Plugin"; - PluginUuid = new Guid("41535647-77A5-477B-9206-DA727ACDC704"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "HP Logical Interchange Format Plugin"; + public virtual Guid Id => new Guid("41535647-77A5-477B-9206-DA727ACDC704"); - public LIF(ImagePlugin imagePlugin, Partition partition, Encoding encoding) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { - Name = "HP Logical Interchange Format Plugin"; - PluginUuid = new Guid("41535647-77A5-477B-9206-DA727ACDC704"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) - { - if(imagePlugin.ImageInfo.SectorSize < 256) return false; + if(imagePlugin.Info.SectorSize < 256) return false; byte[] sector = imagePlugin.ReadSector(partition.Start); LIF_SystemBlock lifSb = BigEndianMarshal.ByteArrayToStructureBigEndian(sector); @@ -78,11 +65,12 @@ namespace DiscImageChef.Filesystems return lifSb.magic == LIF_MAGIC; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { + currentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); information = ""; - if(imagePlugin.ImageInfo.SectorSize < 256) return; + if(imagePlugin.Info.SectorSize < 256) return; byte[] sector = imagePlugin.ReadSector(partition.Start); LIF_SystemBlock lifSb = BigEndianMarshal.ByteArrayToStructureBigEndian(sector); @@ -100,79 +88,74 @@ namespace DiscImageChef.Filesystems sb.AppendFormat("{0} tracks", lifSb.tracks).AppendLine(); sb.AppendFormat("{0} heads", lifSb.heads).AppendLine(); sb.AppendFormat("{0} sectors", lifSb.sectors).AppendLine(); - sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(lifSb.volumeLabel, CurrentEncoding)) + sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(lifSb.volumeLabel, currentEncoding)) .AppendLine(); sb.AppendFormat("Volume created on {0}", DateHandlers.LifToDateTime(lifSb.creationDate)).AppendLine(); information = sb.ToString(); - XmlFsType = new FileSystemType + xmlFsType = new FileSystemType { Type = "HP Logical Interchange Format", ClusterSize = 256, Clusters = (long)(partition.Size / 256), CreationDate = DateHandlers.LifToDateTime(lifSb.creationDate), CreationDateSpecified = true, - VolumeName = StringHandlers.CToString(lifSb.volumeLabel, CurrentEncoding) + VolumeName = StringHandlers.CToString(lifSb.volumeLabel, currentEncoding) }; } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/LisaFS/Dir.cs b/DiscImageChef.Filesystems/LisaFS/Dir.cs index a7876729..8bf0910f 100644 --- a/DiscImageChef.Filesystems/LisaFS/Dir.cs +++ b/DiscImageChef.Filesystems/LisaFS/Dir.cs @@ -45,7 +45,7 @@ namespace DiscImageChef.Filesystems.LisaFS /// /// Link path. /// Link destination. - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { // LisaFS does not support symbolic links (afaik) return Errno.NotSupported; @@ -56,7 +56,7 @@ namespace DiscImageChef.Filesystems.LisaFS /// /// Directory path. /// Directory contents. - public override Errno ReadDir(string path, ref List contents) + public virtual Errno ReadDir(string path, ref List contents) { Errno error = LookupFileId(path, out short fileId, out bool isDir); if(error != Errno.NoError) return error; @@ -92,7 +92,7 @@ namespace DiscImageChef.Filesystems.LisaFS // as '-' is the path separator in Lisa OS contents = (from entry in catalogCache where entry.parentID == dirId - select StringHandlers.CToString(entry.filename, CurrentEncoding).Replace('/', '-')).ToList(); + select StringHandlers.CToString(entry.filename, currentEncoding).Replace('/', '-')).ToList(); return Errno.NoError; } @@ -164,7 +164,7 @@ namespace DiscImageChef.Filesystems.LisaFS // Search for the first sector describing the catalog // While root catalog is not stored in S-Records, probably rest are? (unchecked) // If root catalog is not pointed in MDDF (unchecked) maybe it's always following S-Records File? - for(ulong i = 0; i < device.ImageInfo.Sectors; i++) + for(ulong i = 0; i < device.Info.Sectors; i++) { DecodeTag(device.ReadSectorTag(i, SectorTagType.AppleSectorTag), out LisaTag.PriamTag catTag); diff --git a/DiscImageChef.Filesystems/LisaFS/Extent.cs b/DiscImageChef.Filesystems/LisaFS/Extent.cs index e347262b..7b50464e 100644 --- a/DiscImageChef.Filesystems/LisaFS/Extent.cs +++ b/DiscImageChef.Filesystems/LisaFS/Extent.cs @@ -39,7 +39,7 @@ namespace DiscImageChef.Filesystems.LisaFS { public partial class LisaFS { - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { // TODO: Not really important. return Errno.NotImplemented; @@ -78,11 +78,11 @@ namespace DiscImageChef.Filesystems.LisaFS // This happens on some disks. // This is a filesystem corruption that makes LisaOS crash on scavenge. // This code just allow to ignore that corruption by searching the Extents File using sector tags - if(ptr >= device.ImageInfo.Sectors) + if(ptr >= device.Info.Sectors) { bool found = false; - for(ulong i = 0; i < device.ImageInfo.Sectors; i++) + for(ulong i = 0; i < device.Info.Sectors; i++) { DecodeTag(device.ReadSectorTag(i, SectorTagType.AppleSectorTag), out extTag); if(extTag.FileId != fileId * -1) continue; @@ -185,7 +185,7 @@ namespace DiscImageChef.Filesystems.LisaFS DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].filenameLen = {1}", fileId, file.filenameLen); DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].filename = {1}", fileId, - StringHandlers.CToString(file.filename, CurrentEncoding)); + StringHandlers.CToString(file.filename, currentEncoding)); DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown1 = 0x{1:X4}", fileId, file.unknown1); DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].file_uid = 0x{1:X16}", fileId, file.file_uid); DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown2 = 0x{1:X2}", fileId, file.unknown2); @@ -219,7 +219,7 @@ namespace DiscImageChef.Filesystems.LisaFS DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].password_valid = {1}", fileId, file.password_valid > 0); DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].password = {1}", fileId, - CurrentEncoding.GetString(file.password)); + currentEncoding.GetString(file.password)); DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown7 = 0x{1:X2}{2:X2}{3:X2}", fileId, file.unknown7[0], file.unknown7[1], file.unknown7[2]); DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].overhead = {1}", fileId, file.overhead); diff --git a/DiscImageChef.Filesystems/LisaFS/File.cs b/DiscImageChef.Filesystems/LisaFS/File.cs index 7574378c..8ebfb59d 100644 --- a/DiscImageChef.Filesystems/LisaFS/File.cs +++ b/DiscImageChef.Filesystems/LisaFS/File.cs @@ -39,7 +39,7 @@ namespace DiscImageChef.Filesystems.LisaFS { public partial class LisaFS { - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { Errno error = LookupFileId(path, out short fileId, out bool isDir); if(error != Errno.NoError) return error; @@ -52,7 +52,7 @@ namespace DiscImageChef.Filesystems.LisaFS return Errno.NoError; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { if(size == 0) { @@ -94,7 +94,7 @@ namespace DiscImageChef.Filesystems.LisaFS return Errno.NoError; } - public override Errno Stat(string path, ref FileEntryInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { Errno error = LookupFileId(path, out short fileId, out bool isDir); if(error != Errno.NoError) return error; @@ -194,7 +194,7 @@ namespace DiscImageChef.Filesystems.LisaFS if(count == 0) return Errno.NoSuchFile; - buf = !tags ? new byte[count * device.ImageInfo.SectorSize] : new byte[count * devTagSize]; + buf = !tags ? new byte[count * device.Info.SectorSize] : new byte[count * devTagSize]; // Should be enough to check 100 sectors? for(ulong i = 0; i < 100; i++) @@ -325,7 +325,7 @@ namespace DiscImageChef.Filesystems.LisaFS int sectorSize; if(tags) sectorSize = devTagSize; - else sectorSize = (int)device.ImageInfo.SectorSize; + else sectorSize = (int)device.Info.SectorSize; byte[] temp = new byte[file.length * sectorSize]; @@ -423,7 +423,7 @@ namespace DiscImageChef.Filesystems.LisaFS foreach(CatalogEntry entry in catalogCache) { - string filename = StringHandlers.CToString(entry.filename, CurrentEncoding); + string filename = StringHandlers.CToString(entry.filename, currentEncoding); // LisaOS is case insensitive if(string.Compare(wantedFilename, filename, StringComparison.InvariantCultureIgnoreCase) != 0 || diff --git a/DiscImageChef.Filesystems/LisaFS/Info.cs b/DiscImageChef.Filesystems/LisaFS/Info.cs index afbad6cf..d1666d27 100644 --- a/DiscImageChef.Filesystems/LisaFS/Info.cs +++ b/DiscImageChef.Filesystems/LisaFS/Info.cs @@ -42,19 +42,19 @@ namespace DiscImageChef.Filesystems.LisaFS { public partial class LisaFS { - public override bool Identify(ImagePlugin imagePlugin, Partition partition) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { try { - if(imagePlugin.ImageInfo.ReadableSectorTags == null) return false; + if(imagePlugin.Info.ReadableSectorTags == null) return false; - if(!imagePlugin.ImageInfo.ReadableSectorTags.Contains(SectorTagType.AppleSectorTag)) return false; + if(!imagePlugin.Info.ReadableSectorTags.Contains(SectorTagType.AppleSectorTag)) return false; // LisaOS is big-endian BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; // Minimal LisaOS disk is 3.5" single sided double density, 800 sectors - if(imagePlugin.ImageInfo.Sectors < 800) return false; + if(imagePlugin.Info.Sectors < 800) return false; int beforeMddf = -1; @@ -84,19 +84,19 @@ namespace DiscImageChef.Filesystems.LisaFS DicConsole.DebugWriteLine("LisaFS plugin", "Current sector = {0}", i); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.mddf_block = {0}", infoMddf.mddf_block); DicConsole.DebugWriteLine("LisaFS plugin", "Disk size = {0} sectors", - imagePlugin.ImageInfo.Sectors); + imagePlugin.Info.Sectors); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.vol_size = {0} sectors", infoMddf.vol_size); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.vol_size - 1 = {0}", infoMddf.volsize_minus_one); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.vol_size - mddf.mddf_block -1 = {0}", infoMddf.volsize_minus_mddf_minus_one); DicConsole.DebugWriteLine("LisaFS plugin", "Disk sector = {0} bytes", - imagePlugin.ImageInfo.SectorSize); + imagePlugin.Info.SectorSize); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.blocksize = {0} bytes", infoMddf.blocksize); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.datasize = {0} bytes", infoMddf.datasize); if(infoMddf.mddf_block != i - beforeMddf) return false; - if(infoMddf.vol_size > imagePlugin.ImageInfo.Sectors) return false; + if(infoMddf.vol_size > imagePlugin.Info.Sectors) return false; if(infoMddf.vol_size - 1 != infoMddf.volsize_minus_one) return false; @@ -104,9 +104,9 @@ namespace DiscImageChef.Filesystems.LisaFS if(infoMddf.datasize > infoMddf.blocksize) return false; - if(infoMddf.blocksize < imagePlugin.ImageInfo.SectorSize) return false; + if(infoMddf.blocksize < imagePlugin.Info.SectorSize) return false; - return infoMddf.datasize == imagePlugin.ImageInfo.SectorSize; + return infoMddf.datasize == imagePlugin.Info.SectorSize; } return false; @@ -118,22 +118,22 @@ namespace DiscImageChef.Filesystems.LisaFS } } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { information = ""; StringBuilder sb = new StringBuilder(); try { - if(imagePlugin.ImageInfo.ReadableSectorTags == null) return; + if(imagePlugin.Info.ReadableSectorTags == null) return; - if(!imagePlugin.ImageInfo.ReadableSectorTags.Contains(SectorTagType.AppleSectorTag)) return; + if(!imagePlugin.Info.ReadableSectorTags.Contains(SectorTagType.AppleSectorTag)) return; // LisaOS is big-endian BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; // Minimal LisaOS disk is 3.5" single sided double density, 800 sectors - if(imagePlugin.ImageInfo.Sectors < 800) return; + if(imagePlugin.Info.Sectors < 800) return; int beforeMddf = -1; @@ -158,11 +158,11 @@ namespace DiscImageChef.Filesystems.LisaFS infoMddf.volid = BigEndianBitConverter.ToUInt64(sector, 0x02); infoMddf.volnum = BigEndianBitConverter.ToUInt16(sector, 0x0A); Array.Copy(sector, 0x0C, pString, 0, 33); - infoMddf.volname = StringHandlers.PascalToString(pString, CurrentEncoding); + infoMddf.volname = StringHandlers.PascalToString(pString, currentEncoding); infoMddf.unknown1 = sector[0x2D]; Array.Copy(sector, 0x2E, pString, 0, 33); // Prevent garbage - infoMddf.password = pString[0] <= 32 ? StringHandlers.PascalToString(pString, CurrentEncoding) : ""; + infoMddf.password = pString[0] <= 32 ? StringHandlers.PascalToString(pString, currentEncoding) : ""; infoMddf.unknown2 = sector[0x4F]; infoMddf.machine_id = BigEndianBitConverter.ToUInt32(sector, 0x50); infoMddf.master_copy_id = BigEndianBitConverter.ToUInt32(sector, 0x54); @@ -276,7 +276,7 @@ namespace DiscImageChef.Filesystems.LisaFS if(infoMddf.mddf_block != i - beforeMddf) return; - if(infoMddf.vol_size > imagePlugin.ImageInfo.Sectors) return; + if(infoMddf.vol_size > imagePlugin.Info.Sectors) return; if(infoMddf.vol_size - 1 != infoMddf.volsize_minus_one) return; @@ -284,9 +284,9 @@ namespace DiscImageChef.Filesystems.LisaFS if(infoMddf.datasize > infoMddf.blocksize) return; - if(infoMddf.blocksize < imagePlugin.ImageInfo.SectorSize) return; + if(infoMddf.blocksize < imagePlugin.Info.SectorSize) return; - if(infoMddf.datasize != imagePlugin.ImageInfo.SectorSize) return; + if(infoMddf.datasize != imagePlugin.Info.SectorSize) return; switch(infoMddf.fsversion) { @@ -348,27 +348,27 @@ namespace DiscImageChef.Filesystems.LisaFS information = sb.ToString(); - XmlFsType = new FileSystemType(); + xmlFsType = new FileSystemType(); if(DateTime.Compare(infoMddf.dtvb, DateHandlers.LisaToDateTime(0)) > 0) { - XmlFsType.BackupDate = infoMddf.dtvb; - XmlFsType.BackupDateSpecified = true; + xmlFsType.BackupDate = infoMddf.dtvb; + xmlFsType.BackupDateSpecified = true; } - XmlFsType.Clusters = infoMddf.vol_size; - XmlFsType.ClusterSize = infoMddf.clustersize * infoMddf.datasize; + xmlFsType.Clusters = infoMddf.vol_size; + xmlFsType.ClusterSize = infoMddf.clustersize * infoMddf.datasize; if(DateTime.Compare(infoMddf.dtvc, DateHandlers.LisaToDateTime(0)) > 0) { - XmlFsType.CreationDate = infoMddf.dtvc; - XmlFsType.CreationDateSpecified = true; + xmlFsType.CreationDate = infoMddf.dtvc; + xmlFsType.CreationDateSpecified = true; } - XmlFsType.Dirty = infoMddf.vol_left_mounted != 0; - XmlFsType.Files = infoMddf.filecount; - XmlFsType.FilesSpecified = true; - XmlFsType.FreeClusters = infoMddf.freecount; - XmlFsType.FreeClustersSpecified = true; - XmlFsType.Type = "LisaFS"; - XmlFsType.VolumeName = infoMddf.volname; - XmlFsType.VolumeSerial = $"{infoMddf.volid:X16}"; + xmlFsType.Dirty = infoMddf.vol_left_mounted != 0; + xmlFsType.Files = infoMddf.filecount; + xmlFsType.FilesSpecified = true; + xmlFsType.FreeClusters = infoMddf.freecount; + xmlFsType.FreeClustersSpecified = true; + xmlFsType.Type = "LisaFS"; + xmlFsType.VolumeName = infoMddf.volname; + xmlFsType.VolumeSerial = $"{infoMddf.volid:X16}"; return; } diff --git a/DiscImageChef.Filesystems/LisaFS/LisaFS.cs b/DiscImageChef.Filesystems/LisaFS/LisaFS.cs index 2c87f582..b11f8b50 100644 --- a/DiscImageChef.Filesystems/LisaFS/LisaFS.cs +++ b/DiscImageChef.Filesystems/LisaFS/LisaFS.cs @@ -35,15 +35,17 @@ using System.Collections.Generic; using Claunia.Encoding; using DiscImageChef.CommonTypes; using DiscImageChef.DiscImages; +using Schemas; using Encoding = System.Text.Encoding; namespace DiscImageChef.Filesystems.LisaFS { // All information by Natalia Portillo // Variable names from Lisa API - public partial class LisaFS : Filesystem + public partial class LisaFS : IFilesystem { - readonly ImagePlugin device; + IMediaImage device; + Encoding currentEncoding; bool debug; int devTagSize; @@ -52,27 +54,11 @@ namespace DiscImageChef.Filesystems.LisaFS SRecord[] srecords; ulong volumePrefix; - public LisaFS() - { - Name = "Apple Lisa File System"; - PluginUuid = new Guid("7E6034D1-D823-4248-A54D-239742B28391"); - CurrentEncoding = new LisaRoman(); - } - - public LisaFS(Encoding encoding) - { - Name = "Apple Lisa File System"; - PluginUuid = new Guid("7E6034D1-D823-4248-A54D-239742B28391"); - CurrentEncoding = new LisaRoman(); - } - - public LisaFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) - { - device = imagePlugin; - Name = "Apple Lisa File System"; - PluginUuid = new Guid("7E6034D1-D823-4248-A54D-239742B28391"); - CurrentEncoding = new LisaRoman(); - } + public virtual string Name => "Apple Lisa File System"; + public virtual Guid Id => new Guid("7E6034D1-D823-4248-A54D-239742B28391"); + public virtual Encoding Encoding => currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; #region Caches /// Caches Extents Files diff --git a/DiscImageChef.Filesystems/LisaFS/Super.cs b/DiscImageChef.Filesystems/LisaFS/Super.cs index 431abee1..6c01cc35 100644 --- a/DiscImageChef.Filesystems/LisaFS/Super.cs +++ b/DiscImageChef.Filesystems/LisaFS/Super.cs @@ -32,10 +32,13 @@ using System; using System.Collections.Generic; +using Claunia.Encoding; +using DiscImageChef.CommonTypes; using DiscImageChef.Console; using DiscImageChef.Decoders; using DiscImageChef.DiscImages; using Schemas; +using Encoding = System.Text.Encoding; namespace DiscImageChef.Filesystems.LisaFS { @@ -44,23 +47,18 @@ namespace DiscImageChef.Filesystems.LisaFS /// /// Mounts an Apple Lisa filesystem /// - public override Errno Mount() - { - return Mount(false); - } - - /// - /// Mounts an Apple Lisa filesystem - /// - public override Errno Mount(bool debug) + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { try { + device = imagePlugin; + currentEncoding = new LisaRoman(); + // Lisa OS is unable to work on disks without tags. // This code is designed like that. // However with some effort the code may be modified to ignore them. - if(device.ImageInfo.ReadableSectorTags == null || - !device.ImageInfo.ReadableSectorTags.Contains(SectorTagType.AppleSectorTag)) + if(device.Info.ReadableSectorTags == null || + !device.Info.ReadableSectorTags.Contains(SectorTagType.AppleSectorTag)) { DicConsole.DebugWriteLine("LisaFS plugin", "Underlying device does not support Lisa tags"); return Errno.InOutError; @@ -70,14 +68,14 @@ namespace DiscImageChef.Filesystems.LisaFS BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; // Minimal LisaOS disk is 3.5" single sided double density, 800 sectors - if(device.ImageInfo.Sectors < 800) + if(device.Info.Sectors < 800) { DicConsole.DebugWriteLine("LisaFS plugin", "Device is too small"); return Errno.InOutError; } // MDDF cannot be at end of device, of course - volumePrefix = device.ImageInfo.Sectors; + volumePrefix = device.Info.Sectors; // LisaOS searches sectors until tag tells MDDF resides there, so we'll search 100 sectors for(ulong i = 0; i < 100; i++) @@ -86,7 +84,7 @@ namespace DiscImageChef.Filesystems.LisaFS DicConsole.DebugWriteLine("LisaFS plugin", "Sector {0}, file ID 0x{1:X4}", i, searchTag.FileId); - if(volumePrefix == device.ImageInfo.Sectors && searchTag.FileId == FILEID_LOADER_SIGNED) + if(volumePrefix == device.Info.Sectors && searchTag.FileId == FILEID_LOADER_SIGNED) volumePrefix = i - 1; if(searchTag.FileId != FILEID_MDDF) continue; @@ -102,11 +100,11 @@ namespace DiscImageChef.Filesystems.LisaFS mddf.volid = BigEndianBitConverter.ToUInt64(sector, 0x02); mddf.volnum = BigEndianBitConverter.ToUInt16(sector, 0x0A); Array.Copy(sector, 0x0C, pString, 0, 33); - mddf.volname = StringHandlers.PascalToString(pString, CurrentEncoding); + mddf.volname = StringHandlers.PascalToString(pString, currentEncoding); mddf.unknown1 = sector[0x2D]; Array.Copy(sector, 0x2E, pString, 0, 33); // Prevent garbage - mddf.password = pString[0] <= 32 ? StringHandlers.PascalToString(pString, CurrentEncoding) : ""; + mddf.password = pString[0] <= 32 ? StringHandlers.PascalToString(pString, currentEncoding) : ""; mddf.unknown2 = sector[0x4F]; mddf.machine_id = BigEndianBitConverter.ToUInt32(sector, 0x50); mddf.master_copy_id = BigEndianBitConverter.ToUInt32(sector, 0x54); @@ -178,11 +176,11 @@ namespace DiscImageChef.Filesystems.LisaFS mddf.vol_left_mounted = sector[0x138]; // Check that the MDDF is correct - if(mddf.mddf_block != i - volumePrefix || mddf.vol_size > device.ImageInfo.Sectors || + if(mddf.mddf_block != i - volumePrefix || mddf.vol_size > device.Info.Sectors || mddf.vol_size - 1 != mddf.volsize_minus_one || mddf.vol_size - i - 1 != mddf.volsize_minus_mddf_minus_one - volumePrefix || - mddf.datasize > mddf.blocksize || mddf.blocksize < device.ImageInfo.SectorSize || - mddf.datasize != device.ImageInfo.SectorSize) + mddf.datasize > mddf.blocksize || mddf.blocksize < device.Info.SectorSize || + mddf.datasize != device.Info.SectorSize) { DicConsole.DebugWriteLine("LisaFS plugin", "Incorrect MDDF found"); return Errno.InvalidArgument; @@ -283,27 +281,27 @@ namespace DiscImageChef.Filesystems.LisaFS } // Create XML metadata for mounted filesystem - XmlFsType = new FileSystemType(); + xmlFsType = new FileSystemType(); if(DateTime.Compare(mddf.dtvb, DateHandlers.LisaToDateTime(0)) > 0) { - XmlFsType.BackupDate = mddf.dtvb; - XmlFsType.BackupDateSpecified = true; + xmlFsType.BackupDate = mddf.dtvb; + xmlFsType.BackupDateSpecified = true; } - XmlFsType.Clusters = mddf.vol_size; - XmlFsType.ClusterSize = mddf.clustersize * mddf.datasize; + xmlFsType.Clusters = mddf.vol_size; + xmlFsType.ClusterSize = mddf.clustersize * mddf.datasize; if(DateTime.Compare(mddf.dtvc, DateHandlers.LisaToDateTime(0)) > 0) { - XmlFsType.CreationDate = mddf.dtvc; - XmlFsType.CreationDateSpecified = true; + xmlFsType.CreationDate = mddf.dtvc; + xmlFsType.CreationDateSpecified = true; } - XmlFsType.Dirty = mddf.vol_left_mounted != 0; - XmlFsType.Files = mddf.filecount; - XmlFsType.FilesSpecified = true; - XmlFsType.FreeClusters = mddf.freecount; - XmlFsType.FreeClustersSpecified = true; - XmlFsType.Type = "LisaFS"; - XmlFsType.VolumeName = mddf.volname; - XmlFsType.VolumeSerial = $"{mddf.volid:X16}"; + xmlFsType.Dirty = mddf.vol_left_mounted != 0; + xmlFsType.Files = mddf.filecount; + xmlFsType.FilesSpecified = true; + xmlFsType.FreeClusters = mddf.freecount; + xmlFsType.FreeClustersSpecified = true; + xmlFsType.Type = "LisaFS"; + xmlFsType.VolumeName = mddf.volname; + xmlFsType.VolumeSerial = $"{mddf.volid:X16}"; return Errno.NoError; } @@ -321,7 +319,7 @@ namespace DiscImageChef.Filesystems.LisaFS /// /// Umounts this Lisa filesystem /// - public override Errno Unmount() + public virtual Errno Unmount() { mounted = false; extentCache = null; @@ -342,7 +340,7 @@ namespace DiscImageChef.Filesystems.LisaFS /// Gets information about the mounted volume. /// /// Information about the mounted volume. - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno StatFs(ref FileSystemInfo stat) { if(!mounted) return Errno.AccessDenied; @@ -353,7 +351,7 @@ namespace DiscImageChef.Filesystems.LisaFS Files = mddf.filecount, FreeBlocks = mddf.freecount, Id = {Serial64 = mddf.volid, IsLong = true}, - PluginId = PluginUuid + PluginId = Id }; stat.FreeFiles = FILEID_MAX - stat.Files; switch(mddf.fsversion) diff --git a/DiscImageChef.Filesystems/LisaFS/Xattr.cs b/DiscImageChef.Filesystems/LisaFS/Xattr.cs index 221caf16..0923a405 100644 --- a/DiscImageChef.Filesystems/LisaFS/Xattr.cs +++ b/DiscImageChef.Filesystems/LisaFS/Xattr.cs @@ -46,7 +46,7 @@ namespace DiscImageChef.Filesystems.LisaFS /// Error number. /// Path. /// List of extended attributes, alternate data streams and forks. - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno ListXAttr(string path, ref List xattrs) { Errno error = LookupFileId(path, out short fileId, out bool isDir); if(error != Errno.NoError) return error; @@ -61,7 +61,7 @@ namespace DiscImageChef.Filesystems.LisaFS /// File path. /// Extendad attribute, alternate data stream or fork name. /// Buffer. - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { Errno error = LookupFileId(path, out short fileId, out bool isDir); if(error != Errno.NoError) return error; diff --git a/DiscImageChef.Filesystems/Locus.cs b/DiscImageChef.Filesystems/Locus.cs index 105a08a1..a3009c9a 100644 --- a/DiscImageChef.Filesystems/Locus.cs +++ b/DiscImageChef.Filesystems/Locus.cs @@ -56,7 +56,7 @@ using time_t = System.Int32; namespace DiscImageChef.Filesystems { - public class Locus : Filesystem + public class Locus : IFilesystem { const int NICINOD = 325; const int NICFREE = 600; @@ -68,39 +68,26 @@ namespace DiscImageChef.Filesystems const uint Locus_OldMagic = 0xFFEEDDCC; const uint Locus_OldCigam = 0xCCDDEEFF; - public Locus() - { - Name = "Locus Filesystem Plugin"; - PluginUuid = new Guid("1A70B30A-437D-479A-88E1-D0C9C1797FF4"); - CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public Locus(Encoding encoding) - { - Name = "Locus Filesystem Plugin"; - PluginUuid = new Guid("1A70B30A-437D-479A-88E1-D0C9C1797FF4"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "Locus Filesystem Plugin"; + public virtual Guid Id => new Guid("1A70B30A-437D-479A-88E1-D0C9C1797FF4"); - public Locus(ImagePlugin imagePlugin, Partition partition, Encoding encoding) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { - Name = "Locus Filesystem Plugin"; - PluginUuid = new Guid("1A70B30A-437D-479A-88E1-D0C9C1797FF4"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) - { - if(imagePlugin.ImageInfo.SectorSize < 512) return false; + if(imagePlugin.Info.SectorSize < 512) return false; for(ulong location = 0; location <= 8; location++) { Locus_Superblock LocusSb = new Locus_Superblock(); - uint sbSize = (uint)(Marshal.SizeOf(LocusSb) / imagePlugin.ImageInfo.SectorSize); - if(Marshal.SizeOf(LocusSb) % imagePlugin.ImageInfo.SectorSize != 0) sbSize++; + uint sbSize = (uint)(Marshal.SizeOf(LocusSb) / imagePlugin.Info.SectorSize); + if(Marshal.SizeOf(LocusSb) % imagePlugin.Info.SectorSize != 0) sbSize++; - if(partition.Start + location + sbSize >= imagePlugin.ImageInfo.Sectors) break; + if(partition.Start + location + sbSize >= imagePlugin.Info.Sectors) break; byte[] sector = imagePlugin.ReadSectors(partition.Start + location, sbSize); if(sector.Length < Marshal.SizeOf(LocusSb)) return false; @@ -119,18 +106,19 @@ namespace DiscImageChef.Filesystems return false; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { + currentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); information = ""; - if(imagePlugin.ImageInfo.SectorSize < 512) return; + if(imagePlugin.Info.SectorSize < 512) return; Locus_Superblock LocusSb = new Locus_Superblock(); byte[] sector = null; for(ulong location = 0; location <= 8; location++) { - uint sbSize = (uint)(Marshal.SizeOf(LocusSb) / imagePlugin.ImageInfo.SectorSize); - if(Marshal.SizeOf(LocusSb) % imagePlugin.ImageInfo.SectorSize != 0) sbSize++; + uint sbSize = (uint)(Marshal.SizeOf(LocusSb) / imagePlugin.Info.SectorSize); + if(Marshal.SizeOf(LocusSb) % imagePlugin.Info.SectorSize != 0) sbSize++; sector = imagePlugin.ReadSectors(partition.Start + location, sbSize); if(sector.Length < Marshal.SizeOf(LocusSb)) return; @@ -161,8 +149,8 @@ namespace DiscImageChef.Filesystems int blockSize = LocusSb.s_version == LocusVersion.SB_SB4096 ? 4096 : 1024; - string s_fsmnt = StringHandlers.CToString(LocusSb.s_fsmnt, CurrentEncoding); - string s_fpack = StringHandlers.CToString(LocusSb.s_fpack, CurrentEncoding); + string s_fsmnt = StringHandlers.CToString(LocusSb.s_fsmnt, currentEncoding); + string s_fpack = StringHandlers.CToString(LocusSb.s_fpack, currentEncoding); DicConsole.DebugWriteLine("Locus plugin", "LocusSb.s_magic = 0x{0:X8}", LocusSb.s_magic); DicConsole.DebugWriteLine("Locus plugin", "LocusSb.s_gfs = {0}", LocusSb.s_gfs); @@ -215,7 +203,7 @@ namespace DiscImageChef.Filesystems information = sb.ToString(); - XmlFsType = new FileSystemType + xmlFsType = new FileSystemType { Type = "Locus filesystem", ClusterSize = blockSize, @@ -230,62 +218,57 @@ namespace DiscImageChef.Filesystems }; } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/MicroDOS.cs b/DiscImageChef.Filesystems/MicroDOS.cs index 3caee273..3bb242c9 100644 --- a/DiscImageChef.Filesystems/MicroDOS.cs +++ b/DiscImageChef.Filesystems/MicroDOS.cs @@ -42,37 +42,23 @@ namespace DiscImageChef.Filesystems { // Information from http://www.owg.ru/mkt/BK/MKDOS.TXT // Thanks to tarlabnor for translating it - public class MicroDOS : Filesystem + public class MicroDOS : IFilesystem { const ushort MAGIC = 0xA72E; const ushort MAGIC2 = 0x530C; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public MicroDOS() - { - Name = "MicroDOS file system"; - PluginUuid = new Guid("9F9A364A-1A27-48A3-B730-7A7122000324"); - CurrentEncoding = Encoding.GetEncoding("koi8-r"); - } + Encoding currentEncoding; + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "MicroDOS file system"; + public virtual Guid Id => new Guid("9F9A364A-1A27-48A3-B730-7A7122000324"); - public MicroDOS(Encoding encoding) - { - Name = "MicroDOS file system"; - PluginUuid = new Guid("9F9A364A-1A27-48A3-B730-7A7122000324"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("koi8-r"); - } - - public MicroDOS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) - { - Name = "MicroDOS file system"; - PluginUuid = new Guid("9F9A364A-1A27-48A3-B730-7A7122000324"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("koi8-r"); - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { if(1 + partition.Start >= partition.End) return false; - if(imagePlugin.ImageInfo.SectorSize < 512) return false; + if(imagePlugin.Info.SectorSize < 512) return false; byte[] bk0 = imagePlugin.ReadSector(0 + partition.Start); @@ -84,8 +70,10 @@ namespace DiscImageChef.Filesystems return block0.label == MAGIC && block0.mklabel == MAGIC2; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, + Encoding encoding) { + currentEncoding = encoding ?? Encoding.GetEncoding("koi8-r"); information = ""; StringBuilder sb = new StringBuilder(); @@ -104,7 +92,7 @@ namespace DiscImageChef.Filesystems sb.AppendFormat("Volume contains {0} files", block0.files).AppendLine(); sb.AppendFormat("First used block is {0}", block0.firstUsedBlock).AppendLine(); - XmlFsType = new FileSystemType + xmlFsType = new FileSystemType { Type = "MicroDOS", ClusterSize = 512, @@ -118,62 +106,57 @@ namespace DiscImageChef.Filesystems information = sb.ToString(); } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/MinixFS.cs b/DiscImageChef.Filesystems/MinixFS.cs index 609f99b7..ca7e1945 100644 --- a/DiscImageChef.Filesystems/MinixFS.cs +++ b/DiscImageChef.Filesystems/MinixFS.cs @@ -41,7 +41,7 @@ using Schemas; namespace DiscImageChef.Filesystems { // Information from the Linux kernel - public class MinixFS : Filesystem + public class MinixFS : IFilesystem { /// Minix v1, 14 char filenames const ushort MINIX_MAGIC = 0x137F; @@ -64,34 +64,20 @@ namespace DiscImageChef.Filesystems const ushort MINIX2_CIGAM2 = 0x7824; /// Minix v3, 60 char filenames const ushort MINIX3_CIGAM = 0x5A4D; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public MinixFS() - { - Name = "Minix Filesystem"; - PluginUuid = new Guid("FE248C3B-B727-4AE5-A39F-79EA9A07D4B3"); - CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); - } + Encoding currentEncoding; + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "Minix Filesystem"; + public virtual Guid Id => new Guid("FE248C3B-B727-4AE5-A39F-79EA9A07D4B3"); - public MinixFS(Encoding encoding) - { - Name = "Minix Filesystem"; - PluginUuid = new Guid("FE248C3B-B727-4AE5-A39F-79EA9A07D4B3"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } - - public MinixFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) - { - Name = "Minix Filesystem"; - PluginUuid = new Guid("FE248C3B-B727-4AE5-A39F-79EA9A07D4B3"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { uint sector = 2; uint offset = 0; - if(imagePlugin.ImageInfo.XmlMediaType == XmlMediaType.OpticalDisc) + if(imagePlugin.Info.XmlMediaType == XmlMediaType.OpticalDisc) { sector = 0; offset = 0x400; @@ -124,8 +110,10 @@ namespace DiscImageChef.Filesystems return false; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, + Encoding encoding) { + currentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); information = ""; StringBuilder sb = new StringBuilder(); @@ -133,7 +121,7 @@ namespace DiscImageChef.Filesystems uint sector = 2; uint offset = 0; - if(imagePlugin.ImageInfo.XmlMediaType == XmlMediaType.OpticalDisc) + if(imagePlugin.Info.XmlMediaType == XmlMediaType.OpticalDisc) { sector = 0; offset = 0x400; @@ -155,7 +143,7 @@ namespace DiscImageChef.Filesystems magic = BitConverter.ToUInt16(minixSbSector, 0x018); - XmlFsType = new FileSystemType(); + xmlFsType = new FileSystemType(); bool littleEndian; @@ -170,16 +158,16 @@ namespace DiscImageChef.Filesystems case MINIX3_MAGIC: case MINIX3_CIGAM: minixVersion = "Minix v3 filesystem"; - XmlFsType.Type = "Minix v3"; + xmlFsType.Type = "Minix v3"; break; case MINIX2_MAGIC: case MINIX2_CIGAM: minixVersion = "Minix 3 v2 filesystem"; - XmlFsType.Type = "Minix 3 v2"; + xmlFsType.Type = "Minix 3 v2"; break; default: minixVersion = "Minix 3 v1 filesystem"; - XmlFsType.Type = "Minix 3 v1"; + xmlFsType.Type = "Minix 3 v1"; break; } @@ -195,49 +183,49 @@ namespace DiscImageChef.Filesystems filenamesize = 14; minixVersion = "Minix v1 filesystem"; littleEndian = true; - XmlFsType.Type = "Minix v1"; + xmlFsType.Type = "Minix v1"; break; case MINIX_MAGIC2: filenamesize = 30; minixVersion = "Minix v1 filesystem"; littleEndian = true; - XmlFsType.Type = "Minix v1"; + xmlFsType.Type = "Minix v1"; break; case MINIX2_MAGIC: filenamesize = 14; minixVersion = "Minix v2 filesystem"; littleEndian = true; - XmlFsType.Type = "Minix v2"; + xmlFsType.Type = "Minix v2"; break; case MINIX2_MAGIC2: filenamesize = 30; minixVersion = "Minix v2 filesystem"; littleEndian = true; - XmlFsType.Type = "Minix v2"; + xmlFsType.Type = "Minix v2"; break; case MINIX_CIGAM: filenamesize = 14; minixVersion = "Minix v1 filesystem"; littleEndian = false; - XmlFsType.Type = "Minix v1"; + xmlFsType.Type = "Minix v1"; break; case MINIX_CIGAM2: filenamesize = 30; minixVersion = "Minix v1 filesystem"; littleEndian = false; - XmlFsType.Type = "Minix v1"; + xmlFsType.Type = "Minix v1"; break; case MINIX2_CIGAM: filenamesize = 14; minixVersion = "Minix v2 filesystem"; littleEndian = false; - XmlFsType.Type = "Minix v2"; + xmlFsType.Type = "Minix v2"; break; case MINIX2_CIGAM2: filenamesize = 30; minixVersion = "Minix v2 filesystem"; littleEndian = false; - XmlFsType.Type = "Minix v2"; + xmlFsType.Type = "Minix v2"; break; default: return; } @@ -277,8 +265,8 @@ namespace DiscImageChef.Filesystems sb.AppendFormat("{0} bytes maximum per file", mnxSb.s_max_size).AppendLine(); sb.AppendFormat("On-disk filesystem version: {0}", mnxSb.s_disk_version).AppendLine(); - XmlFsType.ClusterSize = mnxSb.s_blocksize; - XmlFsType.Clusters = mnxSb.s_zones > 0 ? mnxSb.s_zones : mnxSb.s_nzones; + xmlFsType.ClusterSize = mnxSb.s_blocksize; + xmlFsType.Clusters = mnxSb.s_zones > 0 ? mnxSb.s_zones : mnxSb.s_nzones; } else { @@ -310,68 +298,63 @@ namespace DiscImageChef.Filesystems //sb.AppendFormat("log2 of blocks/zone: {0}", mnx_sb.s_log_zone_size).AppendLine(); // Apparently 0 sb.AppendFormat("{0} bytes maximum per file", mnxSb.s_max_size).AppendLine(); sb.AppendFormat("Filesystem state: {0:X4}", mnxSb.s_state).AppendLine(); - XmlFsType.ClusterSize = 1024; - XmlFsType.Clusters = mnxSb.s_zones > 0 ? mnxSb.s_zones : mnxSb.s_nzones; + xmlFsType.ClusterSize = 1024; + xmlFsType.Clusters = mnxSb.s_zones > 0 ? mnxSb.s_zones : mnxSb.s_nzones; } information = sb.ToString(); } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/NILFS2.cs b/DiscImageChef.Filesystems/NILFS2.cs index 4f39a4d9..f563b39b 100644 --- a/DiscImageChef.Filesystems/NILFS2.cs +++ b/DiscImageChef.Filesystems/NILFS2.cs @@ -40,43 +40,30 @@ using Schemas; namespace DiscImageChef.Filesystems { - public class NILFS2 : Filesystem + public class NILFS2 : IFilesystem { const ushort NILFS2_MAGIC = 0x3434; const uint NILFS2_SUPER_OFFSET = 1024; - public NILFS2() - { - Name = "NILFS2 Plugin"; - PluginUuid = new Guid("35224226-C5CC-48B5-8FFD-3781E91E86B6"); - CurrentEncoding = Encoding.UTF8; - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public NILFS2(Encoding encoding) - { - Name = "NILFS2 Plugin"; - PluginUuid = new Guid("35224226-C5CC-48B5-8FFD-3781E91E86B6"); - CurrentEncoding = encoding ?? Encoding.UTF8; - } + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "NILFS2 Plugin"; + public virtual Guid Id => new Guid("35224226-C5CC-48B5-8FFD-3781E91E86B6"); - public NILFS2(ImagePlugin imagePlugin, Partition partition, Encoding encoding) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { - Name = "NILFS2 Plugin"; - PluginUuid = new Guid("35224226-C5CC-48B5-8FFD-3781E91E86B6"); - CurrentEncoding = encoding ?? Encoding.UTF8; - } + if(imagePlugin.Info.SectorSize < 512) return false; - public override bool Identify(ImagePlugin imagePlugin, Partition partition) - { - if(imagePlugin.ImageInfo.SectorSize < 512) return false; - - uint sbAddr = NILFS2_SUPER_OFFSET / imagePlugin.ImageInfo.SectorSize; + uint sbAddr = NILFS2_SUPER_OFFSET / imagePlugin.Info.SectorSize; if(sbAddr == 0) sbAddr = 1; NILFS2_Superblock nilfsSb = new NILFS2_Superblock(); - uint sbSize = (uint)(Marshal.SizeOf(nilfsSb) / imagePlugin.ImageInfo.SectorSize); - if(Marshal.SizeOf(nilfsSb) % imagePlugin.ImageInfo.SectorSize != 0) sbSize++; + uint sbSize = (uint)(Marshal.SizeOf(nilfsSb) / imagePlugin.Info.SectorSize); + if(Marshal.SizeOf(nilfsSb) % imagePlugin.Info.SectorSize != 0) sbSize++; if(partition.Start + sbAddr + sbSize >= partition.End) return false; @@ -91,18 +78,19 @@ namespace DiscImageChef.Filesystems return nilfsSb.magic == NILFS2_MAGIC; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { + currentEncoding = encoding ?? Encoding.UTF8; information = ""; - if(imagePlugin.ImageInfo.SectorSize < 512) return; + if(imagePlugin.Info.SectorSize < 512) return; - uint sbAddr = NILFS2_SUPER_OFFSET / imagePlugin.ImageInfo.SectorSize; + uint sbAddr = NILFS2_SUPER_OFFSET / imagePlugin.Info.SectorSize; if(sbAddr == 0) sbAddr = 1; NILFS2_Superblock nilfsSb = new NILFS2_Superblock(); - uint sbSize = (uint)(Marshal.SizeOf(nilfsSb) / imagePlugin.ImageInfo.SectorSize); - if(Marshal.SizeOf(nilfsSb) % imagePlugin.ImageInfo.SectorSize != 0) sbSize++; + uint sbSize = (uint)(Marshal.SizeOf(nilfsSb) / imagePlugin.Info.SectorSize); + if(Marshal.SizeOf(nilfsSb) % imagePlugin.Info.SectorSize != 0) sbSize++; byte[] sector = imagePlugin.ReadSectors(partition.Start + sbAddr, sbSize); if(sector.Length < Marshal.SizeOf(nilfsSb)) return; @@ -126,7 +114,7 @@ namespace DiscImageChef.Filesystems else sb.AppendFormat("Creator OS code: {0}", nilfsSb.creator_os).AppendLine(); sb.AppendFormat("{0} bytes per inode", nilfsSb.inode_size).AppendLine(); sb.AppendFormat("Volume UUID: {0}", nilfsSb.uuid).AppendLine(); - sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(nilfsSb.volume_name, CurrentEncoding)) + sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(nilfsSb.volume_name, currentEncoding)) .AppendLine(); sb.AppendFormat("Volume created on {0}", DateHandlers.UnixUnsignedToDateTime(nilfsSb.ctime)).AppendLine(); sb.AppendFormat("Volume last mounted on {0}", DateHandlers.UnixUnsignedToDateTime(nilfsSb.mtime)) @@ -136,77 +124,72 @@ namespace DiscImageChef.Filesystems information = sb.ToString(); - XmlFsType = new FileSystemType + xmlFsType = new FileSystemType { Type = "NILFS2 filesystem", ClusterSize = 1 << (int)(nilfsSb.log_block_size + 10), - VolumeName = StringHandlers.CToString(nilfsSb.volume_name, CurrentEncoding), + VolumeName = StringHandlers.CToString(nilfsSb.volume_name, currentEncoding), VolumeSerial = nilfsSb.uuid.ToString(), CreationDate = DateHandlers.UnixUnsignedToDateTime(nilfsSb.ctime), CreationDateSpecified = true, ModificationDate = DateHandlers.UnixUnsignedToDateTime(nilfsSb.wtime), ModificationDateSpecified = true }; - if(nilfsSb.creator_os == 0) XmlFsType.SystemIdentifier = "Linux"; - XmlFsType.Clusters = (long)nilfsSb.dev_size / XmlFsType.ClusterSize; + if(nilfsSb.creator_os == 0) xmlFsType.SystemIdentifier = "Linux"; + xmlFsType.Clusters = (long)nilfsSb.dev_size / xmlFsType.ClusterSize; } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/NTFS.cs b/DiscImageChef.Filesystems/NTFS.cs index 166600f5..a3c06f66 100644 --- a/DiscImageChef.Filesystems/NTFS.cs +++ b/DiscImageChef.Filesystems/NTFS.cs @@ -42,30 +42,16 @@ using Schemas; namespace DiscImageChef.Filesystems { // Information from Inside Windows NT - public class NTFS : Filesystem + public class NTFS : IFilesystem { - public NTFS() - { - Name = "New Technology File System (NTFS)"; - PluginUuid = new Guid("33513B2C-1e6d-4d21-a660-0bbc789c3871"); - CurrentEncoding = Encoding.Unicode; - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "New Technology File System (NTFS)"; + public virtual Guid Id => new Guid("33513B2C-1e6d-4d21-a660-0bbc789c3871"); - public NTFS(Encoding encoding) - { - Name = "New Technology File System (NTFS)"; - PluginUuid = new Guid("33513B2C-1e6d-4d21-a660-0bbc789c3871"); - CurrentEncoding = Encoding.Unicode; - } - - public NTFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) - { - Name = "New Technology File System (NTFS)"; - PluginUuid = new Guid("33513B2C-1e6d-4d21-a660-0bbc789c3871"); - CurrentEncoding = Encoding.Unicode; - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { if(2 + partition.Start >= partition.End) return false; @@ -93,8 +79,9 @@ namespace DiscImageChef.Filesystems return signature == 0xAA55; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { + currentEncoding = Encoding.Unicode; information = ""; StringBuilder sb = new StringBuilder(); @@ -138,11 +125,11 @@ namespace DiscImageChef.Filesystems sb.AppendFormat("Volume serial number: {0:X16}", ntfsBb.serial_no).AppendLine(); // sb.AppendFormat("Signature 2: 0x{0:X4}", ntfs_bb.signature2).AppendLine(); - XmlFsType = new FileSystemType(); + xmlFsType = new FileSystemType(); if(ntfsBb.jump[0] == 0xEB && ntfsBb.jump[1] > 0x4E && ntfsBb.jump[1] < 0x80 && ntfsBb.signature2 == 0xAA55) { - XmlFsType.Bootable = true; + xmlFsType.Bootable = true; Sha1Context sha1Ctx = new Sha1Context(); sha1Ctx.Init(); string bootChk = sha1Ctx.Data(ntfsBb.boot_code, out _); @@ -150,70 +137,65 @@ namespace DiscImageChef.Filesystems sb.AppendFormat("Boot code's SHA1: {0}", bootChk).AppendLine(); } - XmlFsType.ClusterSize = ntfsBb.spc * ntfsBb.bps; - XmlFsType.Clusters = ntfsBb.sectors / ntfsBb.spc; - XmlFsType.VolumeSerial = $"{ntfsBb.serial_no:X16}"; - XmlFsType.Type = "NTFS"; + xmlFsType.ClusterSize = ntfsBb.spc * ntfsBb.bps; + xmlFsType.Clusters = ntfsBb.sectors / ntfsBb.spc; + xmlFsType.VolumeSerial = $"{ntfsBb.serial_no:X16}"; + xmlFsType.Type = "NTFS"; information = sb.ToString(); } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/Nintendo.cs b/DiscImageChef.Filesystems/Nintendo.cs index 3560fb8b..f31f10aa 100644 --- a/DiscImageChef.Filesystems/Nintendo.cs +++ b/DiscImageChef.Filesystems/Nintendo.cs @@ -40,38 +40,25 @@ using Schemas; namespace DiscImageChef.Filesystems { - public class NintendoPlugin : Filesystem + public class NintendoPlugin : IFilesystem { - public NintendoPlugin() - { - Name = "Nintendo optical filesystems"; - PluginUuid = new Guid("4675fcb4-4418-4288-9e4a-33d6a4ac1126"); - CurrentEncoding = Encoding.GetEncoding("shift_jis"); - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public NintendoPlugin(Encoding encoding) - { - Name = "Nintendo optical filesystems"; - PluginUuid = new Guid("4675fcb4-4418-4288-9e4a-33d6a4ac1126"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("shift_jis"); - } + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "Nintendo optical filesystems"; + public virtual Guid Id => new Guid("4675fcb4-4418-4288-9e4a-33d6a4ac1126"); - public NintendoPlugin(ImagePlugin imagePlugin, Partition partition, Encoding encoding) - { - Name = "Nintendo optical filesystems"; - PluginUuid = new Guid("4675fcb4-4418-4288-9e4a-33d6a4ac1126"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("shift_jis"); - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { if(partition.Start != 0) return false; - if(imagePlugin.ImageInfo.Sectors * imagePlugin.ImageInfo.SectorSize < 0x50000) return false; + if(imagePlugin.Info.Sectors * imagePlugin.Info.SectorSize < 0x50000) return false; BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; - byte[] header = imagePlugin.ReadSectors(0, 0x50000 / imagePlugin.ImageInfo.SectorSize); + byte[] header = imagePlugin.ReadSectors(0, 0x50000 / imagePlugin.Info.SectorSize); uint magicGc = BigEndianBitConverter.ToUInt32(header, 0x1C); uint magicWii = BigEndianBitConverter.ToUInt32(header, 0x18); @@ -79,16 +66,17 @@ namespace DiscImageChef.Filesystems return magicGc == 0xC2339F3D || magicWii == 0x5D1C9EA3; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { + currentEncoding = encoding ?? Encoding.GetEncoding("shift_jis"); StringBuilder sbInformation = new StringBuilder(); information = ""; - XmlFsType = new FileSystemType(); + xmlFsType = new FileSystemType(); NintendoFields fields = new NintendoFields(); BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; - byte[] header = imagePlugin.ReadSectors(0, 0x50000 / imagePlugin.ImageInfo.SectorSize); + byte[] header = imagePlugin.ReadSectors(0, 0x50000 / imagePlugin.Info.SectorSize); bool wii = false; @@ -109,7 +97,7 @@ namespace DiscImageChef.Filesystems fields.StreamBufferSize = header[9]; byte[] temp = new byte[64]; Array.Copy(header, 0x20, temp, 0, 64); - fields.Title = StringHandlers.CToString(temp, CurrentEncoding); + fields.Title = StringHandlers.CToString(temp, currentEncoding); if(!wii) { @@ -303,12 +291,12 @@ namespace DiscImageChef.Filesystems .AppendLine(); information = sbInformation.ToString(); - XmlFsType.Bootable = true; - XmlFsType.Clusters = (long)(imagePlugin.ImageInfo.Sectors * imagePlugin.ImageInfo.SectorSize / 2048); - XmlFsType.ClusterSize = 2048; - XmlFsType.Type = wii ? "Nintendo Wii filesystem" : "Nintendo Gamecube filesystem"; - XmlFsType.VolumeName = fields.Title; - XmlFsType.VolumeSerial = fields.DiscId; + xmlFsType.Bootable = true; + xmlFsType.Clusters = (long)(imagePlugin.Info.Sectors * imagePlugin.Info.SectorSize / 2048); + xmlFsType.ClusterSize = 2048; + xmlFsType.Type = wii ? "Nintendo Wii filesystem" : "Nintendo Gamecube filesystem"; + xmlFsType.VolumeName = fields.Title; + xmlFsType.VolumeSerial = fields.DiscId; } static string DiscTypeToString(string discType) @@ -408,62 +396,57 @@ namespace DiscImageChef.Filesystems return $"unknown type {type}"; } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/ODS.cs b/DiscImageChef.Filesystems/ODS.cs index 26c5ea3b..26a16966 100644 --- a/DiscImageChef.Filesystems/ODS.cs +++ b/DiscImageChef.Filesystems/ODS.cs @@ -50,34 +50,21 @@ namespace DiscImageChef.Filesystems // There is an ODS with signature "DECFILES11A", yet to be seen // Time is a 64 bit unsigned integer, tenths of microseconds since 1858/11/17 00:00:00. // TODO: Implement checksum - public class ODS : Filesystem + public class ODS : IFilesystem { - public ODS() - { - Name = "Files-11 On-Disk Structure"; - PluginUuid = new Guid("de20633c-8021-4384-aeb0-83b0df14491f"); - CurrentEncoding = Encoding.GetEncoding("iso-8859-1"); - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public ODS(Encoding encoding) - { - Name = "Files-11 On-Disk Structure"; - PluginUuid = new Guid("de20633c-8021-4384-aeb0-83b0df14491f"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1"); - } + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "Files-11 On-Disk Structure"; + public virtual Guid Id => new Guid("de20633c-8021-4384-aeb0-83b0df14491f"); - public ODS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) - { - Name = "Files-11 On-Disk Structure"; - PluginUuid = new Guid("de20633c-8021-4384-aeb0-83b0df14491f"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1"); - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { if(2 + partition.Start >= partition.End) return false; - if(imagePlugin.ImageInfo.SectorSize < 512) return false; + if(imagePlugin.Info.SectorSize < 512) return false; byte[] magicB = new byte[12]; byte[] hbSector = imagePlugin.ReadSector(1 + partition.Start); @@ -90,7 +77,7 @@ namespace DiscImageChef.Filesystems if(magic == "DECFILE11A " || magic == "DECFILE11B ") return true; // Optical disc - if(imagePlugin.ImageInfo.XmlMediaType != XmlMediaType.OpticalDisc) return false; + if(imagePlugin.Info.XmlMediaType != XmlMediaType.OpticalDisc) return false; if(hbSector.Length < 0x400) return false; @@ -104,8 +91,9 @@ namespace DiscImageChef.Filesystems return magic == "DECFILE11A " || magic == "DECFILE11B "; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { + currentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1"); information = ""; StringBuilder sb = new StringBuilder(); @@ -118,7 +106,7 @@ namespace DiscImageChef.Filesystems handle.Free(); // Optical disc - if(imagePlugin.ImageInfo.XmlMediaType == XmlMediaType.OpticalDisc && + if(imagePlugin.Info.XmlMediaType == XmlMediaType.OpticalDisc && StringHandlers.CToString(homeblock.format) != "DECFILE11A " && StringHandlers.CToString(homeblock.format) != "DECFILE11B ") { @@ -142,7 +130,7 @@ namespace DiscImageChef.Filesystems if(homeblock.resfiles < 5 || homeblock.devtype != 0) sb.AppendLine("This volume may be corrupted."); sb.AppendFormat("Volume format is {0}", - StringHandlers.SpacePaddedToString(homeblock.format, CurrentEncoding)).AppendLine(); + StringHandlers.SpacePaddedToString(homeblock.format, currentEncoding)).AppendLine(); sb.AppendFormat("Volume is Level {0} revision {1}", (homeblock.struclev & 0xFF00) >> 8, homeblock.struclev & 0xFF).AppendLine(); sb.AppendFormat("Lowest structure in the volume is Level {0}, revision {1}", @@ -166,12 +154,12 @@ namespace DiscImageChef.Filesystems 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, - StringHandlers.SpacePaddedToString(homeblock.strucname, CurrentEncoding)).AppendLine(); + StringHandlers.SpacePaddedToString(homeblock.strucname, currentEncoding)).AppendLine(); sb.AppendFormat("Volume owner is \"{0}\" (ID 0x{1:X8})", - StringHandlers.SpacePaddedToString(homeblock.ownername, CurrentEncoding), + StringHandlers.SpacePaddedToString(homeblock.ownername, currentEncoding), homeblock.volowner).AppendLine(); sb.AppendFormat("Volume label: \"{0}\"", - StringHandlers.SpacePaddedToString(homeblock.volname, CurrentEncoding)).AppendLine(); + StringHandlers.SpacePaddedToString(homeblock.volname, currentEncoding)).AppendLine(); sb.AppendFormat("Drive serial number: 0x{0:X8}", homeblock.serialnum).AppendLine(); sb.AppendFormat("Volume was created on {0}", DateHandlers.VmsToDateTime(homeblock.credate)).AppendLine(); if(homeblock.revdate > 0) @@ -219,84 +207,79 @@ 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 FileSystemType + xmlFsType = new FileSystemType { Type = "FILES-11", ClusterSize = homeblock.cluster * 512, Clusters = (long)partition.Size / (homeblock.cluster * 512), - VolumeName = StringHandlers.SpacePaddedToString(homeblock.volname, CurrentEncoding), + VolumeName = StringHandlers.SpacePaddedToString(homeblock.volname, currentEncoding), VolumeSerial = $"{homeblock.serialnum:X8}" }; if(homeblock.credate > 0) { - XmlFsType.CreationDate = DateHandlers.VmsToDateTime(homeblock.credate); - XmlFsType.CreationDateSpecified = true; + xmlFsType.CreationDate = DateHandlers.VmsToDateTime(homeblock.credate); + xmlFsType.CreationDateSpecified = true; } if(homeblock.revdate > 0) { - XmlFsType.ModificationDate = DateHandlers.VmsToDateTime(homeblock.revdate); - XmlFsType.ModificationDateSpecified = true; + xmlFsType.ModificationDate = DateHandlers.VmsToDateTime(homeblock.revdate); + xmlFsType.ModificationDateSpecified = true; } information = sb.ToString(); } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/Opera.cs b/DiscImageChef.Filesystems/Opera.cs index 76b8ca6b..e2a989cf 100644 --- a/DiscImageChef.Filesystems/Opera.cs +++ b/DiscImageChef.Filesystems/Opera.cs @@ -40,32 +40,17 @@ using Schemas; namespace DiscImageChef.Filesystems { - public class OperaFS : Filesystem + public class OperaFS : IFilesystem { - public OperaFS() - { - Name = "Opera Filesystem Plugin"; - PluginUuid = new Guid("0ec84ec7-eae6-4196-83fe-943b3fe46dbd"); - CurrentEncoding = Encoding.ASCII; - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public OperaFS(Encoding encoding) - { - Name = "Opera Filesystem Plugin"; - PluginUuid = new Guid("0ec84ec7-eae6-4196-83fe-943b3fe46dbd"); - // TODO: Find correct default encoding - CurrentEncoding = Encoding.ASCII; - } + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "Opera Filesystem Plugin"; + public virtual Guid Id => new Guid("0ec84ec7-eae6-4196-83fe-943b3fe46dbd"); - public OperaFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) - { - Name = "Opera Filesystem Plugin"; - PluginUuid = new Guid("0ec84ec7-eae6-4196-83fe-943b3fe46dbd"); - // TODO: Find correct default encoding - CurrentEncoding = Encoding.ASCII; - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { if(2 + partition.Start >= partition.End) return false; @@ -82,8 +67,10 @@ namespace DiscImageChef.Filesystems return Encoding.ASCII.GetString(syncBytes) == "ZZZZZ"; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { + // TODO: Find correct default encoding + currentEncoding = Encoding.ASCII; information = ""; StringBuilder superBlockMetadata = new StringBuilder(); @@ -96,35 +83,35 @@ namespace DiscImageChef.Filesystems if(Encoding.ASCII.GetString(sb.sync_bytes) != "ZZZZZ") return; superBlockMetadata.AppendFormat("Opera filesystem disc.").AppendLine(); - if(!string.IsNullOrEmpty(StringHandlers.CToString(sb.volume_label, CurrentEncoding))) + if(!string.IsNullOrEmpty(StringHandlers.CToString(sb.volume_label, currentEncoding))) superBlockMetadata - .AppendFormat("Volume label: {0}", StringHandlers.CToString(sb.volume_label, CurrentEncoding)) + .AppendFormat("Volume label: {0}", StringHandlers.CToString(sb.volume_label, currentEncoding)) .AppendLine(); - if(!string.IsNullOrEmpty(StringHandlers.CToString(sb.volume_comment, CurrentEncoding))) + if(!string.IsNullOrEmpty(StringHandlers.CToString(sb.volume_comment, currentEncoding))) superBlockMetadata.AppendFormat("Volume comment: {0}", - StringHandlers.CToString(sb.volume_comment, CurrentEncoding)) + 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.ImageInfo.SectorSize == 2336 || imagePlugin.ImageInfo.SectorSize == 2352 || - imagePlugin.ImageInfo.SectorSize == 2448) + if(imagePlugin.Info.SectorSize == 2336 || imagePlugin.Info.SectorSize == 2352 || + imagePlugin.Info.SectorSize == 2448) { if(sb.block_size != 2048) superBlockMetadata .AppendFormat("WARNING: Filesystem indicates {0} bytes/block while device indicates {1} bytes/block", sb.block_size, 2048); } - else if(imagePlugin.ImageInfo.SectorSize != sb.block_size) + else if(imagePlugin.Info.SectorSize != sb.block_size) superBlockMetadata .AppendFormat("WARNING: Filesystem indicates {0} bytes/block while device indicates {1} bytes/block", - sb.block_size, imagePlugin.ImageInfo.SectorSize); + sb.block_size, imagePlugin.Info.SectorSize); superBlockMetadata .AppendFormat("Volume size: {0} blocks, {1} bytes", sb.block_count, sb.block_size * sb.block_count) .AppendLine(); - if((ulong)sb.block_count > imagePlugin.ImageInfo.Sectors) + if((ulong)sb.block_count > imagePlugin.Info.Sectors) superBlockMetadata .AppendFormat("WARNING: Filesystem indicates {0} blocks while device indicates {1} blocks", - sb.block_count, imagePlugin.ImageInfo.Sectors); + sb.block_count, imagePlugin.Info.Sectors); superBlockMetadata.AppendFormat("Root directory identifier: 0x{0:X8}", sb.root_dirid).AppendLine(); superBlockMetadata.AppendFormat("Root directory block size: {0} bytes", sb.rootdir_bsize).AppendLine(); superBlockMetadata.AppendFormat("Root directory size: {0} blocks, {1} bytes", sb.rootdir_blocks, @@ -133,71 +120,66 @@ namespace DiscImageChef.Filesystems information = superBlockMetadata.ToString(); - XmlFsType = new FileSystemType + xmlFsType = new FileSystemType { Type = "Opera", - VolumeName = StringHandlers.CToString(sb.volume_label, CurrentEncoding), + VolumeName = StringHandlers.CToString(sb.volume_label, currentEncoding), ClusterSize = sb.block_size, Clusters = sb.block_count }; } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/PCEngine.cs b/DiscImageChef.Filesystems/PCEngine.cs index 50210420..1226f26b 100644 --- a/DiscImageChef.Filesystems/PCEngine.cs +++ b/DiscImageChef.Filesystems/PCEngine.cs @@ -39,30 +39,16 @@ using Schemas; namespace DiscImageChef.Filesystems { - public class PCEnginePlugin : Filesystem + public class PCEnginePlugin : IFilesystem { - public PCEnginePlugin() - { - Name = "PC Engine CD Plugin"; - PluginUuid = new Guid("e5ee6d7c-90fa-49bd-ac89-14ef750b8af3"); - CurrentEncoding = Encoding.GetEncoding("shift_jis"); - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "PC Engine CD Plugin"; + public virtual Guid Id => new Guid("e5ee6d7c-90fa-49bd-ac89-14ef750b8af3"); - public PCEnginePlugin(Encoding encoding) - { - Name = "PC Engine CD Plugin"; - PluginUuid = new Guid("e5ee6d7c-90fa-49bd-ac89-14ef750b8af3"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("shift_jis"); - } - - public PCEnginePlugin(ImagePlugin imagePlugin, Partition partition, Encoding encoding) - { - Name = "PC Engine CD Plugin"; - PluginUuid = new Guid("e5ee6d7c-90fa-49bd-ac89-14ef750b8af3"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("shift_jis"); - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { if(2 + partition.Start >= partition.End) return false; @@ -74,73 +60,70 @@ namespace DiscImageChef.Filesystems return Encoding.ASCII.GetString(systemDescriptor) == "PC Engine CD-ROM SYSTEM"; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, + Encoding encoding) { + currentEncoding = encoding ?? Encoding.GetEncoding("shift_jis"); information = ""; - XmlFsType = new FileSystemType + xmlFsType = new FileSystemType { Type = "PC Engine filesystem", - Clusters = (long)((partition.End - partition.Start + 1) / imagePlugin.ImageInfo.SectorSize * 2048), + Clusters = (long)((partition.End - partition.Start + 1) / imagePlugin.Info.SectorSize * 2048), ClusterSize = 2048 }; } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/PFS.cs b/DiscImageChef.Filesystems/PFS.cs index ea9dc71c..40b82e25 100644 --- a/DiscImageChef.Filesystems/PFS.cs +++ b/DiscImageChef.Filesystems/PFS.cs @@ -40,7 +40,7 @@ using Schemas; namespace DiscImageChef.Filesystems { - public class PFS : Filesystem + public class PFS : IFilesystem { /// /// Identifier for AFS (PFS v1) @@ -63,28 +63,15 @@ namespace DiscImageChef.Filesystems /// const uint MUPFS_DISK = 0x6D755046; - public PFS() - { - Name = "Professional File System"; - PluginUuid = new Guid("68DE769E-D957-406A-8AE4-3781CA8CDA77"); - CurrentEncoding = Encoding.GetEncoding("iso-8859-1"); - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public PFS(Encoding encoding) - { - Name = "Professional File System"; - PluginUuid = new Guid("68DE769E-D957-406A-8AE4-3781CA8CDA77"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1"); - } + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "Professional File System"; + public virtual Guid Id => new Guid("68DE769E-D957-406A-8AE4-3781CA8CDA77"); - public PFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) - { - Name = "Professional File System"; - PluginUuid = new Guid("68DE769E-D957-406A-8AE4-3781CA8CDA77"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1"); - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { if(partition.Length < 3) return false; @@ -98,29 +85,30 @@ namespace DiscImageChef.Filesystems magic == MUPFS_DISK; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { + currentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1"); byte[] rootBlockSector = imagePlugin.ReadSector(2 + partition.Start); RootBlock rootBlock = BigEndianMarshal.ByteArrayToStructureBigEndian(rootBlockSector); StringBuilder sbInformation = new StringBuilder(); - XmlFsType = new FileSystemType(); + xmlFsType = new FileSystemType(); switch(rootBlock.diskType) { case AFS_DISK: case MUAF_DISK: sbInformation.Append("Professional File System v1"); - XmlFsType.Type = "PFS v1"; + xmlFsType.Type = "PFS v1"; break; case PFS2_DISK: sbInformation.Append("Professional File System v2"); - XmlFsType.Type = "PFS v2"; + xmlFsType.Type = "PFS v2"; break; case PFS_DISK: case MUPFS_DISK: sbInformation.Append("Professional File System v3"); - XmlFsType.Type = "PFS v3"; + xmlFsType.Type = "PFS v3"; break; } @@ -130,7 +118,7 @@ namespace DiscImageChef.Filesystems sbInformation.AppendLine(); sbInformation - .AppendFormat("Volume name: {0}", StringHandlers.PascalToString(rootBlock.diskname, CurrentEncoding)) + .AppendFormat("Volume name: {0}", StringHandlers.PascalToString(rootBlock.diskname, currentEncoding)) .AppendLine(); sbInformation.AppendFormat("Volume has {0} free sectors of {1}", rootBlock.blocksfree, rootBlock.diskSize) .AppendLine(); @@ -143,72 +131,67 @@ namespace DiscImageChef.Filesystems information = sbInformation.ToString(); - XmlFsType.CreationDate = + xmlFsType.CreationDate = DateHandlers.AmigaToDateTime(rootBlock.creationday, rootBlock.creationminute, rootBlock.creationtick); - XmlFsType.CreationDateSpecified = true; - XmlFsType.FreeClusters = rootBlock.blocksfree; - XmlFsType.FreeClustersSpecified = true; - XmlFsType.Clusters = rootBlock.diskSize; - XmlFsType.ClusterSize = (int)imagePlugin.ImageInfo.SectorSize; - XmlFsType.VolumeName = StringHandlers.PascalToString(rootBlock.diskname, CurrentEncoding); + xmlFsType.CreationDateSpecified = true; + xmlFsType.FreeClusters = rootBlock.blocksfree; + xmlFsType.FreeClustersSpecified = true; + xmlFsType.Clusters = rootBlock.diskSize; + xmlFsType.ClusterSize = (int)imagePlugin.Info.SectorSize; + xmlFsType.VolumeName = StringHandlers.PascalToString(rootBlock.diskname, currentEncoding); } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/ProDOS.cs b/DiscImageChef.Filesystems/ProDOS.cs index f7f1d878..66beb9ee 100644 --- a/DiscImageChef.Filesystems/ProDOS.cs +++ b/DiscImageChef.Filesystems/ProDOS.cs @@ -44,7 +44,7 @@ using Encoding = System.Text.Encoding; namespace DiscImageChef.Filesystems { // Information from Apple ProDOS 8 Technical Reference - public class ProDOSPlugin : Filesystem + public class ProDOSPlugin : IFilesystem { const byte EMPTY_STORAGE_TYPE = 0x00; /// @@ -84,30 +84,15 @@ namespace DiscImageChef.Filesystems const byte ENTRY_LENGTH = 0x27; const byte ENTRIES_PER_BLOCK = 0x0D; - public ProDOSPlugin() - { - Name = "Apple ProDOS filesystem"; - PluginUuid = new Guid("43874265-7B8A-4739-BCF7-07F80D5932BF"); - CurrentEncoding = new LisaRoman(); - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public ProDOSPlugin(Encoding encoding) - { - Name = "Apple ProDOS filesystem"; - PluginUuid = new Guid("43874265-7B8A-4739-BCF7-07F80D5932BF"); - // TODO: Until Apple ][ encoding is implemented - CurrentEncoding = new LisaRoman(); - } + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "Apple ProDOS filesystem"; + public virtual Guid Id => new Guid("43874265-7B8A-4739-BCF7-07F80D5932BF"); - public ProDOSPlugin(ImagePlugin imagePlugin, Partition partition, Encoding encoding) - { - Name = "Apple ProDOS filesystem"; - PluginUuid = new Guid("43874265-7B8A-4739-BCF7-07F80D5932BF"); - // TODO: Until Apple ][ encoding is implemented - CurrentEncoding = new LisaRoman(); - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { if(partition.Length < 3) return false; @@ -115,8 +100,8 @@ namespace DiscImageChef.Filesystems byte[] rootDirectoryKeyBlock = imagePlugin.ReadSector(2 + partition.Start); bool APMFromHDDOnCD = false; - if(imagePlugin.ImageInfo.SectorSize == 2352 || imagePlugin.ImageInfo.SectorSize == 2448 || - imagePlugin.ImageInfo.SectorSize == 2048) + if(imagePlugin.Info.SectorSize == 2352 || imagePlugin.Info.SectorSize == 2448 || + imagePlugin.Info.SectorSize == 2048) { byte[] tmp = imagePlugin.ReadSectors(partition.Start, 2); @@ -169,8 +154,10 @@ namespace DiscImageChef.Filesystems return totalBlocks <= partition.End - partition.Start + 1; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { + // TODO: Until Apple ][ encoding is implemented + currentEncoding = new LisaRoman(); StringBuilder sbInformation = new StringBuilder(); // Blocks 0 and 1 are boot code @@ -178,8 +165,8 @@ namespace DiscImageChef.Filesystems bool APMFromHDDOnCD = false; - if(imagePlugin.ImageInfo.SectorSize == 2352 || imagePlugin.ImageInfo.SectorSize == 2448 || - imagePlugin.ImageInfo.SectorSize == 2048) + if(imagePlugin.Info.SectorSize == 2352 || imagePlugin.Info.SectorSize == 2448 || + imagePlugin.Info.SectorSize == 2048) { byte[] tmp = imagePlugin.ReadSectors(partition.Start, 2); @@ -214,7 +201,7 @@ namespace DiscImageChef.Filesystems rootDirectoryKeyBlock.header.name_length = (byte)(rootDirectoryKeyBlockBytes[0x04] & NAME_LENGTH_MASK); byte[] temporal = new byte[rootDirectoryKeyBlock.header.name_length]; Array.Copy(rootDirectoryKeyBlockBytes, 0x05, temporal, 0, rootDirectoryKeyBlock.header.name_length); - rootDirectoryKeyBlock.header.volume_name = CurrentEncoding.GetString(temporal); + rootDirectoryKeyBlock.header.volume_name = currentEncoding.GetString(temporal); rootDirectoryKeyBlock.header.reserved = BitConverter.ToUInt64(rootDirectoryKeyBlockBytes, 0x14); ushort tempTimestampLeft = BitConverter.ToUInt16(rootDirectoryKeyBlockBytes, 0x1C); @@ -309,77 +296,72 @@ namespace DiscImageChef.Filesystems information = sbInformation.ToString(); - XmlFsType = new FileSystemType(); - XmlFsType.VolumeName = rootDirectoryKeyBlock.header.volume_name; + xmlFsType = new FileSystemType(); + xmlFsType.VolumeName = rootDirectoryKeyBlock.header.volume_name; if(dateCorrect) { - XmlFsType.CreationDate = rootDirectoryKeyBlock.header.creation_time; - XmlFsType.CreationDateSpecified = true; + xmlFsType.CreationDate = rootDirectoryKeyBlock.header.creation_time; + xmlFsType.CreationDateSpecified = true; } - XmlFsType.Files = rootDirectoryKeyBlock.header.file_count; - XmlFsType.FilesSpecified = true; - XmlFsType.Clusters = rootDirectoryKeyBlock.header.total_blocks; - XmlFsType.ClusterSize = (int)((partition.End - partition.Start + 1) * imagePlugin.ImageInfo.SectorSize / - (ulong)XmlFsType.Clusters); - XmlFsType.Type = "ProDOS"; + xmlFsType.Files = rootDirectoryKeyBlock.header.file_count; + xmlFsType.FilesSpecified = true; + xmlFsType.Clusters = rootDirectoryKeyBlock.header.total_blocks; + xmlFsType.ClusterSize = (int)((partition.End - partition.Start + 1) * imagePlugin.Info.SectorSize / + (ulong)xmlFsType.Clusters); + xmlFsType.Type = "ProDOS"; } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/QNX4.cs b/DiscImageChef.Filesystems/QNX4.cs index 578f293f..5e8ae5ac 100644 --- a/DiscImageChef.Filesystems/QNX4.cs +++ b/DiscImageChef.Filesystems/QNX4.cs @@ -41,35 +41,21 @@ using Schemas; namespace DiscImageChef.Filesystems { - public class QNX4 : Filesystem + public class QNX4 : IFilesystem { readonly byte[] QNX4_RootDir_Fname = {0x2F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - public QNX4() - { - Name = "QNX4 Plugin"; - PluginUuid = new Guid("E73A63FA-B5B0-48BF-BF82-DA5F0A8170D2"); - CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "QNX4 Plugin"; + public virtual Guid Id => new Guid("E73A63FA-B5B0-48BF-BF82-DA5F0A8170D2"); - public QNX4(Encoding encoding) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { - Name = "QNX4 Plugin"; - PluginUuid = new Guid("E73A63FA-B5B0-48BF-BF82-DA5F0A8170D2"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } - - public QNX4(ImagePlugin imagePlugin, Partition partition, Encoding encoding) - { - Name = "QNX4 Plugin"; - PluginUuid = new Guid("E73A63FA-B5B0-48BF-BF82-DA5F0A8170D2"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) - { - if(partition.Start + 1 >= imagePlugin.ImageInfo.Sectors) return false; + if(partition.Start + 1 >= imagePlugin.Info.Sectors) return false; byte[] sector = imagePlugin.ReadSector(partition.Start + 1); if(sector.Length < 512) return false; @@ -100,8 +86,10 @@ namespace DiscImageChef.Filesystems return true; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, + Encoding encoding) { + currentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); information = ""; byte[] sector = imagePlugin.ReadSector(partition.Start + 1); if(sector.Length < 512) return; @@ -189,7 +177,7 @@ namespace DiscImageChef.Filesystems information = $"QNX4 filesystem\nCreated on {DateHandlers.UnixUnsignedToDateTime(qnxSb.rootDir.di_ftime)}\n"; - XmlFsType = new FileSystemType + xmlFsType = new FileSystemType { Type = "QNX4 filesystem", Clusters = (long)partition.Length, @@ -199,65 +187,60 @@ namespace DiscImageChef.Filesystems ModificationDate = DateHandlers.UnixUnsignedToDateTime(qnxSb.rootDir.di_mtime), ModificationDateSpecified = true }; - XmlFsType.Bootable |= qnxSb.boot.di_size != 0 || qnxSb.altBoot.di_size != 0; + xmlFsType.Bootable |= qnxSb.boot.di_size != 0 || qnxSb.altBoot.di_size != 0; } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/QNX6.cs b/DiscImageChef.Filesystems/QNX6.cs index 05b4b9fb..8f69df89 100644 --- a/DiscImageChef.Filesystems/QNX6.cs +++ b/DiscImageChef.Filesystems/QNX6.cs @@ -40,37 +40,23 @@ using Schemas; namespace DiscImageChef.Filesystems { - public class QNX6 : Filesystem + public class QNX6 : IFilesystem { const uint QNX6_SUPER_BLOCK_SIZE = 0x1000; const uint QNX6_BOOT_BLOCKS_SIZE = 0x2000; const uint QNX6_MAGIC = 0x68191122; - public QNX6() - { - Name = "QNX6 Plugin"; - PluginUuid = new Guid("3E610EA2-4D08-4D70-8947-830CD4C74FC0"); - CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "QNX6 Plugin"; + public virtual Guid Id => new Guid("3E610EA2-4D08-4D70-8947-830CD4C74FC0"); - public QNX6(Encoding encoding) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { - Name = "QNX6 Plugin"; - PluginUuid = new Guid("3E610EA2-4D08-4D70-8947-830CD4C74FC0"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } - - public QNX6(ImagePlugin imagePlugin, Partition partition, Encoding encoding) - { - Name = "QNX6 Plugin"; - PluginUuid = new Guid("3E610EA2-4D08-4D70-8947-830CD4C74FC0"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) - { - uint sectors = QNX6_SUPER_BLOCK_SIZE / imagePlugin.ImageInfo.SectorSize; - uint bootSectors = QNX6_BOOT_BLOCKS_SIZE / imagePlugin.ImageInfo.SectorSize; + uint sectors = QNX6_SUPER_BLOCK_SIZE / imagePlugin.Info.SectorSize; + uint bootSectors = QNX6_BOOT_BLOCKS_SIZE / imagePlugin.Info.SectorSize; if(partition.Start + bootSectors + sectors >= partition.End) return false; @@ -93,12 +79,14 @@ namespace DiscImageChef.Filesystems return qnxSb.magic == QNX6_MAGIC || audiSb.magic == QNX6_MAGIC; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, + Encoding encoding) { + currentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); information = ""; StringBuilder sb = new StringBuilder(); - uint sectors = QNX6_SUPER_BLOCK_SIZE / imagePlugin.ImageInfo.SectorSize; - uint bootSectors = QNX6_BOOT_BLOCKS_SIZE / imagePlugin.ImageInfo.SectorSize; + uint sectors = QNX6_SUPER_BLOCK_SIZE / imagePlugin.Info.SectorSize; + uint bootSectors = QNX6_BOOT_BLOCKS_SIZE / imagePlugin.Info.SectorSize; byte[] audiSector = imagePlugin.ReadSectors(partition.Start, sectors); byte[] sector = imagePlugin.ReadSectors(partition.Start + bootSectors, sectors); @@ -129,7 +117,7 @@ namespace DiscImageChef.Filesystems audiSb.freeBlocks * audiSb.blockSize, audiSb.numBlocks, audiSb.numBlocks * audiSb.blockSize).AppendLine(); - XmlFsType = new FileSystemType + xmlFsType = new FileSystemType { Type = "QNX6 (Audi) filesystem", Clusters = audiSb.numBlocks, @@ -162,7 +150,7 @@ namespace DiscImageChef.Filesystems qnxSb.freeBlocks * qnxSb.blockSize, qnxSb.numBlocks, qnxSb.numBlocks * qnxSb.blockSize) .AppendLine(); - XmlFsType = new FileSystemType + xmlFsType = new FileSystemType { Type = "QNX6 filesystem", Clusters = qnxSb.numBlocks, @@ -183,62 +171,57 @@ namespace DiscImageChef.Filesystems information = sb.ToString(); } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/RBF.cs b/DiscImageChef.Filesystems/RBF.cs index 5996cf63..b0e83103 100644 --- a/DiscImageChef.Filesystems/RBF.cs +++ b/DiscImageChef.Filesystems/RBF.cs @@ -41,36 +41,23 @@ using Schemas; namespace DiscImageChef.Filesystems { - public class RBF : Filesystem + public class RBF : IFilesystem { /// Magic number for OS-9. Same for OS-9000? const uint RBF_SYNC = 0x4372757A; const uint RBF_CNYS = 0x7A757243; - public RBF() - { - Name = "OS-9 Random Block File Plugin"; - PluginUuid = new Guid("E864E45B-0B52-4D29-A858-7BDFA9199FB2"); - CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public RBF(Encoding encoding) - { - Name = "OS-9 Random Block File Plugin"; - PluginUuid = new Guid("E864E45B-0B52-4D29-A858-7BDFA9199FB2"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "OS-9 Random Block File Plugin"; + public virtual Guid Id => new Guid("E864E45B-0B52-4D29-A858-7BDFA9199FB2"); - public RBF(ImagePlugin imagePlugin, Partition partition, Encoding encoding) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { - Name = "OS-9 Random Block File Plugin"; - PluginUuid = new Guid("E864E45B-0B52-4D29-A858-7BDFA9199FB2"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) - { - if(imagePlugin.ImageInfo.SectorSize < 256) return false; + if(imagePlugin.Info.SectorSize < 256) return false; // Documentation says ID should be sector 0 // I've found that OS-9/X68000 has it on sector 4 @@ -79,10 +66,10 @@ namespace DiscImageChef.Filesystems { RBF_IdSector rbfSb = new RBF_IdSector(); - uint sbSize = (uint)(Marshal.SizeOf(rbfSb) / imagePlugin.ImageInfo.SectorSize); - if(Marshal.SizeOf(rbfSb) % imagePlugin.ImageInfo.SectorSize != 0) sbSize++; + uint sbSize = (uint)(Marshal.SizeOf(rbfSb) / imagePlugin.Info.SectorSize); + if(Marshal.SizeOf(rbfSb) % imagePlugin.Info.SectorSize != 0) sbSize++; - if(partition.Start + location + sbSize >= imagePlugin.ImageInfo.Sectors) break; + if(partition.Start + location + sbSize >= imagePlugin.Info.Sectors) break; byte[] sector = imagePlugin.ReadSectors(partition.Start + location, sbSize); if(sector.Length < Marshal.SizeOf(rbfSb)) return false; @@ -101,18 +88,19 @@ namespace DiscImageChef.Filesystems return false; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { + currentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); information = ""; - if(imagePlugin.ImageInfo.SectorSize < 256) return; + if(imagePlugin.Info.SectorSize < 256) return; RBF_IdSector rbfSb = new RBF_IdSector(); RBF_NewIdSector rbf9000Sb = new RBF_NewIdSector(); foreach(ulong location in new[] {0, 4, 15}) { - uint sbSize = (uint)(Marshal.SizeOf(rbfSb) / imagePlugin.ImageInfo.SectorSize); - if(Marshal.SizeOf(rbfSb) % imagePlugin.ImageInfo.SectorSize != 0) sbSize++; + uint sbSize = (uint)(Marshal.SizeOf(rbfSb) / imagePlugin.Info.SectorSize); + if(Marshal.SizeOf(rbfSb) % imagePlugin.Info.SectorSize != 0) sbSize++; byte[] sector = imagePlugin.ReadSectors(partition.Start + location, sbSize); if(sector.Length < Marshal.SizeOf(rbfSb)) return; @@ -166,10 +154,10 @@ namespace DiscImageChef.Filesystems .AppendLine(); sb.AppendFormat("Volume's identification block was last written on {0}", DateHandlers.UnixToDateTime(rbf9000Sb.rid_mtime)).AppendLine(); - sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(rbf9000Sb.rid_name, CurrentEncoding)) + sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(rbf9000Sb.rid_name, currentEncoding)) .AppendLine(); - XmlFsType = new FileSystemType + xmlFsType = new FileSystemType { Type = "OS-9 Random Block File", Bootable = rbf9000Sb.rid_bootfile > 0, @@ -179,7 +167,7 @@ namespace DiscImageChef.Filesystems CreationDateSpecified = true, ModificationDate = DateHandlers.UnixToDateTime(rbf9000Sb.rid_mtime), ModificationDateSpecified = true, - VolumeName = StringHandlers.CToString(rbf9000Sb.rid_name, CurrentEncoding), + VolumeName = StringHandlers.CToString(rbf9000Sb.rid_name, currentEncoding), VolumeSerial = $"{rbf9000Sb.rid_diskid:X8}" }; } @@ -210,12 +198,12 @@ namespace DiscImageChef.Filesystems sb.AppendFormat("Disk is owned by user {0}", rbfSb.dd_own).AppendLine(); sb.AppendFormat("Volume was created on {0}", DateHandlers.Os9ToDateTime(rbfSb.dd_dat)).AppendLine(); sb.AppendFormat("Volume attributes: {0:X2}", rbfSb.dd_att).AppendLine(); - sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(rbfSb.dd_nam, CurrentEncoding)) + sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(rbfSb.dd_nam, currentEncoding)) .AppendLine(); - sb.AppendFormat("Path descriptor options: {0}", StringHandlers.CToString(rbfSb.dd_opt, CurrentEncoding)) + sb.AppendFormat("Path descriptor options: {0}", StringHandlers.CToString(rbfSb.dd_opt, currentEncoding)) .AppendLine(); - XmlFsType = new FileSystemType + xmlFsType = new FileSystemType { Type = "OS-9 Random Block File", Bootable = LSNToUInt32(rbfSb.dd_bt) > 0 && rbfSb.dd_bsz > 0, @@ -223,7 +211,7 @@ namespace DiscImageChef.Filesystems Clusters = LSNToUInt32(rbfSb.dd_tot), CreationDate = DateHandlers.Os9ToDateTime(rbfSb.dd_dat), CreationDateSpecified = true, - VolumeName = StringHandlers.CToString(rbfSb.dd_nam, CurrentEncoding), + VolumeName = StringHandlers.CToString(rbfSb.dd_nam, currentEncoding), VolumeSerial = $"{rbfSb.dd_dsk:X4}" }; } @@ -238,62 +226,57 @@ namespace DiscImageChef.Filesystems return (uint)((lsn[0] << 16) + (lsn[1] << 8) + lsn[2]); } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/RT11.cs b/DiscImageChef.Filesystems/RT11.cs index 9073a80c..a31058c0 100644 --- a/DiscImageChef.Filesystems/RT11.cs +++ b/DiscImageChef.Filesystems/RT11.cs @@ -42,34 +42,21 @@ namespace DiscImageChef.Filesystems { // Information from http://www.trailing-edge.com/~shoppa/rt11fs/ // TODO: Implement Radix-50 - public class RT11 : Filesystem + public class RT11 : IFilesystem { - public RT11() - { - Name = "RT-11 file system"; - PluginUuid = new Guid("DB3E2F98-8F98-463C-8126-E937843DA024"); - CurrentEncoding = Encoding.GetEncoding("iso-8859-1"); - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public RT11(Encoding encoding) - { - Name = "RT-11 file system"; - PluginUuid = new Guid("DB3E2F98-8F98-463C-8126-E937843DA024"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1"); - } + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "RT-11 file system"; + public virtual Guid Id => new Guid("DB3E2F98-8F98-463C-8126-E937843DA024"); - public RT11(ImagePlugin imagePlugin, Partition partition, Encoding encoding) - { - Name = "RT-11 file system"; - PluginUuid = new Guid("DB3E2F98-8F98-463C-8126-E937843DA024"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1"); - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { if(1 + partition.Start >= partition.End) return false; - if(imagePlugin.ImageInfo.SectorSize < 512) return false; + if(imagePlugin.Info.SectorSize < 512) return false; byte[] magicB = new byte[12]; byte[] hbSector = imagePlugin.ReadSector(1 + partition.Start); @@ -80,8 +67,9 @@ namespace DiscImageChef.Filesystems return magic == "DECRT11A "; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { + currentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1"); information = ""; StringBuilder sb = new StringBuilder(); @@ -106,86 +94,81 @@ namespace DiscImageChef.Filesystems for(int i = 0; i < 512; i += 2) check += BitConverter.ToUInt16(hbSector, i); sb.AppendFormat("Volume format is {0}", - StringHandlers.SpacePaddedToString(homeblock.format, CurrentEncoding)).AppendLine(); + StringHandlers.SpacePaddedToString(homeblock.format, currentEncoding)).AppendLine(); sb.AppendFormat("{0} sectors per cluster ({1} bytes)", homeblock.cluster, homeblock.cluster * 512) .AppendLine(); sb.AppendFormat("First directory segment starts at block {0}", homeblock.rootBlock).AppendLine(); sb.AppendFormat("Volume owner is \"{0}\"", - StringHandlers.SpacePaddedToString(homeblock.ownername, CurrentEncoding)).AppendLine(); + StringHandlers.SpacePaddedToString(homeblock.ownername, currentEncoding)).AppendLine(); sb.AppendFormat("Volume label: \"{0}\"", - StringHandlers.SpacePaddedToString(homeblock.volname, CurrentEncoding)).AppendLine(); + StringHandlers.SpacePaddedToString(homeblock.volname, currentEncoding)).AppendLine(); sb.AppendFormat("Checksum: 0x{0:X4} (calculated 0x{1:X4})", homeblock.checksum, check).AppendLine(); byte[] bootBlock = imagePlugin.ReadSector(0); - XmlFsType = new FileSystemType + xmlFsType = new FileSystemType { Type = "RT-11", ClusterSize = homeblock.cluster * 512, Clusters = homeblock.cluster, - VolumeName = StringHandlers.SpacePaddedToString(homeblock.volname, CurrentEncoding), + VolumeName = StringHandlers.SpacePaddedToString(homeblock.volname, currentEncoding), Bootable = !ArrayHelpers.ArrayIsNullOrEmpty(bootBlock) }; information = sb.ToString(); } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/Reiser.cs b/DiscImageChef.Filesystems/Reiser.cs index 1bfc1968..acdaa343 100644 --- a/DiscImageChef.Filesystems/Reiser.cs +++ b/DiscImageChef.Filesystems/Reiser.cs @@ -41,7 +41,7 @@ using Schemas; namespace DiscImageChef.Filesystems { - public class Reiser : Filesystem + public class Reiser : IFilesystem { const uint REISER_SUPER_OFFSET = 0x10000; @@ -49,38 +49,25 @@ namespace DiscImageChef.Filesystems readonly byte[] Reiser36_Magic = {0x52, 0x65, 0x49, 0x73, 0x45, 0x72, 0x32, 0x46, 0x73, 0x00}; readonly byte[] ReiserJr_Magic = {0x52, 0x65, 0x49, 0x73, 0x45, 0x72, 0x33, 0x46, 0x73, 0x00}; - public Reiser() - { - Name = "Reiser Filesystem Plugin"; - PluginUuid = new Guid("1D8CD8B8-27E6-410F-9973-D16409225FBA"); - CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public Reiser(Encoding encoding) - { - Name = "Reiser Filesystem Plugin"; - PluginUuid = new Guid("1D8CD8B8-27E6-410F-9973-D16409225FBA"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "Reiser Filesystem Plugin"; + public virtual Guid Id => new Guid("1D8CD8B8-27E6-410F-9973-D16409225FBA"); - public Reiser(ImagePlugin imagePlugin, Partition partition, Encoding encoding) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { - Name = "Reiser Filesystem Plugin"; - PluginUuid = new Guid("1D8CD8B8-27E6-410F-9973-D16409225FBA"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } + if(imagePlugin.Info.SectorSize < 512) return false; - public override bool Identify(ImagePlugin imagePlugin, Partition partition) - { - if(imagePlugin.ImageInfo.SectorSize < 512) return false; - - uint sbAddr = REISER_SUPER_OFFSET / imagePlugin.ImageInfo.SectorSize; + uint sbAddr = REISER_SUPER_OFFSET / imagePlugin.Info.SectorSize; if(sbAddr == 0) sbAddr = 1; Reiser_Superblock reiserSb = new Reiser_Superblock(); - uint sbSize = (uint)(Marshal.SizeOf(reiserSb) / imagePlugin.ImageInfo.SectorSize); - if(Marshal.SizeOf(reiserSb) % imagePlugin.ImageInfo.SectorSize != 0) sbSize++; + uint sbSize = (uint)(Marshal.SizeOf(reiserSb) / imagePlugin.Info.SectorSize); + if(Marshal.SizeOf(reiserSb) % imagePlugin.Info.SectorSize != 0) sbSize++; if(partition.Start + sbAddr + sbSize >= partition.End) return false; @@ -96,18 +83,19 @@ namespace DiscImageChef.Filesystems ReiserJr_Magic.SequenceEqual(reiserSb.magic); } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { + currentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); information = ""; - if(imagePlugin.ImageInfo.SectorSize < 512) return; + if(imagePlugin.Info.SectorSize < 512) return; - uint sbAddr = REISER_SUPER_OFFSET / imagePlugin.ImageInfo.SectorSize; + uint sbAddr = REISER_SUPER_OFFSET / imagePlugin.Info.SectorSize; if(sbAddr == 0) sbAddr = 1; Reiser_Superblock reiserSb = new Reiser_Superblock(); - uint sbSize = (uint)(Marshal.SizeOf(reiserSb) / imagePlugin.ImageInfo.SectorSize); - if(Marshal.SizeOf(reiserSb) % imagePlugin.ImageInfo.SectorSize != 0) sbSize++; + uint sbSize = (uint)(Marshal.SizeOf(reiserSb) / imagePlugin.Info.SectorSize); + if(Marshal.SizeOf(reiserSb) % imagePlugin.Info.SectorSize != 0) sbSize++; byte[] sector = imagePlugin.ReadSectors(partition.Start + sbAddr, sbSize); if(sector.Length < Marshal.SizeOf(reiserSb)) return; @@ -135,82 +123,77 @@ namespace DiscImageChef.Filesystems if(reiserSb.version >= 2) { sb.AppendFormat("Volume UUID: {0}", reiserSb.uuid).AppendLine(); - sb.AppendFormat("Volume name: {0}", CurrentEncoding.GetString(reiserSb.label)).AppendLine(); + sb.AppendFormat("Volume name: {0}", currentEncoding.GetString(reiserSb.label)).AppendLine(); } information = sb.ToString(); - XmlFsType = new FileSystemType(); - if(Reiser35_Magic.SequenceEqual(reiserSb.magic)) XmlFsType.Type = "Reiser 3.5 filesystem"; - else if(Reiser36_Magic.SequenceEqual(reiserSb.magic)) XmlFsType.Type = "Reiser 3.6 filesystem"; - else if(ReiserJr_Magic.SequenceEqual(reiserSb.magic)) XmlFsType.Type = "Reiser Jr. filesystem"; - XmlFsType.ClusterSize = reiserSb.blocksize; - XmlFsType.Clusters = reiserSb.block_count; - XmlFsType.FreeClusters = reiserSb.free_blocks; - XmlFsType.FreeClustersSpecified = true; - XmlFsType.Dirty = reiserSb.umount_state == 2; + xmlFsType = new FileSystemType(); + if(Reiser35_Magic.SequenceEqual(reiserSb.magic)) xmlFsType.Type = "Reiser 3.5 filesystem"; + else if(Reiser36_Magic.SequenceEqual(reiserSb.magic)) xmlFsType.Type = "Reiser 3.6 filesystem"; + else if(ReiserJr_Magic.SequenceEqual(reiserSb.magic)) xmlFsType.Type = "Reiser Jr. filesystem"; + xmlFsType.ClusterSize = reiserSb.blocksize; + xmlFsType.Clusters = reiserSb.block_count; + xmlFsType.FreeClusters = reiserSb.free_blocks; + xmlFsType.FreeClustersSpecified = true; + xmlFsType.Dirty = reiserSb.umount_state == 2; if(reiserSb.version < 2) return; - XmlFsType.VolumeName = CurrentEncoding.GetString(reiserSb.label); - XmlFsType.VolumeSerial = reiserSb.uuid.ToString(); + xmlFsType.VolumeName = currentEncoding.GetString(reiserSb.label); + xmlFsType.VolumeSerial = reiserSb.uuid.ToString(); } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/Reiser4.cs b/DiscImageChef.Filesystems/Reiser4.cs index 6aabe4b3..b87a5cc4 100644 --- a/DiscImageChef.Filesystems/Reiser4.cs +++ b/DiscImageChef.Filesystems/Reiser4.cs @@ -41,45 +41,32 @@ using Schemas; namespace DiscImageChef.Filesystems { - public class Reiser4 : Filesystem + public class Reiser4 : IFilesystem { const uint REISER4_SUPER_OFFSET = 0x10000; readonly byte[] Reiser4_Magic = {0x52, 0x65, 0x49, 0x73, 0x45, 0x72, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - public Reiser4() - { - Name = "Reiser4 Filesystem Plugin"; - PluginUuid = new Guid("301F2D00-E8D5-4F04-934E-81DFB21D15BA"); - CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public Reiser4(Encoding encoding) - { - Name = "Reiser4 Filesystem Plugin"; - PluginUuid = new Guid("301F2D00-E8D5-4F04-934E-81DFB21D15BA"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "Reiser4 Filesystem Plugin"; + public virtual Guid Id => new Guid("301F2D00-E8D5-4F04-934E-81DFB21D15BA"); - public Reiser4(ImagePlugin imagePlugin, Partition partition, Encoding encoding) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { - Name = "Reiser4 Filesystem Plugin"; - PluginUuid = new Guid("301F2D00-E8D5-4F04-934E-81DFB21D15BA"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } + if(imagePlugin.Info.SectorSize < 512) return false; - public override bool Identify(ImagePlugin imagePlugin, Partition partition) - { - if(imagePlugin.ImageInfo.SectorSize < 512) return false; - - uint sbAddr = REISER4_SUPER_OFFSET / imagePlugin.ImageInfo.SectorSize; + uint sbAddr = REISER4_SUPER_OFFSET / imagePlugin.Info.SectorSize; if(sbAddr == 0) sbAddr = 1; Reiser4_Superblock reiserSb = new Reiser4_Superblock(); - uint sbSize = (uint)(Marshal.SizeOf(reiserSb) / imagePlugin.ImageInfo.SectorSize); - if(Marshal.SizeOf(reiserSb) % imagePlugin.ImageInfo.SectorSize != 0) sbSize++; + uint sbSize = (uint)(Marshal.SizeOf(reiserSb) / imagePlugin.Info.SectorSize); + if(Marshal.SizeOf(reiserSb) % imagePlugin.Info.SectorSize != 0) sbSize++; if(partition.Start + sbAddr + sbSize >= partition.End) return false; @@ -94,18 +81,19 @@ namespace DiscImageChef.Filesystems return Reiser4_Magic.SequenceEqual(reiserSb.magic); } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { + currentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); information = ""; - if(imagePlugin.ImageInfo.SectorSize < 512) return; + if(imagePlugin.Info.SectorSize < 512) return; - uint sbAddr = REISER4_SUPER_OFFSET / imagePlugin.ImageInfo.SectorSize; + uint sbAddr = REISER4_SUPER_OFFSET / imagePlugin.Info.SectorSize; if(sbAddr == 0) sbAddr = 1; Reiser4_Superblock reiserSb = new Reiser4_Superblock(); - uint sbSize = (uint)(Marshal.SizeOf(reiserSb) / imagePlugin.ImageInfo.SectorSize); - if(Marshal.SizeOf(reiserSb) % imagePlugin.ImageInfo.SectorSize != 0) sbSize++; + uint sbSize = (uint)(Marshal.SizeOf(reiserSb) / imagePlugin.Info.SectorSize); + if(Marshal.SizeOf(reiserSb) % imagePlugin.Info.SectorSize != 0) sbSize++; byte[] sector = imagePlugin.ReadSectors(partition.Start + sbAddr, sbSize); if(sector.Length < Marshal.SizeOf(reiserSb)) return; @@ -123,77 +111,71 @@ namespace DiscImageChef.Filesystems sb.AppendFormat("{0} bytes per block", reiserSb.blocksize).AppendLine(); sb.AppendFormat("Volume disk format: {0}", reiserSb.diskformat).AppendLine(); sb.AppendFormat("Volume UUID: {0}", reiserSb.uuid).AppendLine(); - sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(reiserSb.label, CurrentEncoding)).AppendLine(); + sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(reiserSb.label, currentEncoding)).AppendLine(); information = sb.ToString(); - XmlFsType = new FileSystemType + xmlFsType = new FileSystemType { Type = "Reiser 4 filesystem", ClusterSize = reiserSb.blocksize, - Clusters = - (long)((partition.End - partition.Start) * imagePlugin.ImageInfo.SectorSize / reiserSb.blocksize), - VolumeName = StringHandlers.CToString(reiserSb.label, CurrentEncoding), + Clusters = (long)((partition.End - partition.Start) * imagePlugin.Info.SectorSize / reiserSb.blocksize), + VolumeName = StringHandlers.CToString(reiserSb.label, currentEncoding), VolumeSerial = reiserSb.uuid.ToString() }; } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/SFS.cs b/DiscImageChef.Filesystems/SFS.cs index 5010b687..ca9450ff 100644 --- a/DiscImageChef.Filesystems/SFS.cs +++ b/DiscImageChef.Filesystems/SFS.cs @@ -40,35 +40,21 @@ using Schemas; namespace DiscImageChef.Filesystems { - public class SFS : Filesystem + public class SFS : IFilesystem { /// Identifier for SFS v1 const uint SFS_MAGIC = 0x53465300; /// Identifier for SFS v2 const uint SFS2_MAGIC = 0x53465302; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public SFS() - { - Name = "SmartFileSystem"; - PluginUuid = new Guid("26550C19-3671-4A2D-BC2F-F20CEB7F48DC"); - CurrentEncoding = Encoding.GetEncoding("iso-8859-1"); - } + Encoding currentEncoding; + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "SmartFileSystem"; + public virtual Guid Id => new Guid("26550C19-3671-4A2D-BC2F-F20CEB7F48DC"); - public SFS(Encoding encoding) - { - Name = "SmartFileSystem"; - PluginUuid = new Guid("26550C19-3671-4A2D-BC2F-F20CEB7F48DC"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1"); - } - - public SFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) - { - Name = "SmartFileSystem"; - PluginUuid = new Guid("26550C19-3671-4A2D-BC2F-F20CEB7F48DC"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1"); - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { if(partition.Start >= partition.End) return false; @@ -81,8 +67,9 @@ namespace DiscImageChef.Filesystems return magic == SFS_MAGIC || magic == SFS2_MAGIC; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { + currentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1"); byte[] rootBlockSector = imagePlugin.ReadSector(partition.Start); RootBlock rootBlock = BigEndianMarshal.ByteArrayToStructureBigEndian(rootBlockSector); @@ -113,7 +100,7 @@ namespace DiscImageChef.Filesystems sbInformation.AppendLine("Volume moves deleted files to a recycled folder"); information = sbInformation.ToString(); - XmlFsType = new FileSystemType + xmlFsType = new FileSystemType { CreationDate = DateHandlers.UnixUnsignedToDateTime(rootBlock.datecreated).AddYears(8), CreationDateSpecified = true, @@ -123,62 +110,57 @@ namespace DiscImageChef.Filesystems }; } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/SolarFS.cs b/DiscImageChef.Filesystems/SolarFS.cs index 1b539dd3..cae88207 100644 --- a/DiscImageChef.Filesystems/SolarFS.cs +++ b/DiscImageChef.Filesystems/SolarFS.cs @@ -41,30 +41,17 @@ using Schemas; namespace DiscImageChef.Filesystems { // Based on FAT's BPB, cannot find a FAT or directory - public class SolarFS : Filesystem + public class SolarFS : IFilesystem { - public SolarFS() - { - Name = "Solar_OS filesystem"; - PluginUuid = new Guid("EA3101C1-E777-4B4F-B5A3-8C57F50F6E65"); - CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public SolarFS(Encoding encoding) - { - Name = "Solar_OS filesystem"; - PluginUuid = new Guid("EA3101C1-E777-4B4F-B5A3-8C57F50F6E65"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "Solar_OS filesystem"; + public virtual Guid Id => new Guid("EA3101C1-E777-4B4F-B5A3-8C57F50F6E65"); - public SolarFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) - { - Name = "Solar_OS filesystem"; - PluginUuid = new Guid("EA3101C1-E777-4B4F-B5A3-8C57F50F6E65"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { if(2 + partition.Start >= partition.End) return false; @@ -81,8 +68,9 @@ namespace DiscImageChef.Filesystems return signature == 0x29 && fsType == "SOL_FS "; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { + currentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); information = ""; StringBuilder sb = new StringBuilder(); @@ -104,10 +92,10 @@ namespace DiscImageChef.Filesystems bpb.OEMName = StringHandlers.CToString(bpbStrings); bpbStrings = new byte[8]; Array.Copy(bpbSector, 0x2A, bpbStrings, 0, 11); - bpb.vol_name = StringHandlers.CToString(bpbStrings, CurrentEncoding); + bpb.vol_name = StringHandlers.CToString(bpbStrings, currentEncoding); bpbStrings = new byte[8]; Array.Copy(bpbSector, 0x35, bpbStrings, 0, 8); - bpb.fs_type = StringHandlers.CToString(bpbStrings, CurrentEncoding); + bpb.fs_type = StringHandlers.CToString(bpbStrings, currentEncoding); bpb.x86_jump = new byte[3]; Array.Copy(bpbSector, 0x00, bpb.x86_jump, 0, 3); @@ -141,27 +129,27 @@ namespace DiscImageChef.Filesystems sb.AppendLine("Solar_OS filesystem"); sb.AppendFormat("Media descriptor: 0x{0:X2}", bpb.media).AppendLine(); sb.AppendFormat("{0} bytes per sector", bpb.bps).AppendLine(); - if(imagePlugin.ImageInfo.SectorSize == 2336 || imagePlugin.ImageInfo.SectorSize == 2352 || - imagePlugin.ImageInfo.SectorSize == 2448) + if(imagePlugin.Info.SectorSize == 2336 || imagePlugin.Info.SectorSize == 2352 || + imagePlugin.Info.SectorSize == 2448) { - if(bpb.bps != imagePlugin.ImageInfo.SectorSize) + if(bpb.bps != imagePlugin.Info.SectorSize) sb .AppendFormat("WARNING: Filesystem describes a {0} bytes/sector, while device describes a {1} bytes/sector", bpb.bps, 2048).AppendLine(); } - else if(bpb.bps != imagePlugin.ImageInfo.SectorSize) + else if(bpb.bps != imagePlugin.Info.SectorSize) sb .AppendFormat("WARNING: Filesystem describes a {0} bytes/sector, while device describes a {1} bytes/sector", - bpb.bps, imagePlugin.ImageInfo.SectorSize).AppendLine(); + bpb.bps, imagePlugin.Info.SectorSize).AppendLine(); sb.AppendFormat("{0} sectors on volume ({1} bytes)", bpb.sectors, bpb.sectors * bpb.bps).AppendLine(); - if(bpb.sectors > imagePlugin.ImageInfo.Sectors) + if(bpb.sectors > imagePlugin.Info.Sectors) sb.AppendFormat("WARNING: Filesystem describes a {0} sectors volume, bigger than device ({1} sectors)", - bpb.sectors, imagePlugin.ImageInfo.Sectors); + bpb.sectors, imagePlugin.Info.Sectors); sb.AppendFormat("{0} heads", bpb.heads).AppendLine(); sb.AppendFormat("{0} sectors per track", bpb.sptrk).AppendLine(); sb.AppendFormat("Volume name: {0}", bpb.vol_name).AppendLine(); - XmlFsType = new FileSystemType + xmlFsType = new FileSystemType { Type = "SolarFS", Clusters = bpb.sectors, @@ -172,62 +160,57 @@ namespace DiscImageChef.Filesystems information = sb.ToString(); } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/Squash.cs b/DiscImageChef.Filesystems/Squash.cs index 3e598751..baf1ac04 100644 --- a/DiscImageChef.Filesystems/Squash.cs +++ b/DiscImageChef.Filesystems/Squash.cs @@ -40,7 +40,7 @@ using Schemas; namespace DiscImageChef.Filesystems { - public class Squash : Filesystem + public class Squash : IFilesystem { /// /// Identifier for Squash @@ -48,28 +48,14 @@ namespace DiscImageChef.Filesystems const uint SQUASH_MAGIC = 0x73717368; const uint SQUASH_CIGAM = 0x68737173; - public Squash() - { - Name = "Squash filesystem"; - PluginUuid = new Guid("F8F6E46F-7A2A-48E3-9C0A-46AF4DC29E09"); - CurrentEncoding = Encoding.UTF8; - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "Squash filesystem"; + public virtual Guid Id => new Guid("F8F6E46F-7A2A-48E3-9C0A-46AF4DC29E09"); - public Squash(Encoding encoding) - { - Name = "Squash filesystem"; - PluginUuid = new Guid("F8F6E46F-7A2A-48E3-9C0A-46AF4DC29E09"); - CurrentEncoding = encoding ?? Encoding.UTF8; - } - - public Squash(ImagePlugin imagePlugin, Partition partition, Encoding encoding) - { - Name = "Squash filesystem"; - PluginUuid = new Guid("F8F6E46F-7A2A-48E3-9C0A-46AF4DC29E09"); - CurrentEncoding = encoding ?? Encoding.UTF8; - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { if(partition.Start >= partition.End) return false; @@ -80,8 +66,10 @@ namespace DiscImageChef.Filesystems return magic == SQUASH_MAGIC || magic == SQUASH_CIGAM; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, + Encoding encoding) { + currentEncoding = encoding ?? Encoding.UTF8; byte[] sector = imagePlugin.ReadSector(partition.Start); uint magic = BitConverter.ToUInt32(sector, 0x00); @@ -140,13 +128,13 @@ namespace DiscImageChef.Filesystems information = sbInformation.ToString(); - XmlFsType = new FileSystemType + xmlFsType = new FileSystemType { Type = "Squash file system", CreationDate = DateHandlers.UnixUnsignedToDateTime(sqSb.mkfs_time), CreationDateSpecified = true, Clusters = - (long)((partition.End - partition.Start + 1) * imagePlugin.ImageInfo.SectorSize / sqSb.block_size), + (long)((partition.End - partition.Start + 1) * imagePlugin.Info.SectorSize / sqSb.block_size), ClusterSize = (int)sqSb.block_size, Files = sqSb.inodes, FilesSpecified = true, @@ -155,62 +143,57 @@ namespace DiscImageChef.Filesystems }; } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/SysV.cs b/DiscImageChef.Filesystems/SysV.cs index 89bd5fd2..20c097b6 100644 --- a/DiscImageChef.Filesystems/SysV.cs +++ b/DiscImageChef.Filesystems/SysV.cs @@ -43,7 +43,7 @@ namespace DiscImageChef.Filesystems { // Information from the Linux kernel [SuppressMessage("ReSharper", "InconsistentNaming")] - public class SysVfs : Filesystem + public class SysVfs : IFilesystem { const uint XENIX_MAGIC = 0x002B5544; const uint XENIX_CIGAM = 0x44552B00; @@ -63,36 +63,23 @@ namespace DiscImageChef.Filesystems const ushort V7_NICFREE = 100; const uint V7_MAXSIZE = 0x00FFFFFF; - public SysVfs() - { - Name = "UNIX System V filesystem"; - PluginUuid = new Guid("9B8D016A-8561-400E-A12A-A198283C211D"); - CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public SysVfs(Encoding encoding) - { - Name = "UNIX System V filesystem"; - PluginUuid = new Guid("9B8D016A-8561-400E-A12A-A198283C211D"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "UNIX System V filesystem"; + public virtual Guid Id => new Guid("9B8D016A-8561-400E-A12A-A198283C211D"); - public SysVfs(ImagePlugin imagePlugin, Partition partition, Encoding encoding) - { - Name = "UNIX System V filesystem"; - PluginUuid = new Guid("9B8D016A-8561-400E-A12A-A198283C211D"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { if(2 + partition.Start >= partition.End) return false; byte sb_size_in_sectors; - if(imagePlugin.ImageInfo.SectorSize <= 0x400 + if(imagePlugin.Info.SectorSize <= 0x400 ) // Check if underlying device sector size is smaller than SuperBlock size - sb_size_in_sectors = (byte)(0x400 / imagePlugin.ImageInfo.SectorSize); + sb_size_in_sectors = (byte)(0x400 / imagePlugin.Info.SectorSize); else sb_size_in_sectors = 1; // If not a single sector can store it if(partition.End <= partition.Start + 4 * (ulong)sb_size_in_sectors + sb_size_in_sectors @@ -100,7 +87,7 @@ namespace DiscImageChef.Filesystems return false; // Sectors in a cylinder - int spc = (int)(imagePlugin.ImageInfo.Heads * imagePlugin.ImageInfo.SectorsPerTrack); + int spc = (int)(imagePlugin.Info.Heads * imagePlugin.Info.SectorsPerTrack); // Superblock can start on 0x000, 0x200, 0x600 and 0x800, not aligned, so we assume 16 (128 bytes/sector) sectors as a safe value int[] locations = @@ -110,9 +97,9 @@ namespace DiscImageChef.Filesystems spc }; - foreach(byte[] sb_sector in locations - .TakeWhile(i => i + sb_size_in_sectors < (int)imagePlugin.ImageInfo.Sectors) - .Select(i => imagePlugin.ReadSectors((ulong)i + partition.Start, sb_size_in_sectors))) + foreach(byte[] sb_sector in locations.TakeWhile(i => i + sb_size_in_sectors < (int)imagePlugin.Info.Sectors) + .Select(i => imagePlugin.ReadSectors((ulong)i + partition.Start, + sb_size_in_sectors))) { uint magic = BitConverter.ToUInt32(sb_sector, 0x3F8); @@ -129,9 +116,9 @@ namespace DiscImageChef.Filesystems byte[] coherent_string = new byte[6]; Array.Copy(sb_sector, 0x1E4, coherent_string, 0, 6); // Coherent UNIX s_fname location - string s_fname = StringHandlers.CToString(coherent_string, CurrentEncoding); + string s_fname = StringHandlers.CToString(coherent_string, currentEncoding); Array.Copy(sb_sector, 0x1EA, coherent_string, 0, 6); // Coherent UNIX s_fpack location - string s_fpack = StringHandlers.CToString(coherent_string, CurrentEncoding); + string s_fpack = StringHandlers.CToString(coherent_string, currentEncoding); if(s_fname == COH_FNAME && s_fpack == COH_FPACK || s_fname == COH_XXXXX && s_fpack == COH_XXXXX || s_fname == COH_XXXXS && s_fpack == COH_XXXXN) return true; @@ -158,15 +145,16 @@ namespace DiscImageChef.Filesystems if(s_fsize >= V7_MAXSIZE || s_nfree >= V7_NICFREE || s_ninode >= V7_NICINOD) continue; - if(s_fsize * 1024 == (partition.End - partition.Start) * imagePlugin.ImageInfo.SectorSize || - s_fsize * 512 == (partition.End - partition.Start) * imagePlugin.ImageInfo.SectorSize) return true; + if(s_fsize * 1024 == (partition.End - partition.Start) * imagePlugin.Info.SectorSize || + s_fsize * 512 == (partition.End - partition.Start) * imagePlugin.Info.SectorSize) return true; } return false; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { + currentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); information = ""; StringBuilder sb = new StringBuilder(); @@ -182,12 +170,12 @@ namespace DiscImageChef.Filesystems byte sb_size_in_sectors; int offset = 0; - if(imagePlugin.ImageInfo.SectorSize <= 0x400 + if(imagePlugin.Info.SectorSize <= 0x400 ) // Check if underlying device sector size is smaller than SuperBlock size - sb_size_in_sectors = (byte)(0x400 / imagePlugin.ImageInfo.SectorSize); + sb_size_in_sectors = (byte)(0x400 / imagePlugin.Info.SectorSize); else sb_size_in_sectors = 1; // If not a single sector can store it // Sectors in a cylinder - int spc = (int)(imagePlugin.ImageInfo.Heads * imagePlugin.ImageInfo.SectorsPerTrack); + int spc = (int)(imagePlugin.Info.Heads * imagePlugin.Info.SectorsPerTrack); // Superblock can start on 0x000, 0x200, 0x600 and 0x800, not aligned, so we assume 16 (128 bytes/sector) sectors as a safe value int[] locations = @@ -266,9 +254,9 @@ namespace DiscImageChef.Filesystems byte[] coherent_string = new byte[6]; Array.Copy(sb_sector, 0x1E4, coherent_string, 0, 6); // Coherent UNIX s_fname location - string s_fname = StringHandlers.CToString(coherent_string, CurrentEncoding); + string s_fname = StringHandlers.CToString(coherent_string, currentEncoding); Array.Copy(sb_sector, 0x1EA, coherent_string, 0, 6); // Coherent UNIX s_fpack location - string s_fpack = StringHandlers.CToString(coherent_string, CurrentEncoding); + string s_fpack = StringHandlers.CToString(coherent_string, currentEncoding); if(s_fname == COH_FNAME && s_fpack == COH_FPACK || s_fname == COH_XXXXX && s_fpack == COH_XXXXX || s_fname == COH_XXXXS && s_fpack == COH_XXXXN) @@ -301,8 +289,8 @@ namespace DiscImageChef.Filesystems if(s_fsize >= V7_MAXSIZE || s_nfree >= V7_NICFREE || s_ninode >= V7_NICINOD) continue; - if(s_fsize * 1024 != (partition.End - partition.Start) * imagePlugin.ImageInfo.SectorSize && - s_fsize * 512 != (partition.End - partition.Start) * imagePlugin.ImageInfo.SectorSize) continue; + if(s_fsize * 1024 != (partition.End - partition.Start) * imagePlugin.Info.SectorSize && + s_fsize * 512 != (partition.End - partition.Start) * imagePlugin.Info.SectorSize) continue; sys7th = true; BigEndianBitConverter.IsLittleEndian = true; @@ -312,7 +300,7 @@ namespace DiscImageChef.Filesystems if(!sys7th && !sysv && !coherent && !xenix && !xenix3) return; - XmlFsType = new FileSystemType(); + xmlFsType = new FileSystemType(); if(xenix || xenix3) { @@ -338,9 +326,9 @@ namespace DiscImageChef.Filesystems xnx_sb.s_dinfo0 = BigEndianBitConverter.ToUInt16(sb_sector, 0x1AC); xnx_sb.s_dinfo1 = BigEndianBitConverter.ToUInt16(sb_sector, 0x1AE); Array.Copy(sb_sector, 0x1B0, xenix_strings, 0, 6); - xnx_sb.s_fname = StringHandlers.CToString(xenix_strings, CurrentEncoding); + xnx_sb.s_fname = StringHandlers.CToString(xenix_strings, currentEncoding); Array.Copy(sb_sector, 0x1B6, xenix_strings, 0, 6); - xnx_sb.s_fpack = StringHandlers.CToString(xenix_strings, CurrentEncoding); + xnx_sb.s_fpack = StringHandlers.CToString(xenix_strings, currentEncoding); xnx_sb.s_clean = sb_sector[0x1BC]; xnx_sb.s_magic = BigEndianBitConverter.ToUInt32(sb_sector, 0x1F0); xnx_sb.s_type = BigEndianBitConverter.ToUInt32(sb_sector, 0x1F4); @@ -363,9 +351,9 @@ namespace DiscImageChef.Filesystems xnx_sb.s_dinfo0 = BigEndianBitConverter.ToUInt16(sb_sector, 0x274); xnx_sb.s_dinfo1 = BigEndianBitConverter.ToUInt16(sb_sector, 0x276); Array.Copy(sb_sector, 0x278, xenix_strings, 0, 6); - xnx_sb.s_fname = StringHandlers.CToString(xenix_strings, CurrentEncoding); + xnx_sb.s_fname = StringHandlers.CToString(xenix_strings, currentEncoding); Array.Copy(sb_sector, 0x27E, xenix_strings, 0, 6); - xnx_sb.s_fpack = StringHandlers.CToString(xenix_strings, CurrentEncoding); + xnx_sb.s_fpack = StringHandlers.CToString(xenix_strings, currentEncoding); xnx_sb.s_clean = sb_sector[0x284]; xnx_sb.s_magic = BigEndianBitConverter.ToUInt32(sb_sector, 0x3F8); xnx_sb.s_type = BigEndianBitConverter.ToUInt32(sb_sector, 0x3FC); @@ -373,30 +361,30 @@ namespace DiscImageChef.Filesystems uint bs = 512; sb.AppendLine("XENIX filesystem"); - XmlFsType.Type = "XENIX fs"; + xmlFsType.Type = "XENIX fs"; switch(xnx_sb.s_type) { case 1: sb.AppendLine("512 bytes per block"); - XmlFsType.ClusterSize = 512; + xmlFsType.ClusterSize = 512; break; case 2: sb.AppendLine("1024 bytes per block"); bs = 1024; - XmlFsType.ClusterSize = 1024; + xmlFsType.ClusterSize = 1024; break; case 3: sb.AppendLine("2048 bytes per block"); bs = 2048; - XmlFsType.ClusterSize = 2048; + xmlFsType.ClusterSize = 2048; break; default: sb.AppendFormat("Unknown s_type value: 0x{0:X8}", xnx_sb.s_type).AppendLine(); break; } - if(imagePlugin.ImageInfo.SectorSize == 2336 || imagePlugin.ImageInfo.SectorSize == 2352 || - imagePlugin.ImageInfo.SectorSize == 2448) + if(imagePlugin.Info.SectorSize == 2336 || imagePlugin.Info.SectorSize == 2352 || + imagePlugin.Info.SectorSize == 2448) { if(bs != 2048) sb @@ -405,10 +393,10 @@ namespace DiscImageChef.Filesystems } else { - if(bs != imagePlugin.ImageInfo.SectorSize) + if(bs != imagePlugin.Info.SectorSize) sb .AppendFormat("WARNING: Filesystem indicates {0} bytes/block while device indicates {1} bytes/sector", - bs, imagePlugin.ImageInfo.SectorSize).AppendLine(); + bs, imagePlugin.Info.SectorSize).AppendLine(); } sb.AppendFormat("{0} zones on volume ({1} bytes)", xnx_sb.s_fsize, xnx_sb.s_fsize * bs).AppendLine(); sb.AppendFormat("{0} free zones on volume ({1} bytes)", xnx_sb.s_tfree, xnx_sb.s_tfree * bs) @@ -429,17 +417,17 @@ namespace DiscImageChef.Filesystems .AppendLine(); if(xnx_sb.s_time != 0) { - XmlFsType.ModificationDate = DateHandlers.UnixToDateTime(xnx_sb.s_time); - XmlFsType.ModificationDateSpecified = true; + xmlFsType.ModificationDate = DateHandlers.UnixToDateTime(xnx_sb.s_time); + xmlFsType.ModificationDateSpecified = true; } sb.AppendFormat("Volume name: {0}", xnx_sb.s_fname).AppendLine(); - XmlFsType.VolumeName = xnx_sb.s_fname; + xmlFsType.VolumeName = xnx_sb.s_fname; sb.AppendFormat("Pack name: {0}", xnx_sb.s_fpack).AppendLine(); if(xnx_sb.s_clean == 0x46) sb.AppendLine("Volume is clean"); else { sb.AppendLine("Volume is dirty"); - XmlFsType.Dirty = true; + xmlFsType.Dirty = true; } } @@ -456,15 +444,15 @@ namespace DiscImageChef.Filesystems switch(sysv_sb.s_type) { case 1: - XmlFsType.ClusterSize = 512; + xmlFsType.ClusterSize = 512; break; case 2: bs = 1024; - XmlFsType.ClusterSize = 1024; + xmlFsType.ClusterSize = 1024; break; case 3: bs = 2048; - XmlFsType.ClusterSize = 2048; + xmlFsType.ClusterSize = 2048; break; default: sb.AppendFormat("Unknown s_type value: 0x{0:X8}", sysv_sb.s_type).AppendLine(); @@ -495,11 +483,11 @@ namespace DiscImageChef.Filesystems sysv_sb.s_tfree = BigEndianBitConverter.ToUInt32(sb_sector, 0x1B0 + offset); sysv_sb.s_tinode = BigEndianBitConverter.ToUInt16(sb_sector, 0x1B4 + offset); Array.Copy(sb_sector, 0x1B6 + offset, sysv_strings, 0, 6); - sysv_sb.s_fname = StringHandlers.CToString(sysv_strings, CurrentEncoding); + sysv_sb.s_fname = StringHandlers.CToString(sysv_strings, currentEncoding); Array.Copy(sb_sector, 0x1BC + offset, sysv_strings, 0, 6); - sysv_sb.s_fpack = StringHandlers.CToString(sysv_strings, CurrentEncoding); + sysv_sb.s_fpack = StringHandlers.CToString(sysv_strings, currentEncoding); sb.AppendLine("System V Release 4 filesystem"); - XmlFsType.Type = "SVR4 fs"; + xmlFsType.Type = "SVR4 fs"; } else { @@ -521,15 +509,15 @@ namespace DiscImageChef.Filesystems sysv_sb.s_tfree = BigEndianBitConverter.ToUInt32(sb_sector, 0x1AA + offset); sysv_sb.s_tinode = BigEndianBitConverter.ToUInt16(sb_sector, 0x1AE + offset); Array.Copy(sb_sector, 0x1B0 + offset, sysv_strings, 0, 6); - sysv_sb.s_fname = StringHandlers.CToString(sysv_strings, CurrentEncoding); + sysv_sb.s_fname = StringHandlers.CToString(sysv_strings, currentEncoding); Array.Copy(sb_sector, 0x1B6 + offset, sysv_strings, 0, 6); - sysv_sb.s_fpack = StringHandlers.CToString(sysv_strings, CurrentEncoding); + sysv_sb.s_fpack = StringHandlers.CToString(sysv_strings, currentEncoding); sb.AppendLine("System V Release 2 filesystem"); - XmlFsType.Type = "SVR2 fs"; + xmlFsType.Type = "SVR2 fs"; } sb.AppendFormat("{0} bytes per block", bs).AppendLine(); - XmlFsType.Clusters = sysv_sb.s_fsize; + xmlFsType.Clusters = sysv_sb.s_fsize; sb.AppendFormat("{0} zones on volume ({1} bytes)", sysv_sb.s_fsize, sysv_sb.s_fsize * bs).AppendLine(); sb.AppendFormat("{0} free zones on volume ({1} bytes)", sysv_sb.s_tfree, sysv_sb.s_tfree * bs) .AppendLine(); @@ -550,17 +538,17 @@ namespace DiscImageChef.Filesystems .AppendLine(); if(sysv_sb.s_time != 0) { - XmlFsType.ModificationDate = DateHandlers.UnixUnsignedToDateTime(sysv_sb.s_time); - XmlFsType.ModificationDateSpecified = true; + xmlFsType.ModificationDate = DateHandlers.UnixUnsignedToDateTime(sysv_sb.s_time); + xmlFsType.ModificationDateSpecified = true; } sb.AppendFormat("Volume name: {0}", sysv_sb.s_fname).AppendLine(); - XmlFsType.VolumeName = sysv_sb.s_fname; + xmlFsType.VolumeName = sysv_sb.s_fname; sb.AppendFormat("Pack name: {0}", sysv_sb.s_fpack).AppendLine(); if(sysv_sb.s_state == 0x7C269D38 - sysv_sb.s_time) sb.AppendLine("Volume is clean"); else { sb.AppendLine("Volume is dirty"); - XmlFsType.Dirty = true; + xmlFsType.Dirty = true; } } @@ -584,16 +572,16 @@ namespace DiscImageChef.Filesystems coh_sb.s_int_m = BitConverter.ToUInt16(sb_sector, 0x1E0); coh_sb.s_int_n = BitConverter.ToUInt16(sb_sector, 0x1E2); Array.Copy(sb_sector, 0x1E4, coh_strings, 0, 6); - coh_sb.s_fname = StringHandlers.CToString(coh_strings, CurrentEncoding); + coh_sb.s_fname = StringHandlers.CToString(coh_strings, currentEncoding); Array.Copy(sb_sector, 0x1EA, coh_strings, 0, 6); - coh_sb.s_fpack = StringHandlers.CToString(coh_strings, CurrentEncoding); + coh_sb.s_fpack = StringHandlers.CToString(coh_strings, currentEncoding); - XmlFsType.Type = "Coherent fs"; - XmlFsType.ClusterSize = 512; - XmlFsType.Clusters = coh_sb.s_fsize; + xmlFsType.Type = "Coherent fs"; + xmlFsType.ClusterSize = 512; + xmlFsType.Clusters = coh_sb.s_fsize; sb.AppendLine("Coherent UNIX filesystem"); - if(imagePlugin.ImageInfo.SectorSize != 512) + if(imagePlugin.Info.SectorSize != 512) sb .AppendFormat("WARNING: Filesystem indicates {0} bytes/block while device indicates {1} bytes/sector", 512, 2048).AppendLine(); @@ -613,11 +601,11 @@ namespace DiscImageChef.Filesystems .AppendLine(); if(coh_sb.s_time != 0) { - XmlFsType.ModificationDate = DateHandlers.UnixUnsignedToDateTime(coh_sb.s_time); - XmlFsType.ModificationDateSpecified = true; + xmlFsType.ModificationDate = DateHandlers.UnixUnsignedToDateTime(coh_sb.s_time); + xmlFsType.ModificationDateSpecified = true; } sb.AppendFormat("Volume name: {0}", coh_sb.s_fname).AppendLine(); - XmlFsType.VolumeName = coh_sb.s_fname; + xmlFsType.VolumeName = coh_sb.s_fname; sb.AppendFormat("Pack name: {0}", coh_sb.s_fpack).AppendLine(); } @@ -641,15 +629,15 @@ namespace DiscImageChef.Filesystems v7_sb.s_int_m = BigEndianBitConverter.ToUInt16(sb_sector, 0x1A8); v7_sb.s_int_n = BigEndianBitConverter.ToUInt16(sb_sector, 0x1AA); Array.Copy(sb_sector, 0x1AC, sys7_strings, 0, 6); - v7_sb.s_fname = StringHandlers.CToString(sys7_strings, CurrentEncoding); + v7_sb.s_fname = StringHandlers.CToString(sys7_strings, currentEncoding); Array.Copy(sb_sector, 0x1B2, sys7_strings, 0, 6); - v7_sb.s_fpack = StringHandlers.CToString(sys7_strings, CurrentEncoding); + v7_sb.s_fpack = StringHandlers.CToString(sys7_strings, currentEncoding); - XmlFsType.Type = "UNIX 7th Edition fs"; - XmlFsType.ClusterSize = 512; - XmlFsType.Clusters = v7_sb.s_fsize; + xmlFsType.Type = "UNIX 7th Edition fs"; + xmlFsType.ClusterSize = 512; + xmlFsType.Clusters = v7_sb.s_fsize; sb.AppendLine("UNIX 7th Edition filesystem"); - if(imagePlugin.ImageInfo.SectorSize != 512) + if(imagePlugin.Info.SectorSize != 512) sb .AppendFormat("WARNING: Filesystem indicates {0} bytes/block while device indicates {1} bytes/sector", 512, 2048).AppendLine(); @@ -668,11 +656,11 @@ namespace DiscImageChef.Filesystems .AppendLine(); if(v7_sb.s_time != 0) { - XmlFsType.ModificationDate = DateHandlers.UnixUnsignedToDateTime(v7_sb.s_time); - XmlFsType.ModificationDateSpecified = true; + xmlFsType.ModificationDate = DateHandlers.UnixUnsignedToDateTime(v7_sb.s_time); + xmlFsType.ModificationDateSpecified = true; } sb.AppendFormat("Volume name: {0}", v7_sb.s_fname).AppendLine(); - XmlFsType.VolumeName = v7_sb.s_fname; + xmlFsType.VolumeName = v7_sb.s_fname; sb.AppendFormat("Pack name: {0}", v7_sb.s_fpack).AppendLine(); } @@ -681,62 +669,57 @@ namespace DiscImageChef.Filesystems BigEndianBitConverter.IsLittleEndian = false; // Return to default (bigendian) } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/UCSDPascal/Dir.cs b/DiscImageChef.Filesystems/UCSDPascal/Dir.cs index b64adbc0..f8c2cfd0 100644 --- a/DiscImageChef.Filesystems/UCSDPascal/Dir.cs +++ b/DiscImageChef.Filesystems/UCSDPascal/Dir.cs @@ -39,14 +39,14 @@ namespace DiscImageChef.Filesystems.UCSDPascal // Information from Call-A.P.P.L.E. Pascal Disk Directory Structure public partial class PascalPlugin { - public override Errno ReadDir(string path, ref List contents) + public virtual Errno ReadDir(string path, ref List contents) { if(!mounted) return Errno.AccessDenied; if(!string.IsNullOrEmpty(path) && string.Compare(path, "/", StringComparison.OrdinalIgnoreCase) != 0) return Errno.NotSupported; - contents = fileEntries.Select(ent => StringHandlers.PascalToString(ent.filename, CurrentEncoding)).ToList(); + contents = fileEntries.Select(ent => StringHandlers.PascalToString(ent.filename, currentEncoding)).ToList(); if(debug) { diff --git a/DiscImageChef.Filesystems/UCSDPascal/File.cs b/DiscImageChef.Filesystems/UCSDPascal/File.cs index 3d014b83..e924506c 100644 --- a/DiscImageChef.Filesystems/UCSDPascal/File.cs +++ b/DiscImageChef.Filesystems/UCSDPascal/File.cs @@ -38,12 +38,12 @@ namespace DiscImageChef.Filesystems.UCSDPascal // Information from Call-A.P.P.L.E. Pascal Disk Directory Structure public partial class PascalPlugin { - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return !mounted ? Errno.AccessDenied : Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { if(!mounted) return Errno.AccessDenied; @@ -60,7 +60,7 @@ namespace DiscImageChef.Filesystems.UCSDPascal return error; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { if(!mounted) return Errno.AccessDenied; @@ -79,7 +79,7 @@ namespace DiscImageChef.Filesystems.UCSDPascal if(error != Errno.NoError) return error; byte[] tmp = device.ReadSectors((ulong)entry.firstBlock, (uint)(entry.lastBlock - entry.firstBlock)); - file = new byte[(entry.lastBlock - entry.firstBlock - 1) * device.ImageInfo.SectorSize + + file = new byte[(entry.lastBlock - entry.firstBlock - 1) * device.Info.SectorSize + entry.lastBytes]; Array.Copy(tmp, 0, file, 0, file.Length); } @@ -95,7 +95,7 @@ namespace DiscImageChef.Filesystems.UCSDPascal return Errno.NoError; } - public override Errno Stat(string path, ref FileEntryInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { if(!mounted) return Errno.AccessDenied; @@ -111,7 +111,7 @@ namespace DiscImageChef.Filesystems.UCSDPascal stat = new FileEntryInfo { Attributes = FileAttributes.System, - BlockSize = device.ImageInfo.SectorSize, + BlockSize = device.Info.SectorSize, DeviceNo = 0, GID = 0, Inode = 0, @@ -142,12 +142,12 @@ namespace DiscImageChef.Filesystems.UCSDPascal { Attributes = FileAttributes.File, Blocks = entry.lastBlock - entry.firstBlock, - BlockSize = device.ImageInfo.SectorSize, + BlockSize = device.Info.SectorSize, DeviceNo = 0, GID = 0, Inode = 0, LastWriteTimeUtc = DateHandlers.UcsdPascalToDateTime(entry.mtime), - Length = (entry.lastBlock - entry.firstBlock) * device.ImageInfo.SectorSize + entry.lastBytes, + Length = (entry.lastBlock - entry.firstBlock) * device.Info.SectorSize + entry.lastBytes, Links = 1, Mode = 0x124, UID = 0 @@ -164,7 +164,7 @@ namespace DiscImageChef.Filesystems.UCSDPascal string.Compare(path, StringHandlers .PascalToString(ent.filename, - CurrentEncoding), + currentEncoding), StringComparison .InvariantCultureIgnoreCase) == 0)) { diff --git a/DiscImageChef.Filesystems/UCSDPascal/Info.cs b/DiscImageChef.Filesystems/UCSDPascal/Info.cs index d8c8220d..cc9b5efa 100644 --- a/DiscImageChef.Filesystems/UCSDPascal/Info.cs +++ b/DiscImageChef.Filesystems/UCSDPascal/Info.cs @@ -41,7 +41,7 @@ namespace DiscImageChef.Filesystems.UCSDPascal // Information from Call-A.P.P.L.E. Pascal Disk Directory Structure public partial class PascalPlugin { - public override bool Identify(ImagePlugin imagePlugin, Partition partition) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { if(partition.Length < 3) return false; @@ -68,7 +68,7 @@ namespace DiscImageChef.Filesystems.UCSDPascal // Last volume record block must be after first block, and before end of device if(volEntry.lastBlock <= volEntry.firstBlock || - (ulong)volEntry.lastBlock > imagePlugin.ImageInfo.Sectors - 2) return false; + (ulong)volEntry.lastBlock > imagePlugin.Info.Sectors - 2) return false; // Volume record entry type must be volume or secure if(volEntry.entryType != PascalFileKind.Volume && volEntry.entryType != PascalFileKind.Secure) return false; @@ -77,18 +77,18 @@ namespace DiscImageChef.Filesystems.UCSDPascal if(volEntry.volumeName[0] > 7) return false; // Volume blocks is equal to volume sectors - if(volEntry.blocks < 0 || (ulong)volEntry.blocks != imagePlugin.ImageInfo.Sectors) return false; + if(volEntry.blocks < 0 || (ulong)volEntry.blocks != imagePlugin.Info.Sectors) return false; // There can be not less than zero files return volEntry.files >= 0; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { StringBuilder sbInformation = new StringBuilder(); information = ""; - if(imagePlugin.ImageInfo.Sectors < 3) return; + if(imagePlugin.Info.Sectors < 3) return; // Blocks 0 and 1 are boot code byte[] volBlock = imagePlugin.ReadSector(2 + partition.Start); @@ -113,7 +113,7 @@ namespace DiscImageChef.Filesystems.UCSDPascal // Last volume record block must be after first block, and before end of device if(volEntry.lastBlock <= volEntry.firstBlock || - (ulong)volEntry.lastBlock > imagePlugin.ImageInfo.Sectors - 2) return; + (ulong)volEntry.lastBlock > imagePlugin.Info.Sectors - 2) return; // Volume record entry type must be volume or secure if(volEntry.entryType != PascalFileKind.Volume && volEntry.entryType != PascalFileKind.Secure) return; @@ -122,7 +122,7 @@ namespace DiscImageChef.Filesystems.UCSDPascal if(volEntry.volumeName[0] > 7) return; // Volume blocks is equal to volume sectors - if(volEntry.blocks < 0 || (ulong)volEntry.blocks != imagePlugin.ImageInfo.Sectors) return; + if(volEntry.blocks < 0 || (ulong)volEntry.blocks != imagePlugin.Info.Sectors) return; // There can be not less than zero files if(volEntry.files < 0) return; @@ -130,7 +130,7 @@ namespace DiscImageChef.Filesystems.UCSDPascal sbInformation.AppendFormat("Volume record spans from block {0} to block {1}", volEntry.firstBlock, volEntry.lastBlock).AppendLine(); sbInformation.AppendFormat("Volume name: {0}", - StringHandlers.PascalToString(volEntry.volumeName, CurrentEncoding)) + StringHandlers.PascalToString(volEntry.volumeName, currentEncoding)) .AppendLine(); sbInformation.AppendFormat("Volume has {0} blocks", volEntry.blocks).AppendLine(); sbInformation.AppendFormat("Volume has {0} files", volEntry.files).AppendLine(); @@ -140,15 +140,15 @@ namespace DiscImageChef.Filesystems.UCSDPascal information = sbInformation.ToString(); - XmlFsType = new FileSystemType + xmlFsType = new FileSystemType { Bootable = !ArrayHelpers.ArrayIsNullOrEmpty(imagePlugin.ReadSectors(partition.Start, 2)), Clusters = volEntry.blocks, - ClusterSize = (int)imagePlugin.ImageInfo.SectorSize, + ClusterSize = (int)imagePlugin.Info.SectorSize, Files = volEntry.files, FilesSpecified = true, Type = "UCSD Pascal", - VolumeName = StringHandlers.PascalToString(volEntry.volumeName, CurrentEncoding) + VolumeName = StringHandlers.PascalToString(volEntry.volumeName, currentEncoding) }; } } diff --git a/DiscImageChef.Filesystems/UCSDPascal/Super.cs b/DiscImageChef.Filesystems/UCSDPascal/Super.cs index d5f41fff..873c9006 100644 --- a/DiscImageChef.Filesystems/UCSDPascal/Super.cs +++ b/DiscImageChef.Filesystems/UCSDPascal/Super.cs @@ -32,22 +32,24 @@ using System; using System.Collections.Generic; +using Claunia.Encoding; +using DiscImageChef.CommonTypes; +using DiscImageChef.DiscImages; using Schemas; +using Encoding = System.Text.Encoding; namespace DiscImageChef.Filesystems.UCSDPascal { // Information from Call-A.P.P.L.E. Pascal Disk Directory Structure public partial class PascalPlugin { - public override Errno Mount() - { - return Mount(false); - } - - public override Errno Mount(bool debug) + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { + device = imagePlugin; + // TODO: Until Apple ][ encoding is implemented + currentEncoding = new LisaRoman(); this.debug = debug; - if(device.ImageInfo.Sectors < 3) return Errno.InvalidArgument; + if(device.Info.Sectors < 3) return Errno.InvalidArgument; // Blocks 0 and 1 are boot code catalogBlocks = device.ReadSector(2); @@ -66,10 +68,10 @@ namespace DiscImageChef.Filesystems.UCSDPascal mountedVolEntry.tail = BigEndianBitConverter.ToInt32(catalogBlocks, 0x16); if(mountedVolEntry.firstBlock != 0 || mountedVolEntry.lastBlock <= mountedVolEntry.firstBlock || - (ulong)mountedVolEntry.lastBlock > device.ImageInfo.Sectors - 2 || + (ulong)mountedVolEntry.lastBlock > device.Info.Sectors - 2 || mountedVolEntry.entryType != PascalFileKind.Volume && mountedVolEntry.entryType != PascalFileKind.Secure || mountedVolEntry.volumeName[0] > 7 || - mountedVolEntry.blocks < 0 || (ulong)mountedVolEntry.blocks != device.ImageInfo.Sectors || + mountedVolEntry.blocks < 0 || (ulong)mountedVolEntry.blocks != device.Info.Sectors || mountedVolEntry.files < 0) return Errno.InvalidArgument; catalogBlocks = device.ReadSectors(2, (uint)(mountedVolEntry.lastBlock - mountedVolEntry.firstBlock - 2)); @@ -96,15 +98,15 @@ namespace DiscImageChef.Filesystems.UCSDPascal bootBlocks = device.ReadSectors(0, 2); - XmlFsType = new FileSystemType + xmlFsType = new FileSystemType { Bootable = !ArrayHelpers.ArrayIsNullOrEmpty(bootBlocks), Clusters = mountedVolEntry.blocks, - ClusterSize = (int)device.ImageInfo.SectorSize, + ClusterSize = (int)device.Info.SectorSize, Files = mountedVolEntry.files, FilesSpecified = true, Type = "UCSD Pascal", - VolumeName = StringHandlers.PascalToString(mountedVolEntry.volumeName, CurrentEncoding) + VolumeName = StringHandlers.PascalToString(mountedVolEntry.volumeName, currentEncoding) }; mounted = true; @@ -112,14 +114,14 @@ namespace DiscImageChef.Filesystems.UCSDPascal return Errno.NoError; } - public override Errno Unmount() + public virtual Errno Unmount() { mounted = false; fileEntries = null; return Errno.NoError; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno StatFs(ref FileSystemInfo stat) { stat = new FileSystemInfo { @@ -127,7 +129,7 @@ namespace DiscImageChef.Filesystems.UCSDPascal FilenameLength = 16, Files = (ulong)mountedVolEntry.files, FreeBlocks = 0, - PluginId = PluginUuid, + PluginId = Id, Type = "UCSD Pascal" }; diff --git a/DiscImageChef.Filesystems/UCSDPascal/UCSDPascal.cs b/DiscImageChef.Filesystems/UCSDPascal/UCSDPascal.cs index 5165a6e2..2cbcb2bc 100644 --- a/DiscImageChef.Filesystems/UCSDPascal/UCSDPascal.cs +++ b/DiscImageChef.Filesystems/UCSDPascal/UCSDPascal.cs @@ -35,57 +35,41 @@ using System.Collections.Generic; using Claunia.Encoding; using DiscImageChef.CommonTypes; using DiscImageChef.DiscImages; +using Schemas; using Encoding = System.Text.Encoding; namespace DiscImageChef.Filesystems.UCSDPascal { // Information from Call-A.P.P.L.E. Pascal Disk Directory Structure - public partial class PascalPlugin : Filesystem + public partial class PascalPlugin : IFilesystem { - readonly ImagePlugin device; + IMediaImage device; byte[] bootBlocks; byte[] catalogBlocks; + Encoding currentEncoding; bool debug; List fileEntries; bool mounted; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; PascalVolumeEntry mountedVolEntry; - public PascalPlugin() - { - Name = "U.C.S.D. Pascal filesystem"; - PluginUuid = new Guid("B0AC2CB5-72AA-473A-9200-270B5A2C2D53"); - CurrentEncoding = new LisaRoman(); - } + public virtual string Name => "U.C.S.D. Pascal filesystem"; + public virtual Guid Id => new Guid("B0AC2CB5-72AA-473A-9200-270B5A2C2D53"); + public virtual Encoding Encoding => currentEncoding; - public PascalPlugin(Encoding encoding) - { - Name = "U.C.S.D. Pascal filesystem"; - PluginUuid = new Guid("B0AC2CB5-72AA-473A-9200-270B5A2C2D53"); - // TODO: Until Apple ][ encoding is implemented - CurrentEncoding = new LisaRoman(); - } - - public PascalPlugin(ImagePlugin imagePlugin, Partition partition, Encoding encoding) - { - device = imagePlugin; - Name = "U.C.S.D. Pascal filesystem"; - PluginUuid = new Guid("B0AC2CB5-72AA-473A-9200-270B5A2C2D53"); - // TODO: Until Apple ][ encoding is implemented - CurrentEncoding = new LisaRoman(); - } - - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotSupported; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotSupported; } - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotSupported; } diff --git a/DiscImageChef.Filesystems/UDF.cs b/DiscImageChef.Filesystems/UDF.cs index 441895d6..80d27b96 100644 --- a/DiscImageChef.Filesystems/UDF.cs +++ b/DiscImageChef.Filesystems/UDF.cs @@ -43,7 +43,7 @@ using Schemas; namespace DiscImageChef.Filesystems { // TODO: Detect bootable - public class UDF : Filesystem + public class UDF : IFilesystem { readonly byte[] UDF_Magic = { @@ -51,36 +51,21 @@ namespace DiscImageChef.Filesystems 0x74, 0x00, 0x00, 0x00, 0x00 }; - public UDF() - { - Name = "Universal Disk Format"; - PluginUuid = new Guid("83976FEC-A91B-464B-9293-56C719461BAB"); - CurrentEncoding = Encoding.UTF8; - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public UDF(Encoding encoding) - { - Name = "Universal Disk Format"; - PluginUuid = new Guid("83976FEC-A91B-464B-9293-56C719461BAB"); - // UDF is always UTF-8 - CurrentEncoding = Encoding.UTF8; - } + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "Universal Disk Format"; + public virtual Guid Id => new Guid("83976FEC-A91B-464B-9293-56C719461BAB"); - public UDF(ImagePlugin imagePlugin, Partition partition, Encoding encoding) - { - Name = "Universal Disk Format"; - PluginUuid = new Guid("83976FEC-A91B-464B-9293-56C719461BAB"); - // UDF is always UTF-8 - CurrentEncoding = Encoding.UTF8; - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { // UDF needs at least that if(partition.End - partition.Start < 256) return false; // UDF needs at least that - if(imagePlugin.ImageInfo.SectorSize < 512) return false; + if(imagePlugin.Info.SectorSize < 512) return false; byte[] sector; AnchorVolumeDescriptorPointer anchor = new AnchorVolumeDescriptorPointer(); @@ -161,8 +146,10 @@ namespace DiscImageChef.Filesystems return false; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { + // UDF is always UTF-8 + currentEncoding = Encoding.UTF8; byte[] sector; StringBuilder sbInformation = new StringBuilder(); @@ -268,10 +255,10 @@ namespace DiscImageChef.Filesystems .AppendFormat("Volume contains {0} files and {1} directories", lvidiu.files, lvidiu.directories) .AppendLine(); sbInformation.AppendFormat("Volume conforms to {0}", - CurrentEncoding.GetString(lvd.domainIdentifier.identifier).TrimEnd('\u0000')) + currentEncoding.GetString(lvd.domainIdentifier.identifier).TrimEnd('\u0000')) .AppendLine(); sbInformation.AppendFormat("Volume was last written by: {0}", - CurrentEncoding + currentEncoding .GetString(pvd.implementationIdentifier.identifier).TrimEnd('\u0000')) .AppendLine(); sbInformation.AppendFormat("Volume requires UDF version {0}.{1:X2} to be read", @@ -284,12 +271,12 @@ namespace DiscImageChef.Filesystems Convert.ToInt32($"{(lvidiu.maximumWriteUDF & 0xFF00) >> 8}", 10), Convert.ToInt32($"{lvidiu.maximumWriteUDF & 0xFF}", 10)).AppendLine(); - XmlFsType = new FileSystemType + xmlFsType = new FileSystemType { Type = $"UDF v{Convert.ToInt32($"{(lvidiu.maximumWriteUDF & 0xFF00) >> 8}", 10)}.{Convert.ToInt32($"{lvidiu.maximumWriteUDF & 0xFF}", 10):X2}", ApplicationIdentifier = - CurrentEncoding.GetString(pvd.implementationIdentifier.identifier).TrimEnd('\u0000'), + currentEncoding.GetString(pvd.implementationIdentifier.identifier).TrimEnd('\u0000'), ClusterSize = (int)lvd.logicalBlockSize, ModificationDate = EcmaToDateTime(lvid.recordingDateTime), ModificationDateSpecified = true, @@ -297,10 +284,10 @@ namespace DiscImageChef.Filesystems FilesSpecified = true, VolumeName = StringHandlers.DecompressUnicode(lvd.logicalVolumeIdentifier), VolumeSetIdentifier = StringHandlers.DecompressUnicode(pvd.volumeSetIdentifier), - SystemIdentifier = CurrentEncoding.GetString(pvd.implementationIdentifier.identifier).TrimEnd('\u0000') + SystemIdentifier = currentEncoding.GetString(pvd.implementationIdentifier.identifier).TrimEnd('\u0000') }; - XmlFsType.Clusters = (long)((partition.End - partition.Start + 1) * imagePlugin.ImageInfo.SectorSize / - (ulong)XmlFsType.ClusterSize); + xmlFsType.Clusters = (long)((partition.End - partition.Start + 1) * imagePlugin.Info.SectorSize / + (ulong)xmlFsType.ClusterSize); information = sbInformation.ToString(); } @@ -313,62 +300,57 @@ namespace DiscImageChef.Filesystems timestamp.microseconds); } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/UNICOS.cs b/DiscImageChef.Filesystems/UNICOS.cs index 3dcfb052..23fa0350 100644 --- a/DiscImageChef.Filesystems/UNICOS.cs +++ b/DiscImageChef.Filesystems/UNICOS.cs @@ -49,7 +49,7 @@ using time_t = System.Int64; namespace DiscImageChef.Filesystems { - public class UNICOS : Filesystem + public class UNICOS : IFilesystem { const int NC1MAXPART = 64; const int NC1MAXIREG = 4; @@ -57,35 +57,22 @@ namespace DiscImageChef.Filesystems const ulong UNICOS_Magic = 0x6e6331667331636e; const ulong UNICOS_Secure = 0xcd076d1771d670cd; - public UNICOS() - { - Name = "UNICOS Filesystem Plugin"; - PluginUuid = new Guid("61712F04-066C-44D5-A2A0-1E44C66B33F0"); - CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public UNICOS(Encoding encoding) - { - Name = "UNICOS Filesystem Plugin"; - PluginUuid = new Guid("61712F04-066C-44D5-A2A0-1E44C66B33F0"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "UNICOS Filesystem Plugin"; + public virtual Guid Id => new Guid("61712F04-066C-44D5-A2A0-1E44C66B33F0"); - public UNICOS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { - Name = "UNICOS Filesystem Plugin"; - PluginUuid = new Guid("61712F04-066C-44D5-A2A0-1E44C66B33F0"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) - { - if(imagePlugin.ImageInfo.SectorSize < 512) return false; + if(imagePlugin.Info.SectorSize < 512) return false; UNICOS_Superblock unicosSb = new UNICOS_Superblock(); - uint sbSize = (uint)(Marshal.SizeOf(unicosSb) / imagePlugin.ImageInfo.SectorSize); - if(Marshal.SizeOf(unicosSb) % imagePlugin.ImageInfo.SectorSize != 0) sbSize++; + uint sbSize = (uint)(Marshal.SizeOf(unicosSb) / imagePlugin.Info.SectorSize); + if(Marshal.SizeOf(unicosSb) % imagePlugin.Info.SectorSize != 0) sbSize++; byte[] sector = imagePlugin.ReadSectors(partition.Start, sbSize); if(sector.Length < Marshal.SizeOf(unicosSb)) return false; @@ -98,15 +85,16 @@ namespace DiscImageChef.Filesystems return unicosSb.s_magic == UNICOS_Magic; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { + currentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); information = ""; - if(imagePlugin.ImageInfo.SectorSize < 512) return; + if(imagePlugin.Info.SectorSize < 512) return; UNICOS_Superblock unicosSb = new UNICOS_Superblock(); - uint sbSize = (uint)(Marshal.SizeOf(unicosSb) / imagePlugin.ImageInfo.SectorSize); - if(Marshal.SizeOf(unicosSb) % imagePlugin.ImageInfo.SectorSize != 0) sbSize++; + uint sbSize = (uint)(Marshal.SizeOf(unicosSb) / imagePlugin.Info.SectorSize); + if(Marshal.SizeOf(unicosSb) % imagePlugin.Info.SectorSize != 0) sbSize++; byte[] sector = imagePlugin.ReadSectors(partition.Start, sbSize); if(sector.Length < Marshal.SizeOf(unicosSb)) return; @@ -128,79 +116,74 @@ namespace DiscImageChef.Filesystems sb.AppendFormat("Volume last updated on {0}", DateHandlers.UnixToDateTime(unicosSb.s_time)).AppendLine(); if(unicosSb.s_error > 0) sb.AppendFormat("Volume is dirty, error code = 0x{0:X16}", unicosSb.s_error).AppendLine(); - sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(unicosSb.s_fname, CurrentEncoding)) + sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(unicosSb.s_fname, currentEncoding)) .AppendLine(); information = sb.ToString(); - XmlFsType = new FileSystemType + xmlFsType = new FileSystemType { Type = "UNICOS filesystem", ClusterSize = 4096, Clusters = unicosSb.s_fsize, - VolumeName = StringHandlers.CToString(unicosSb.s_fname, CurrentEncoding), + VolumeName = StringHandlers.CToString(unicosSb.s_fname, currentEncoding), ModificationDate = DateHandlers.UnixToDateTime(unicosSb.s_time), ModificationDateSpecified = true }; - XmlFsType.Dirty |= unicosSb.s_error > 0; + xmlFsType.Dirty |= unicosSb.s_error > 0; } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/UNIXBFS.cs b/DiscImageChef.Filesystems/UNIXBFS.cs index c08f777d..deacb769 100644 --- a/DiscImageChef.Filesystems/UNIXBFS.cs +++ b/DiscImageChef.Filesystems/UNIXBFS.cs @@ -41,32 +41,19 @@ using Schemas; namespace DiscImageChef.Filesystems { // Information from the Linux kernel - public class BFS : Filesystem + public class BFS : IFilesystem { const uint BFS_MAGIC = 0x1BADFACE; - public BFS() - { - Name = "UNIX Boot filesystem"; - PluginUuid = new Guid("1E6E0DA6-F7E4-494C-80C6-CB5929E96155"); - CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public BFS(Encoding encoding) - { - Name = "UNIX Boot filesystem"; - PluginUuid = new Guid("1E6E0DA6-F7E4-494C-80C6-CB5929E96155"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "UNIX Boot filesystem"; + public virtual Guid Id => new Guid("1E6E0DA6-F7E4-494C-80C6-CB5929E96155"); - public BFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) - { - Name = "UNIX Boot filesystem"; - PluginUuid = new Guid("1E6E0DA6-F7E4-494C-80C6-CB5929E96155"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { if(2 + partition.Start >= partition.End) return false; @@ -77,8 +64,9 @@ namespace DiscImageChef.Filesystems return magic == BFS_MAGIC; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { + currentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); information = ""; StringBuilder sb = new StringBuilder(); @@ -97,9 +85,9 @@ namespace DiscImageChef.Filesystems }; Array.Copy(bfsSbSector, 0x1C, sbStrings, 0, 6); - bfsSb.s_fsname = StringHandlers.CToString(sbStrings, CurrentEncoding); + bfsSb.s_fsname = StringHandlers.CToString(sbStrings, currentEncoding); Array.Copy(bfsSbSector, 0x22, sbStrings, 0, 6); - bfsSb.s_volume = StringHandlers.CToString(sbStrings, CurrentEncoding); + bfsSb.s_volume = StringHandlers.CToString(sbStrings, currentEncoding); DicConsole.DebugWriteLine("BFS plugin", "bfs_sb.s_magic: 0x{0:X8}", bfsSb.s_magic); DicConsole.DebugWriteLine("BFS plugin", "bfs_sb.s_start: 0x{0:X8}", bfsSb.s_start); @@ -117,71 +105,66 @@ namespace DiscImageChef.Filesystems sb.AppendFormat("Filesystem name: {0}", bfsSb.s_fsname).AppendLine(); sb.AppendFormat("Volume name: {0}", bfsSb.s_volume).AppendLine(); - XmlFsType = new FileSystemType(); - XmlFsType.Type = "BFS"; - XmlFsType.VolumeName = bfsSb.s_volume; - XmlFsType.ClusterSize = (int)imagePlugin.ImageInfo.SectorSize; - XmlFsType.Clusters = (long)(partition.End - partition.Start + 1); + xmlFsType = new FileSystemType(); + xmlFsType.Type = "BFS"; + xmlFsType.VolumeName = bfsSb.s_volume; + xmlFsType.ClusterSize = (int)imagePlugin.Info.SectorSize; + xmlFsType.Clusters = (long)(partition.End - partition.Start + 1); information = sb.ToString(); } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/VMfs.cs b/DiscImageChef.Filesystems/VMfs.cs index 150e0856..b2822269 100644 --- a/DiscImageChef.Filesystems/VMfs.cs +++ b/DiscImageChef.Filesystems/VMfs.cs @@ -40,7 +40,7 @@ using Schemas; namespace DiscImageChef.Filesystems { - public class VMfs : Filesystem + public class VMfs : IFilesystem { /// /// Identifier for VMfs @@ -48,32 +48,19 @@ namespace DiscImageChef.Filesystems const uint VMFS_MAGIC = 0xC001D00D; const uint VMFS_BASE = 0x00100000; - public VMfs() - { - Name = "VMware filesystem"; - PluginUuid = new Guid("EE52BDB8-B49C-4122-A3DA-AD21CBE79843"); - CurrentEncoding = Encoding.UTF8; - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public VMfs(Encoding encoding) - { - Name = "VMware filesystem"; - PluginUuid = new Guid("EE52BDB8-B49C-4122-A3DA-AD21CBE79843"); - CurrentEncoding = encoding ?? Encoding.UTF8; - } + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "VMware filesystem"; + public virtual Guid Id => new Guid("EE52BDB8-B49C-4122-A3DA-AD21CBE79843"); - public VMfs(ImagePlugin imagePlugin, Partition partition, Encoding encoding) - { - Name = "VMware filesystem"; - PluginUuid = new Guid("EE52BDB8-B49C-4122-A3DA-AD21CBE79843"); - CurrentEncoding = encoding ?? Encoding.UTF8; - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { if(partition.Start >= partition.End) return false; - ulong vmfsSuperOff = VMFS_BASE / imagePlugin.ImageInfo.SectorSize; + ulong vmfsSuperOff = VMFS_BASE / imagePlugin.Info.SectorSize; if(partition.Start + vmfsSuperOff > partition.End) return false; @@ -84,9 +71,10 @@ namespace DiscImageChef.Filesystems return magic == VMFS_MAGIC; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { - ulong vmfsSuperOff = VMFS_BASE / imagePlugin.ImageInfo.SectorSize; + currentEncoding = encoding ?? Encoding.UTF8; + ulong vmfsSuperOff = VMFS_BASE / imagePlugin.Info.SectorSize; byte[] sector = imagePlugin.ReadSector(partition.Start + vmfsSuperOff); VolumeInfo volInfo = new VolumeInfo(); @@ -105,7 +93,7 @@ namespace DiscImageChef.Filesystems uint mtimeNanoSecs = (uint)(volInfo.mtime % 1000000); sbInformation.AppendFormat("Volume version {0}", volInfo.version).AppendLine(); - sbInformation.AppendFormat("Volume name {0}", StringHandlers.CToString(volInfo.name, CurrentEncoding)) + sbInformation.AppendFormat("Volume name {0}", StringHandlers.CToString(volInfo.name, currentEncoding)) .AppendLine(); sbInformation.AppendFormat("Volume size {0} bytes", volInfo.size * 256).AppendLine(); sbInformation.AppendFormat("Volume UUID {0}", volInfo.uuid).AppendLine(); @@ -117,75 +105,70 @@ namespace DiscImageChef.Filesystems information = sbInformation.ToString(); - XmlFsType = new FileSystemType + xmlFsType = new FileSystemType { Type = "VMware file system", CreationDate = DateHandlers.UnixUnsignedToDateTime(ctimeSecs, ctimeNanoSecs), CreationDateSpecified = true, ModificationDate = DateHandlers.UnixUnsignedToDateTime(mtimeSecs, mtimeNanoSecs), ModificationDateSpecified = true, - Clusters = volInfo.size * 256 / imagePlugin.ImageInfo.SectorSize, - ClusterSize = (int)imagePlugin.ImageInfo.SectorSize, + Clusters = volInfo.size * 256 / imagePlugin.Info.SectorSize, + ClusterSize = (int)imagePlugin.Info.SectorSize, VolumeSerial = volInfo.uuid.ToString() }; } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/VxFS.cs b/DiscImageChef.Filesystems/VxFS.cs index d336df97..2272d73e 100644 --- a/DiscImageChef.Filesystems/VxFS.cs +++ b/DiscImageChef.Filesystems/VxFS.cs @@ -40,7 +40,7 @@ using Schemas; namespace DiscImageChef.Filesystems { - public class VxFS : Filesystem + public class VxFS : IFilesystem { /// /// Identifier for VxFS @@ -48,30 +48,17 @@ namespace DiscImageChef.Filesystems const uint VXFS_MAGIC = 0xA501FCF5; const uint VXFS_BASE = 0x400; - public VxFS() - { - Name = "Veritas filesystem"; - PluginUuid = new Guid("EC372605-7687-453C-8BEA-7E0DFF79CB03"); - CurrentEncoding = Encoding.UTF8; - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public VxFS(Encoding encoding) - { - Name = "Veritas filesystem"; - PluginUuid = new Guid("EC372605-7687-453C-8BEA-7E0DFF79CB03"); - CurrentEncoding = encoding ?? Encoding.UTF8; - } + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "Veritas filesystem"; + public virtual Guid Id => new Guid("EC372605-7687-453C-8BEA-7E0DFF79CB03"); - public VxFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { - Name = "Veritas filesystem"; - PluginUuid = new Guid("EC372605-7687-453C-8BEA-7E0DFF79CB03"); - CurrentEncoding = encoding ?? Encoding.UTF8; - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) - { - ulong vmfsSuperOff = VXFS_BASE / imagePlugin.ImageInfo.SectorSize; + ulong vmfsSuperOff = VXFS_BASE / imagePlugin.Info.SectorSize; if(partition.Start + vmfsSuperOff >= partition.End) return false; @@ -82,9 +69,10 @@ namespace DiscImageChef.Filesystems return magic == VXFS_MAGIC; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { - ulong vmfsSuperOff = VXFS_BASE / imagePlugin.ImageInfo.SectorSize; + currentEncoding = encoding ?? Encoding.UTF8; + ulong vmfsSuperOff = VXFS_BASE / imagePlugin.Info.SectorSize; byte[] sector = imagePlugin.ReadSector(partition.Start + vmfsSuperOff); VxSuperBlock vxSb = new VxSuperBlock(); @@ -98,7 +86,7 @@ namespace DiscImageChef.Filesystems sbInformation.AppendLine("Veritas file system"); sbInformation.AppendFormat("Volume version {0}", vxSb.vs_version).AppendLine(); - sbInformation.AppendFormat("Volume name {0}", StringHandlers.CToString(vxSb.vs_fname, CurrentEncoding)) + sbInformation.AppendFormat("Volume name {0}", StringHandlers.CToString(vxSb.vs_fname, currentEncoding)) .AppendLine(); sbInformation.AppendFormat("Volume has {0} blocks of {1} bytes each", vxSb.vs_bsize, vxSb.vs_size) .AppendLine(); @@ -113,7 +101,7 @@ namespace DiscImageChef.Filesystems information = sbInformation.ToString(); - XmlFsType = new FileSystemType + xmlFsType = new FileSystemType { Type = "Veritas file system", CreationDate = DateHandlers.UnixUnsignedToDateTime(vxSb.vs_ctime, vxSb.vs_cutime), @@ -128,62 +116,57 @@ namespace DiscImageChef.Filesystems }; } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/XFS.cs b/DiscImageChef.Filesystems/XFS.cs index 58a4109c..34c063d8 100644 --- a/DiscImageChef.Filesystems/XFS.cs +++ b/DiscImageChef.Filesystems/XFS.cs @@ -41,42 +41,29 @@ using Schemas; namespace DiscImageChef.Filesystems { - public class XFS : Filesystem + public class XFS : IFilesystem { const uint XFS_MAGIC = 0x58465342; - public XFS() - { - Name = "XFS Filesystem Plugin"; - PluginUuid = new Guid("1D8CD8B8-27E6-410F-9973-D16409225FBA"); - CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public XFS(Encoding encoding) - { - Name = "XFS Filesystem Plugin"; - PluginUuid = new Guid("1D8CD8B8-27E6-410F-9973-D16409225FBA"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "XFS Filesystem Plugin"; + public virtual Guid Id => new Guid("1D8CD8B8-27E6-410F-9973-D16409225FBA"); - public XFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { - Name = "XFS Filesystem Plugin"; - PluginUuid = new Guid("1D8CD8B8-27E6-410F-9973-D16409225FBA"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) - { - if(imagePlugin.ImageInfo.SectorSize < 512) return false; + if(imagePlugin.Info.SectorSize < 512) return false; // Misaligned - if(imagePlugin.ImageInfo.XmlMediaType == XmlMediaType.OpticalDisc) + if(imagePlugin.Info.XmlMediaType == XmlMediaType.OpticalDisc) { XFS_Superblock xfsSb = new XFS_Superblock(); - uint sbSize = (uint)((Marshal.SizeOf(xfsSb) + 0x400) / imagePlugin.ImageInfo.SectorSize); - if((Marshal.SizeOf(xfsSb) + 0x400) % imagePlugin.ImageInfo.SectorSize != 0) sbSize++; + uint sbSize = (uint)((Marshal.SizeOf(xfsSb) + 0x400) / imagePlugin.Info.SectorSize); + if((Marshal.SizeOf(xfsSb) + 0x400) % imagePlugin.Info.SectorSize != 0) sbSize++; byte[] sector = imagePlugin.ReadSectors(partition.Start, sbSize); if(sector.Length < Marshal.SizeOf(xfsSb)) return false; @@ -100,8 +87,8 @@ namespace DiscImageChef.Filesystems { XFS_Superblock xfsSb = new XFS_Superblock(); - uint sbSize = (uint)(Marshal.SizeOf(xfsSb) / imagePlugin.ImageInfo.SectorSize); - if(Marshal.SizeOf(xfsSb) % imagePlugin.ImageInfo.SectorSize != 0) sbSize++; + uint sbSize = (uint)(Marshal.SizeOf(xfsSb) / imagePlugin.Info.SectorSize); + if(Marshal.SizeOf(xfsSb) % imagePlugin.Info.SectorSize != 0) sbSize++; byte[] sector = imagePlugin.ReadSectors(partition.Start + location, sbSize); if(sector.Length < Marshal.SizeOf(xfsSb)) return false; @@ -117,18 +104,19 @@ namespace DiscImageChef.Filesystems return false; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { + currentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); information = ""; - if(imagePlugin.ImageInfo.SectorSize < 512) return; + if(imagePlugin.Info.SectorSize < 512) return; XFS_Superblock xfsSb = new XFS_Superblock(); // Misaligned - if(imagePlugin.ImageInfo.XmlMediaType == XmlMediaType.OpticalDisc) + if(imagePlugin.Info.XmlMediaType == XmlMediaType.OpticalDisc) { - uint sbSize = (uint)((Marshal.SizeOf(xfsSb) + 0x400) / imagePlugin.ImageInfo.SectorSize); - if((Marshal.SizeOf(xfsSb) + 0x400) % imagePlugin.ImageInfo.SectorSize != 0) sbSize++; + uint sbSize = (uint)((Marshal.SizeOf(xfsSb) + 0x400) / imagePlugin.Info.SectorSize); + if((Marshal.SizeOf(xfsSb) + 0x400) % imagePlugin.Info.SectorSize != 0) sbSize++; byte[] sector = imagePlugin.ReadSectors(partition.Start, sbSize); if(sector.Length < Marshal.SizeOf(xfsSb)) return; @@ -150,8 +138,8 @@ namespace DiscImageChef.Filesystems else foreach(ulong location in new[] {0, 1, 2}) { - uint sbSize = (uint)(Marshal.SizeOf(xfsSb) / imagePlugin.ImageInfo.SectorSize); - if(Marshal.SizeOf(xfsSb) % imagePlugin.ImageInfo.SectorSize != 0) sbSize++; + uint sbSize = (uint)(Marshal.SizeOf(xfsSb) / imagePlugin.Info.SectorSize); + if(Marshal.SizeOf(xfsSb) % imagePlugin.Info.SectorSize != 0) sbSize++; byte[] sector = imagePlugin.ReadSectors(partition.Start + location, sbSize); if(sector.Length < Marshal.SizeOf(xfsSb)) return; @@ -178,12 +166,12 @@ namespace DiscImageChef.Filesystems sb.AppendFormat("{0} allocation groups in volume", xfsSb.agcount).AppendLine(); sb.AppendFormat("{0} inodes in volume, {1} free", xfsSb.icount, xfsSb.ifree).AppendLine(); if(xfsSb.inprogress > 0) sb.AppendLine("fsck in progress"); - sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(xfsSb.fname, CurrentEncoding)).AppendLine(); + sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(xfsSb.fname, currentEncoding)).AppendLine(); sb.AppendFormat("Volume UUID: {0}", xfsSb.uuid).AppendLine(); information = sb.ToString(); - XmlFsType = new FileSystemType + xmlFsType = new FileSystemType { Type = "XFS filesystem", ClusterSize = (int)xfsSb.blocksize, @@ -193,67 +181,62 @@ namespace DiscImageChef.Filesystems Files = (long)(xfsSb.icount - xfsSb.ifree), FilesSpecified = true, Dirty = xfsSb.inprogress > 0, - VolumeName = StringHandlers.CToString(xfsSb.fname, CurrentEncoding), + VolumeName = StringHandlers.CToString(xfsSb.fname, currentEncoding), VolumeSerial = xfsSb.uuid.ToString() }; } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/Xia.cs b/DiscImageChef.Filesystems/Xia.cs index 2b781630..e4127eed 100644 --- a/DiscImageChef.Filesystems/Xia.cs +++ b/DiscImageChef.Filesystems/Xia.cs @@ -41,7 +41,7 @@ using Schemas; namespace DiscImageChef.Filesystems { // Information from the Linux kernel - public class Xia : Filesystem + public class Xia : IFilesystem { const uint XIAFS_SUPER_MAGIC = 0x012FD16D; const uint XIAFS_ROOT_INO = 1; @@ -51,32 +51,18 @@ namespace DiscImageChef.Filesystems const int XIAFS_NUM_BLOCK_POINTERS = 10; const int XIAFS_NAME_LEN = 248; - public Xia() - { - Name = "Xia filesystem"; - PluginUuid = new Guid("169E1DE5-24F2-4EF6-A04D-A4B2CA66DE9D"); - CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "Xia filesystem"; + public virtual Guid Id => new Guid("169E1DE5-24F2-4EF6-A04D-A4B2CA66DE9D"); - public Xia(Encoding encoding) - { - Name = "Xia filesystem"; - PluginUuid = new Guid("169E1DE5-24F2-4EF6-A04D-A4B2CA66DE9D"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } - - public Xia(ImagePlugin imagePlugin, Partition partition, Encoding encoding) - { - Name = "Xia filesystem"; - PluginUuid = new Guid("169E1DE5-24F2-4EF6-A04D-A4B2CA66DE9D"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { int sbSizeInBytes = Marshal.SizeOf(typeof(XiaSuperBlock)); - uint sbSizeInSectors = (uint)(sbSizeInBytes / imagePlugin.ImageInfo.SectorSize); - if(sbSizeInBytes % imagePlugin.ImageInfo.SectorSize > 0) sbSizeInSectors++; + uint sbSizeInSectors = (uint)(sbSizeInBytes / imagePlugin.Info.SectorSize); + if(sbSizeInBytes % imagePlugin.Info.SectorSize > 0) sbSizeInSectors++; if(sbSizeInSectors + partition.Start >= partition.End) return false; byte[] sbSector = imagePlugin.ReadSectors(partition.Start, sbSizeInSectors); @@ -88,15 +74,16 @@ namespace DiscImageChef.Filesystems return supblk.s_magic == XIAFS_SUPER_MAGIC; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { + currentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); information = ""; StringBuilder sb = new StringBuilder(); int sbSizeInBytes = Marshal.SizeOf(typeof(XiaSuperBlock)); - uint sbSizeInSectors = (uint)(sbSizeInBytes / imagePlugin.ImageInfo.SectorSize); - if(sbSizeInBytes % imagePlugin.ImageInfo.SectorSize > 0) sbSizeInSectors++; + uint sbSizeInSectors = (uint)(sbSizeInBytes / imagePlugin.Info.SectorSize); + if(sbSizeInBytes % imagePlugin.Info.SectorSize > 0) sbSizeInSectors++; byte[] sbSector = imagePlugin.ReadSectors(partition.Start, sbSizeInSectors); IntPtr sbPtr = Marshal.AllocHGlobal(sbSizeInBytes); @@ -121,7 +108,7 @@ namespace DiscImageChef.Filesystems supblk.s_kernzones * supblk.s_zone_size).AppendLine(); sb.AppendFormat("First kernel zone: {0}", supblk.s_firstkernzone).AppendLine(); - XmlFsType = new FileSystemType + xmlFsType = new FileSystemType { Bootable = !ArrayHelpers.ArrayIsNullOrEmpty(supblk.s_boot_segment), Clusters = supblk.s_nzones, @@ -132,62 +119,57 @@ namespace DiscImageChef.Filesystems information = sb.ToString(); } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/ZFS.cs b/DiscImageChef.Filesystems/ZFS.cs index b947fb18..9f70c548 100644 --- a/DiscImageChef.Filesystems/ZFS.cs +++ b/DiscImageChef.Filesystems/ZFS.cs @@ -61,7 +61,7 @@ namespace DiscImageChef.Filesystems * Because of this variations, ZFS stored a header indicating the used encoding and endianess before the encoded nvlist. */ [SuppressMessage("ReSharper", "InconsistentNaming")] - public class ZFS : Filesystem + public class ZFS : IFilesystem { const ulong ZEC_MAGIC = 0x0210DA7AB10C7A11; const ulong ZEC_CIGAM = 0x117A0CB17ADA1002; @@ -76,32 +76,16 @@ namespace DiscImageChef.Filesystems const uint ZFS_MAGIC = 0x58465342; - public ZFS() - { - Name = "ZFS Filesystem Plugin"; - PluginUuid = new Guid("0750014F-A714-4692-A369-E23F6EC3659C"); - CurrentEncoding = Encoding.UTF8; - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "ZFS Filesystem Plugin"; + public virtual Guid Id => new Guid("0750014F-A714-4692-A369-E23F6EC3659C"); - public ZFS(Encoding encoding) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { - Name = "ZFS Filesystem Plugin"; - PluginUuid = new Guid("0750014F-A714-4692-A369-E23F6EC3659C"); - // ZFS is always UTF-8 - CurrentEncoding = Encoding.UTF8; - } - - public ZFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) - { - Name = "ZFS Filesystem Plugin"; - PluginUuid = new Guid("0750014F-A714-4692-A369-E23F6EC3659C"); - // ZFS is always UTF-8 - CurrentEncoding = Encoding.UTF8; - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) - { - if(imagePlugin.ImageInfo.SectorSize < 512) return false; + if(imagePlugin.Info.SectorSize < 512) return false; byte[] sector; ulong magic; @@ -120,16 +104,19 @@ namespace DiscImageChef.Filesystems return magic == ZEC_MAGIC || magic == ZEC_CIGAM; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, + Encoding encoding) { + // ZFS is always UTF-8 + currentEncoding = Encoding.UTF8; information = ""; - if(imagePlugin.ImageInfo.SectorSize < 512) return; + if(imagePlugin.Info.SectorSize < 512) return; byte[] sector; ulong magic; ulong nvlistOff = 32; - uint nvlistLen = 114688 / imagePlugin.ImageInfo.SectorSize; + uint nvlistLen = 114688 / imagePlugin.Info.SectorSize; if(partition.Start + 31 < partition.End) { @@ -156,11 +143,11 @@ namespace DiscImageChef.Filesystems information = sb.ToString(); - XmlFsType = new FileSystemType {Type = "ZFS filesystem"}; - if(decodedNvList.TryGetValue("name", out NVS_Item tmpObj)) XmlFsType.VolumeName = (string)tmpObj.value; - if(decodedNvList.TryGetValue("guid", out tmpObj)) XmlFsType.VolumeSerial = $"{(ulong)tmpObj.value}"; + xmlFsType = new FileSystemType {Type = "ZFS filesystem"}; + if(decodedNvList.TryGetValue("name", out NVS_Item tmpObj)) xmlFsType.VolumeName = (string)tmpObj.value; + if(decodedNvList.TryGetValue("guid", out tmpObj)) xmlFsType.VolumeSerial = $"{(ulong)tmpObj.value}"; if(decodedNvList.TryGetValue("pool_guid", out tmpObj)) - XmlFsType.VolumeSetIdentifier = $"{(ulong)tmpObj.value}"; + xmlFsType.VolumeSetIdentifier = $"{(ulong)tmpObj.value}"; } static bool DecodeNvList(byte[] nvlist, out Dictionary decodedNvList) @@ -639,62 +626,57 @@ namespace DiscImageChef.Filesystems return sb.ToString(); } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/dump.cs b/DiscImageChef.Filesystems/dump.cs index 4d46f2f1..50d85933 100644 --- a/DiscImageChef.Filesystems/dump.cs +++ b/DiscImageChef.Filesystems/dump.cs @@ -44,7 +44,7 @@ using ufs_daddr_t = System.Int32; namespace DiscImageChef.Filesystems { [SuppressMessage("ReSharper", "InconsistentNaming")] - public class dump : Filesystem + public class dump : IFilesystem { /// Magic number for old dump const ushort OFS_MAGIC = 60011; @@ -99,30 +99,16 @@ namespace DiscImageChef.Filesystems const int NDADDR = 12; const int NIADDR = 3; - public dump() - { - Name = "dump(8) Plugin"; - PluginUuid = new Guid("E53B4D28-C858-4800-B092-DDAE80D361B9"); - CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); - } + Encoding currentEncoding; + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "dump(8) Plugin"; + public virtual Guid Id => new Guid("E53B4D28-C858-4800-B092-DDAE80D361B9"); + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public dump(Encoding encoding) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { - Name = "dump(8) Plugin"; - PluginUuid = new Guid("E53B4D28-C858-4800-B092-DDAE80D361B9"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } - - public dump(ImagePlugin imagePlugin, Partition partition, Encoding encoding) - { - Name = "dump(8) Plugin"; - PluginUuid = new Guid("E53B4D28-C858-4800-B092-DDAE80D361B9"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) - { - if(imagePlugin.ImageInfo.SectorSize < 512) return false; + if(imagePlugin.Info.SectorSize < 512) return false; // It should be start of a tape or floppy or file if(partition.Start != 0) return false; @@ -131,8 +117,8 @@ namespace DiscImageChef.Filesystems spcl_aix aixHdr = new spcl_aix(); s_spcl newHdr = new s_spcl(); - uint sbSize = (uint)(Marshal.SizeOf(newHdr) / imagePlugin.ImageInfo.SectorSize); - if(Marshal.SizeOf(newHdr) % imagePlugin.ImageInfo.SectorSize != 0) sbSize++; + uint sbSize = (uint)(Marshal.SizeOf(newHdr) / imagePlugin.Info.SectorSize); + if(Marshal.SizeOf(newHdr) % imagePlugin.Info.SectorSize != 0) sbSize++; byte[] sector = imagePlugin.ReadSectors(partition.Start, sbSize); if(sector.Length < Marshal.SizeOf(newHdr)) return false; @@ -161,10 +147,12 @@ namespace DiscImageChef.Filesystems newHdr.c_magic == NFS_CIGAM || newHdr.c_magic == UFS2_MAGIC || newHdr.c_magic == UFS2_CIGAM; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, + Encoding encoding) { + currentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); information = ""; - if(imagePlugin.ImageInfo.SectorSize < 512) return; + if(imagePlugin.Info.SectorSize < 512) return; if(partition.Start != 0) return; @@ -172,8 +160,8 @@ namespace DiscImageChef.Filesystems spcl_aix aixHdr = new spcl_aix(); s_spcl newHdr = new s_spcl(); - uint sbSize = (uint)(Marshal.SizeOf(newHdr) / imagePlugin.ImageInfo.SectorSize); - if(Marshal.SizeOf(newHdr) % imagePlugin.ImageInfo.SectorSize != 0) sbSize++; + uint sbSize = (uint)(Marshal.SizeOf(newHdr) / imagePlugin.Info.SectorSize); + if(Marshal.SizeOf(newHdr) % imagePlugin.Info.SectorSize != 0) sbSize++; byte[] sector = imagePlugin.ReadSectors(partition.Start, sbSize); if(sector.Length < Marshal.SizeOf(newHdr)) return; @@ -225,78 +213,78 @@ namespace DiscImageChef.Filesystems StringBuilder sb = new StringBuilder(); - XmlFsType = new FileSystemType {ClusterSize = 1024, Clusters = (long)(partition.Size / 1024)}; + xmlFsType = new FileSystemType {ClusterSize = 1024, Clusters = (long)(partition.Size / 1024)}; if(useOld) { - XmlFsType.Type = "Old 16-bit dump(8)"; - sb.AppendLine(XmlFsType.Type); + xmlFsType.Type = "Old 16-bit dump(8)"; + sb.AppendLine(xmlFsType.Type); if(oldHdr.c_date > 0) { - XmlFsType.CreationDate = DateHandlers.UnixToDateTime(oldHdr.c_date); - XmlFsType.CreationDateSpecified = true; - sb.AppendFormat("Dump created on {0}", XmlFsType.CreationDate).AppendLine(); + xmlFsType.CreationDate = DateHandlers.UnixToDateTime(oldHdr.c_date); + xmlFsType.CreationDateSpecified = true; + sb.AppendFormat("Dump created on {0}", xmlFsType.CreationDate).AppendLine(); } if(oldHdr.c_ddate > 0) { - XmlFsType.BackupDate = DateHandlers.UnixToDateTime(oldHdr.c_ddate); - XmlFsType.BackupDateSpecified = true; - sb.AppendFormat("Previous dump created on {0}", XmlFsType.BackupDate).AppendLine(); + xmlFsType.BackupDate = DateHandlers.UnixToDateTime(oldHdr.c_ddate); + xmlFsType.BackupDateSpecified = true; + sb.AppendFormat("Previous dump created on {0}", xmlFsType.BackupDate).AppendLine(); } sb.AppendFormat("Dump volume number: {0}", oldHdr.c_volume).AppendLine(); } else if(useAix) { - XmlFsType.Type = "AIX dump(8)"; - sb.AppendLine(XmlFsType.Type); + xmlFsType.Type = "AIX dump(8)"; + sb.AppendLine(xmlFsType.Type); if(aixHdr.c_date > 0) { - XmlFsType.CreationDate = DateHandlers.UnixToDateTime(aixHdr.c_date); - XmlFsType.CreationDateSpecified = true; - sb.AppendFormat("Dump created on {0}", XmlFsType.CreationDate).AppendLine(); + xmlFsType.CreationDate = DateHandlers.UnixToDateTime(aixHdr.c_date); + xmlFsType.CreationDateSpecified = true; + sb.AppendFormat("Dump created on {0}", xmlFsType.CreationDate).AppendLine(); } if(aixHdr.c_ddate > 0) { - XmlFsType.BackupDate = DateHandlers.UnixToDateTime(aixHdr.c_ddate); - XmlFsType.BackupDateSpecified = true; - sb.AppendFormat("Previous dump created on {0}", XmlFsType.BackupDate).AppendLine(); + xmlFsType.BackupDate = DateHandlers.UnixToDateTime(aixHdr.c_ddate); + xmlFsType.BackupDateSpecified = true; + sb.AppendFormat("Previous dump created on {0}", xmlFsType.BackupDate).AppendLine(); } sb.AppendFormat("Dump volume number: {0}", aixHdr.c_volume).AppendLine(); } else { - XmlFsType.Type = "dump(8)"; - sb.AppendLine(XmlFsType.Type); + xmlFsType.Type = "dump(8)"; + sb.AppendLine(xmlFsType.Type); if(newHdr.c_ndate > 0) { - XmlFsType.CreationDate = DateHandlers.UnixToDateTime(newHdr.c_ndate); - XmlFsType.CreationDateSpecified = true; - sb.AppendFormat("Dump created on {0}", XmlFsType.CreationDate).AppendLine(); + xmlFsType.CreationDate = DateHandlers.UnixToDateTime(newHdr.c_ndate); + xmlFsType.CreationDateSpecified = true; + sb.AppendFormat("Dump created on {0}", xmlFsType.CreationDate).AppendLine(); } else if(newHdr.c_date > 0) { - XmlFsType.CreationDate = DateHandlers.UnixToDateTime(newHdr.c_date); - XmlFsType.CreationDateSpecified = true; - sb.AppendFormat("Dump created on {0}", XmlFsType.CreationDate).AppendLine(); + xmlFsType.CreationDate = DateHandlers.UnixToDateTime(newHdr.c_date); + xmlFsType.CreationDateSpecified = true; + sb.AppendFormat("Dump created on {0}", xmlFsType.CreationDate).AppendLine(); } if(newHdr.c_nddate > 0) { - XmlFsType.BackupDate = DateHandlers.UnixToDateTime(newHdr.c_nddate); - XmlFsType.BackupDateSpecified = true; - sb.AppendFormat("Previous dump created on {0}", XmlFsType.BackupDate).AppendLine(); + xmlFsType.BackupDate = DateHandlers.UnixToDateTime(newHdr.c_nddate); + xmlFsType.BackupDateSpecified = true; + sb.AppendFormat("Previous dump created on {0}", xmlFsType.BackupDate).AppendLine(); } else if(newHdr.c_ddate > 0) { - XmlFsType.BackupDate = DateHandlers.UnixToDateTime(newHdr.c_ddate); - XmlFsType.BackupDateSpecified = true; - sb.AppendFormat("Previous dump created on {0}", XmlFsType.BackupDate).AppendLine(); + xmlFsType.BackupDate = DateHandlers.UnixToDateTime(newHdr.c_ddate); + xmlFsType.BackupDateSpecified = true; + sb.AppendFormat("Previous dump created on {0}", xmlFsType.BackupDate).AppendLine(); } sb.AppendFormat("Dump volume number: {0}", newHdr.c_volume).AppendLine(); sb.AppendFormat("Dump level: {0}", newHdr.c_level).AppendLine(); string dumpname = StringHandlers.CToString(newHdr.c_label); if(!string.IsNullOrEmpty(dumpname)) { - XmlFSType.VolumeName = dumpname; + XmlFsType.VolumeName = dumpname; sb.AppendFormat("Dump label: {0}", dumpname).AppendLine(); } @@ -311,62 +299,57 @@ namespace DiscImageChef.Filesystems information = sb.ToString(); } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/exFAT.cs b/DiscImageChef.Filesystems/exFAT.cs index 09d0739e..6833ac5e 100644 --- a/DiscImageChef.Filesystems/exFAT.cs +++ b/DiscImageChef.Filesystems/exFAT.cs @@ -42,34 +42,20 @@ using Schemas; namespace DiscImageChef.Filesystems { // Information from https://www.sans.org/reading-room/whitepapers/forensics/reverse-engineering-microsoft-exfat-file-system-33274 - public class exFAT : Filesystem + public class exFAT : IFilesystem { readonly Guid OEM_FLASH_PARAMETER_GUID = new Guid("0A0C7E46-3399-4021-90C8-FA6D389C4BA2"); readonly byte[] Signature = {0x45, 0x58, 0x46, 0x41, 0x54, 0x20, 0x20, 0x20}; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public exFAT() - { - Name = "Microsoft Extended File Allocation Table"; - PluginUuid = new Guid("8271D088-1533-4CB3-AC28-D802B68BB95C"); - CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); - } + Encoding currentEncoding; + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "Microsoft Extended File Allocation Table"; + public virtual Guid Id => new Guid("8271D088-1533-4CB3-AC28-D802B68BB95C"); - public exFAT(Encoding encoding) - { - Name = "Microsoft Extended File Allocation Table"; - PluginUuid = new Guid("8271D088-1533-4CB3-AC28-D802B68BB95C"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } - - public exFAT(ImagePlugin imagePlugin, Partition partition, Encoding encoding) - { - Name = "Microsoft Extended File Allocation Table"; - PluginUuid = new Guid("8271D088-1533-4CB3-AC28-D802B68BB95C"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { if(12 + partition.Start >= partition.End) return false; @@ -84,12 +70,14 @@ namespace DiscImageChef.Filesystems return Signature.SequenceEqual(vbr.signature); } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, + Encoding encoding) { + currentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); information = ""; StringBuilder sb = new StringBuilder(); - XmlFsType = new FileSystemType(); + xmlFsType = new FileSystemType(); byte[] vbrSector = imagePlugin.ReadSector(0 + partition.Start); IntPtr vbrPtr = Marshal.AllocHGlobal(512); @@ -151,71 +139,66 @@ namespace DiscImageChef.Filesystems sb.AppendFormat("Checksum 0x{0:X8}", chksector.checksum[0]).AppendLine(); - XmlFsType.ClusterSize = (1 << vbr.sectorShift) * (1 << vbr.clusterShift); - XmlFsType.Clusters = vbr.clusterHeapLength; - XmlFsType.Dirty = vbr.flags.HasFlag(VolumeFlags.VolumeDirty); - XmlFsType.Type = "exFAT"; - XmlFsType.VolumeSerial = $"{vbr.volumeSerial:X8}"; + xmlFsType.ClusterSize = (1 << vbr.sectorShift) * (1 << vbr.clusterShift); + xmlFsType.Clusters = vbr.clusterHeapLength; + xmlFsType.Dirty = vbr.flags.HasFlag(VolumeFlags.VolumeDirty); + xmlFsType.Type = "exFAT"; + xmlFsType.VolumeSerial = $"{vbr.volumeSerial:X8}"; information = sb.ToString(); } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { throw new NotImplementedException(); } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { throw new NotImplementedException(); } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno ListXAttr(string path, ref List xattrs) { throw new NotImplementedException(); } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { throw new NotImplementedException(); } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { throw new NotImplementedException(); } - public override Errno Mount(bool debug) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { throw new NotImplementedException(); } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { throw new NotImplementedException(); } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno ReadLink(string path, ref string dest) { throw new NotImplementedException(); } - public override Errno ReadLink(string path, ref string dest) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { throw new NotImplementedException(); } - public override Errno Stat(string path, ref FileEntryInfo stat) + public virtual Errno StatFs(ref FileSystemInfo stat) { throw new NotImplementedException(); } - public override Errno StatFs(ref FileSystemInfo stat) - { - throw new NotImplementedException(); - } - - public override Errno Unmount() + public virtual Errno Unmount() { throw new NotImplementedException(); } diff --git a/DiscImageChef.Filesystems/ext2FS.cs b/DiscImageChef.Filesystems/ext2FS.cs index fcc260e8..d2e0a19f 100644 --- a/DiscImageChef.Filesystems/ext2FS.cs +++ b/DiscImageChef.Filesystems/ext2FS.cs @@ -42,7 +42,7 @@ using Schemas; namespace DiscImageChef.Filesystems { // Information from the Linux kernel - public class ext2FS : Filesystem + public class ext2FS : IFilesystem { const int SB_POS = 0x400; @@ -162,37 +162,24 @@ namespace DiscImageChef.Filesystems /// Testing development code const uint EXT2_FLAGS_TEST_FILESYS = 0x00000004; - public ext2FS() - { - Name = "Linux extended Filesystem 2, 3 and 4"; - PluginUuid = new Guid("6AA91B88-150B-4A7B-AD56-F84FB2DF4184"); - CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); - } + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public ext2FS(Encoding encoding) - { - Name = "Linux extended Filesystem 2, 3 and 4"; - PluginUuid = new Guid("6AA91B88-150B-4A7B-AD56-F84FB2DF4184"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } + public virtual Encoding Encoding => currentEncoding; + public virtual string Name => "Linux extended Filesystem 2, 3 and 4"; + public virtual Guid Id => new Guid("6AA91B88-150B-4A7B-AD56-F84FB2DF4184"); - public ext2FS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { - Name = "Linux extended Filesystem 2, 3 and 4"; - PluginUuid = new Guid("6AA91B88-150B-4A7B-AD56-F84FB2DF4184"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) - { - ulong sbSectorOff = SB_POS / imagePlugin.ImageInfo.SectorSize; - uint sbOff = SB_POS % imagePlugin.ImageInfo.SectorSize; + ulong sbSectorOff = SB_POS / imagePlugin.Info.SectorSize; + uint sbOff = SB_POS % imagePlugin.Info.SectorSize; if(sbSectorOff + partition.Start >= partition.End) return false; int sbSizeInBytes = Marshal.SizeOf(typeof(ext2FSSuperBlock)); - uint sbSizeInSectors = (uint)(sbSizeInBytes / imagePlugin.ImageInfo.SectorSize); - if(sbSizeInBytes % imagePlugin.ImageInfo.SectorSize > 0) sbSizeInSectors++; + uint sbSizeInSectors = (uint)(sbSizeInBytes / imagePlugin.Info.SectorSize); + if(sbSizeInBytes % imagePlugin.Info.SectorSize > 0) sbSizeInSectors++; byte[] sbSector = imagePlugin.ReadSectors(sbSectorOff + partition.Start, sbSizeInSectors); byte[] sb = new byte[sbSizeInBytes]; @@ -203,8 +190,9 @@ namespace DiscImageChef.Filesystems return magic == EXT2_MAGIC || magic == EXT2_MAGIC_OLD; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { + currentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); information = ""; StringBuilder sb = new StringBuilder(); @@ -214,11 +202,11 @@ namespace DiscImageChef.Filesystems bool ext4 = false; int sbSizeInBytes = Marshal.SizeOf(typeof(ext2FSSuperBlock)); - uint sbSizeInSectors = (uint)(sbSizeInBytes / imagePlugin.ImageInfo.SectorSize); - if(sbSizeInBytes % imagePlugin.ImageInfo.SectorSize > 0) sbSizeInSectors++; + uint sbSizeInSectors = (uint)(sbSizeInBytes / imagePlugin.Info.SectorSize); + if(sbSizeInBytes % imagePlugin.Info.SectorSize > 0) sbSizeInSectors++; - ulong sbSectorOff = SB_POS / imagePlugin.ImageInfo.SectorSize; - uint sbOff = SB_POS % imagePlugin.ImageInfo.SectorSize; + ulong sbSectorOff = SB_POS / imagePlugin.Info.SectorSize; + uint sbOff = SB_POS % imagePlugin.Info.SectorSize; byte[] sbSector = imagePlugin.ReadSectors(sbSectorOff + partition.Start, sbSizeInSectors); byte[] sblock = new byte[sbSizeInBytes]; @@ -228,13 +216,13 @@ namespace DiscImageChef.Filesystems ext2FSSuperBlock supblk = (ext2FSSuperBlock)Marshal.PtrToStructure(sbPtr, typeof(ext2FSSuperBlock)); Marshal.FreeHGlobal(sbPtr); - XmlFsType = new FileSystemType(); + xmlFsType = new FileSystemType(); switch(supblk.magic) { case EXT2_MAGIC_OLD: sb.AppendLine("ext2 (old) filesystem"); - XmlFsType.Type = "ext2"; + xmlFsType.Type = "ext2"; break; case EXT2_MAGIC: ext3 |= (supblk.ftr_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) == EXT3_FEATURE_COMPAT_HAS_JOURNAL || @@ -262,17 +250,17 @@ namespace DiscImageChef.Filesystems if(newExt2) { sb.AppendLine("ext2 filesystem"); - XmlFsType.Type = "ext2"; + xmlFsType.Type = "ext2"; } if(ext3) { sb.AppendLine("ext3 filesystem"); - XmlFsType.Type = "ext3"; + xmlFsType.Type = "ext3"; } if(ext4) { sb.AppendLine("ext4 filesystem"); - XmlFsType.Type = "ext4"; + xmlFsType.Type = "ext4"; } break; default: @@ -303,14 +291,14 @@ namespace DiscImageChef.Filesystems break; } - XmlFsType.SystemIdentifier = extOs; + xmlFsType.SystemIdentifier = extOs; if(supblk.mkfs_t > 0) { sb.AppendFormat("Volume was created on {0} for {1}", DateHandlers.UnixUnsignedToDateTime(supblk.mkfs_t), extOs).AppendLine(); - XmlFsType.CreationDate = DateHandlers.UnixUnsignedToDateTime(supblk.mkfs_t); - XmlFsType.CreationDateSpecified = true; + xmlFsType.CreationDate = DateHandlers.UnixUnsignedToDateTime(supblk.mkfs_t); + xmlFsType.CreationDateSpecified = true; } else sb.AppendFormat("Volume was created for {0}", extOs).AppendLine(); @@ -368,8 +356,8 @@ namespace DiscImageChef.Filesystems sb.AppendFormat("Volume has {0} blocks of {1} bytes, for a total of {2} bytes", blocks, 1024 << (int)supblk.block_size, blocks * (ulong)(1024 << (int)supblk.block_size)) .AppendLine(); - XmlFsType.Clusters = (long)blocks; - XmlFsType.ClusterSize = 1024 << (int)supblk.block_size; + xmlFsType.Clusters = (long)blocks; + xmlFsType.ClusterSize = 1024 << (int)supblk.block_size; if(supblk.mount_t > 0 || supblk.mount_c > 0) { if(supblk.mount_t > 0) @@ -381,12 +369,12 @@ namespace DiscImageChef.Filesystems else sb.AppendFormat("Volume has been mounted {0} times with no maximum no. of mounts before checking", supblk.mount_c).AppendLine(); - if(!string.IsNullOrEmpty(StringHandlers.CToString(supblk.last_mount_dir, CurrentEncoding))) + if(!string.IsNullOrEmpty(StringHandlers.CToString(supblk.last_mount_dir, currentEncoding))) sb.AppendFormat("Last mounted on: \"{0}\"", - StringHandlers.CToString(supblk.last_mount_dir, CurrentEncoding)).AppendLine(); - if(!string.IsNullOrEmpty(StringHandlers.CToString(supblk.mount_options, CurrentEncoding))) + StringHandlers.CToString(supblk.last_mount_dir, currentEncoding)).AppendLine(); + if(!string.IsNullOrEmpty(StringHandlers.CToString(supblk.mount_options, currentEncoding))) sb.AppendFormat("Last used mount options were: {0}", - StringHandlers.CToString(supblk.mount_options, CurrentEncoding)).AppendLine(); + StringHandlers.CToString(supblk.mount_options, currentEncoding)).AppendLine(); } else { @@ -415,17 +403,17 @@ namespace DiscImageChef.Filesystems { sb.AppendFormat("Last written on {0}", DateHandlers.UnixUnsignedToDateTime(supblk.write_t)) .AppendLine(); - XmlFsType.ModificationDate = DateHandlers.UnixUnsignedToDateTime(supblk.write_t); - XmlFsType.ModificationDateSpecified = true; + xmlFsType.ModificationDate = DateHandlers.UnixUnsignedToDateTime(supblk.write_t); + xmlFsType.ModificationDateSpecified = true; } else sb.AppendLine("Volume has never been written"); - XmlFsType.Dirty = true; + xmlFsType.Dirty = true; switch(supblk.state) { case EXT2_VALID_FS: sb.AppendLine("Volume is clean"); - XmlFsType.Dirty = false; + xmlFsType.Dirty = false; break; case EXT2_ERROR_FS: sb.AppendLine("Volume is dirty"); @@ -438,11 +426,11 @@ namespace DiscImageChef.Filesystems break; } - if(!string.IsNullOrEmpty(StringHandlers.CToString(supblk.volume_name, CurrentEncoding))) + if(!string.IsNullOrEmpty(StringHandlers.CToString(supblk.volume_name, currentEncoding))) { - sb.AppendFormat("Volume name: \"{0}\"", StringHandlers.CToString(supblk.volume_name, CurrentEncoding)) + sb.AppendFormat("Volume name: \"{0}\"", StringHandlers.CToString(supblk.volume_name, currentEncoding)) .AppendLine(); - XmlFsType.VolumeName = StringHandlers.CToString(supblk.volume_name, CurrentEncoding); + xmlFsType.VolumeName = StringHandlers.CToString(supblk.volume_name, currentEncoding); } switch(supblk.err_behaviour) @@ -468,15 +456,15 @@ namespace DiscImageChef.Filesystems if(supblk.uuid != Guid.Empty) { sb.AppendFormat("Volume UUID: {0}", supblk.uuid).AppendLine(); - XmlFsType.VolumeSerial = supblk.uuid.ToString(); + xmlFsType.VolumeSerial = supblk.uuid.ToString(); } if(supblk.kbytes_written > 0) sb.AppendFormat("{0} KiB has been written on volume", supblk.kbytes_written).AppendLine(); sb.AppendFormat("{0} reserved and {1} free blocks", reserved, free).AppendLine(); - XmlFsType.FreeClusters = (long)free; - XmlFsType.FreeClustersSpecified = true; + xmlFsType.FreeClusters = (long)free; + xmlFsType.FreeClustersSpecified = true; sb.AppendFormat("{0} inodes with {1} free inodes ({2}%)", supblk.inodes, supblk.free_inodes, supblk.free_inodes * 100 / supblk.inodes).AppendLine(); if(supblk.first_inode > 0) sb.AppendFormat("First inode is {0}", supblk.first_inode).AppendLine(); @@ -643,62 +631,57 @@ namespace DiscImageChef.Filesystems information = sb.ToString(); } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filesystems/extFS.cs b/DiscImageChef.Filesystems/extFS.cs index 08519e2b..b3020970 100644 --- a/DiscImageChef.Filesystems/extFS.cs +++ b/DiscImageChef.Filesystems/extFS.cs @@ -41,7 +41,7 @@ using Schemas; namespace DiscImageChef.Filesystems { // Information from the Linux kernel - public class extFS : Filesystem + public class extFS : IFilesystem { const int SB_POS = 0x400; @@ -49,34 +49,20 @@ namespace DiscImageChef.Filesystems /// ext superblock magic /// const ushort EXT_MAGIC = 0x137D; + Encoding currentEncoding; + FileSystemType xmlFsType; + public virtual FileSystemType XmlFsType => xmlFsType; - public extFS() + public virtual string Name => "Linux extended Filesystem"; + public virtual Guid Id => new Guid("076CB3A2-08C2-4D69-BC8A-FCAA2E502BE2"); + public virtual Encoding Encoding => currentEncoding; + + public virtual bool Identify(IMediaImage imagePlugin, Partition partition) { - Name = "Linux extended Filesystem"; - PluginUuid = new Guid("076CB3A2-08C2-4D69-BC8A-FCAA2E502BE2"); - CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); - } + if(imagePlugin.Info.SectorSize < 512) return false; - public extFS(Encoding encoding) - { - Name = "Linux extended Filesystem"; - PluginUuid = new Guid("076CB3A2-08C2-4D69-BC8A-FCAA2E502BE2"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } - - public extFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) - { - Name = "Linux extended Filesystem"; - PluginUuid = new Guid("076CB3A2-08C2-4D69-BC8A-FCAA2E502BE2"); - CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); - } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) - { - if(imagePlugin.ImageInfo.SectorSize < 512) return false; - - ulong sbSectorOff = SB_POS / imagePlugin.ImageInfo.SectorSize; - uint sbOff = SB_POS % imagePlugin.ImageInfo.SectorSize; + ulong sbSectorOff = SB_POS / imagePlugin.Info.SectorSize; + uint sbOff = SB_POS % imagePlugin.Info.SectorSize; if(sbSectorOff + partition.Start >= partition.End) return false; @@ -89,16 +75,18 @@ namespace DiscImageChef.Filesystems return magic == EXT_MAGIC; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + public virtual void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, + Encoding encoding) { + currentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); information = ""; StringBuilder sb = new StringBuilder(); - if(imagePlugin.ImageInfo.SectorSize < 512) return; + if(imagePlugin.Info.SectorSize < 512) return; - ulong sbSectorOff = SB_POS / imagePlugin.ImageInfo.SectorSize; - uint sbOff = SB_POS % imagePlugin.ImageInfo.SectorSize; + ulong sbSectorOff = SB_POS / imagePlugin.Info.SectorSize; + uint sbOff = SB_POS % imagePlugin.Info.SectorSize; if(sbSectorOff + partition.Start >= partition.End) return; @@ -130,74 +118,69 @@ namespace DiscImageChef.Filesystems sb.AppendFormat("Log zone size: {0}", extSb.logzonesize); sb.AppendFormat("Max zone size: {0}", extSb.maxsize); - XmlFsType = new FileSystemType + xmlFsType = new FileSystemType { Type = "ext", FreeClusters = extSb.freecountblk, FreeClustersSpecified = true, ClusterSize = 1024, - Clusters = (long)((partition.End - partition.Start + 1) * imagePlugin.ImageInfo.SectorSize / 1024) + Clusters = (long)((partition.End - partition.Start + 1) * imagePlugin.Info.SectorSize / 1024) }; information = sb.ToString(); } - public override Errno Mount() + public virtual Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, bool debug) { return Errno.NotImplemented; } - public override Errno Mount(bool debug) + public virtual Errno Unmount() { return Errno.NotImplemented; } - public override Errno Unmount() + public virtual Errno MapBlock(string path, long fileBlock, ref long deviceBlock) { return Errno.NotImplemented; } - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + public virtual Errno GetAttributes(string path, ref FileAttributes attributes) { return Errno.NotImplemented; } - public override Errno GetAttributes(string path, ref FileAttributes attributes) + public virtual Errno ListXAttr(string path, ref List xattrs) { return Errno.NotImplemented; } - public override Errno ListXAttr(string path, ref List xattrs) + public virtual Errno GetXattr(string path, string xattr, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno GetXattr(string path, string xattr, ref byte[] buf) + public virtual Errno Read(string path, long offset, long size, ref byte[] buf) { return Errno.NotImplemented; } - public override Errno Read(string path, long offset, long size, ref byte[] buf) + public virtual Errno ReadDir(string path, ref List contents) { return Errno.NotImplemented; } - public override Errno ReadDir(string path, ref List contents) + public virtual Errno StatFs(ref FileSystemInfo stat) { return Errno.NotImplemented; } - public override Errno StatFs(ref FileSystemInfo stat) + public virtual Errno Stat(string path, ref FileEntryInfo stat) { return Errno.NotImplemented; } - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) + public virtual Errno ReadLink(string path, ref string dest) { return Errno.NotImplemented; } diff --git a/DiscImageChef.Filters/AppleDouble.cs b/DiscImageChef.Filters/AppleDouble.cs index 48405edc..e0b54b09 100644 --- a/DiscImageChef.Filters/AppleDouble.cs +++ b/DiscImageChef.Filters/AppleDouble.cs @@ -40,7 +40,7 @@ namespace DiscImageChef.Filters /// /// Decodes AppleDouble files /// - public class AppleDouble : Filter + public class AppleDouble : IFilter { const uint AppleDoubleMagic = 0x00051607; const uint AppleDoubleVersion = 0x00010000; @@ -68,68 +68,65 @@ namespace DiscImageChef.Filters bool opened; AppleDoubleEntry rsrcFork; - public AppleDouble() - { - Name = "AppleDouble"; - UUID = new Guid("1B2165EE-C9DF-4B21-BBBB-9E5892B2DF4D"); - } + public virtual string Name => "AppleDouble"; + public virtual Guid Id => new Guid("1B2165EE-C9DF-4B21-BBBB-9E5892B2DF4D"); - public override void Close() + public virtual void Close() { opened = false; } - public override string GetBasePath() + public virtual string GetBasePath() { return basePath; } - public override DateTime GetCreationTime() + public virtual DateTime GetCreationTime() { return creationTime; } - public override long GetDataForkLength() + public virtual long GetDataForkLength() { return dataFork.length; } - public override Stream GetDataForkStream() + public virtual Stream GetDataForkStream() { return new FileStream(basePath, FileMode.Open, FileAccess.Read); } - public override string GetFilename() + public virtual string GetFilename() { return Path.GetFileName(basePath); } - public override DateTime GetLastWriteTime() + public virtual DateTime GetLastWriteTime() { return lastWriteTime; } - public override long GetLength() + public virtual long GetLength() { return dataFork.length + rsrcFork.length; } - public override string GetParentFolder() + public virtual string GetParentFolder() { return Path.GetDirectoryName(basePath); } - public override string GetPath() + public virtual string GetPath() { return basePath; } - public override long GetResourceForkLength() + public virtual long GetResourceForkLength() { return rsrcFork.length; } - public override Stream GetResourceForkStream() + public virtual Stream GetResourceForkStream() { if(rsrcFork.length == 0) return null; @@ -137,24 +134,24 @@ namespace DiscImageChef.Filters rsrcFork.offset + rsrcFork.length - 1); } - public override bool HasResourceFork() + public virtual bool HasResourceFork() { return rsrcFork.length > 0; } - public override bool Identify(byte[] buffer) + public virtual bool Identify(byte[] buffer) { // Now way to have two files in a single byte array return false; } - public override bool Identify(Stream stream) + public virtual bool Identify(Stream stream) { // Now way to have two files in a single stream return false; } - public override bool Identify(string path) + public virtual bool Identify(string path) { // Prepend data fork name with "R." string ProDosAppleDouble; @@ -306,24 +303,24 @@ namespace DiscImageChef.Filters (header.version == AppleDoubleVersion || header.version == AppleDoubleVersion2); } - public override bool IsOpened() + public virtual bool IsOpened() { return opened; } - public override void Open(byte[] buffer) + public virtual void Open(byte[] buffer) { // Now way to have two files in a single byte array throw new NotSupportedException(); } - public override void Open(Stream stream) + public virtual void Open(Stream stream) { // Now way to have two files in a single stream throw new NotSupportedException(); } - public override void Open(string path) + public virtual void Open(string path) { // Prepend data fork name with "R." string ProDosAppleDouble; diff --git a/DiscImageChef.Filters/AppleSingle.cs b/DiscImageChef.Filters/AppleSingle.cs index 622d331d..148d60b5 100644 --- a/DiscImageChef.Filters/AppleSingle.cs +++ b/DiscImageChef.Filters/AppleSingle.cs @@ -40,7 +40,7 @@ namespace DiscImageChef.Filters /// /// Decodes AppleSingle files /// - public class AppleSingle : Filter + public class AppleSingle : IFilter { const uint AppleSingleMagic = 0x00051600; const uint AppleSingleVersion = 0x00010000; @@ -69,13 +69,10 @@ namespace DiscImageChef.Filters AppleSingleEntry rsrcFork; Stream stream; - public AppleSingle() - { - Name = "AppleSingle"; - UUID = new Guid("A69B20E8-F4D3-42BB-BD2B-4A7263394A05"); - } + public virtual string Name => "AppleSingle"; + public virtual Guid Id => new Guid("A69B20E8-F4D3-42BB-BD2B-4A7263394A05"); - public override void Close() + public virtual void Close() { bytes = null; stream?.Close(); @@ -85,22 +82,22 @@ namespace DiscImageChef.Filters opened = false; } - public override string GetBasePath() + public virtual string GetBasePath() { return basePath; } - public override DateTime GetCreationTime() + public virtual DateTime GetCreationTime() { return creationTime; } - public override long GetDataForkLength() + public virtual long GetDataForkLength() { return dataFork.length; } - public override Stream GetDataForkStream() + public virtual Stream GetDataForkStream() { if(dataFork.length == 0) return null; @@ -113,37 +110,37 @@ namespace DiscImageChef.Filters return null; } - public override string GetFilename() + public virtual string GetFilename() { return Path.GetFileName(basePath); } - public override DateTime GetLastWriteTime() + public virtual DateTime GetLastWriteTime() { return lastWriteTime; } - public override long GetLength() + public virtual long GetLength() { return dataFork.length + rsrcFork.length; } - public override string GetParentFolder() + public virtual string GetParentFolder() { return Path.GetDirectoryName(basePath); } - public override string GetPath() + public virtual string GetPath() { return basePath; } - public override long GetResourceForkLength() + public virtual long GetResourceForkLength() { return rsrcFork.length; } - public override Stream GetResourceForkStream() + public virtual Stream GetResourceForkStream() { if(rsrcFork.length == 0) return null; @@ -156,12 +153,12 @@ namespace DiscImageChef.Filters return null; } - public override bool HasResourceFork() + public virtual bool HasResourceFork() { return rsrcFork.length > 0; } - public override bool Identify(byte[] buffer) + public virtual bool Identify(byte[] buffer) { if(buffer == null || buffer.Length < 26) return false; @@ -173,7 +170,7 @@ namespace DiscImageChef.Filters (header.version == AppleSingleVersion || header.version == AppleSingleVersion2); } - public override bool Identify(Stream stream) + public virtual bool Identify(Stream stream) { if(stream == null || stream.Length < 26) return false; @@ -186,7 +183,7 @@ namespace DiscImageChef.Filters (header.version == AppleSingleVersion || header.version == AppleSingleVersion2); } - public override bool Identify(string path) + public virtual bool Identify(string path) { FileStream fstream = new FileStream(path, FileMode.Open, FileAccess.Read); if(fstream.Length < 26) return false; @@ -200,12 +197,12 @@ namespace DiscImageChef.Filters (header.version == AppleSingleVersion || header.version == AppleSingleVersion2); } - public override bool IsOpened() + public virtual bool IsOpened() { return opened; } - public override void Open(byte[] buffer) + public virtual void Open(byte[] buffer) { MemoryStream ms = new MemoryStream(buffer); ms.Seek(0, SeekOrigin.Begin); @@ -283,7 +280,7 @@ namespace DiscImageChef.Filters bytes = buffer; } - public override void Open(Stream stream) + public virtual void Open(Stream stream) { stream.Seek(0, SeekOrigin.Begin); @@ -360,7 +357,7 @@ namespace DiscImageChef.Filters this.stream = stream; } - public override void Open(string path) + public virtual void Open(string path) { FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read); fs.Seek(0, SeekOrigin.Begin); diff --git a/DiscImageChef.Filters/BZip2.cs b/DiscImageChef.Filters/BZip2.cs index a14d6d50..b1253696 100644 --- a/DiscImageChef.Filters/BZip2.cs +++ b/DiscImageChef.Filters/BZip2.cs @@ -40,7 +40,7 @@ namespace DiscImageChef.Filters /// /// Decompress bz2 files while reading /// - public class BZip2 : Filter + public class BZip2 : IFilter { string basePath; DateTime creationTime; @@ -50,13 +50,10 @@ namespace DiscImageChef.Filters DateTime lastWriteTime; bool opened; - public BZip2() - { - Name = "BZip2"; - UUID = new Guid("FCCFB0C3-32EF-40D8-9714-2333F6AC72A9"); - } + public virtual string Name => "BZip2"; + public virtual Guid Id => new Guid("FCCFB0C3-32EF-40D8-9714-2333F6AC72A9"); - public override void Close() + public virtual void Close() { dataStream?.Close(); dataStream = null; @@ -64,32 +61,32 @@ namespace DiscImageChef.Filters opened = false; } - public override string GetBasePath() + public virtual string GetBasePath() { return basePath; } - public override Stream GetDataForkStream() + public virtual Stream GetDataForkStream() { return innerStream; } - public override string GetPath() + public virtual string GetPath() { return basePath; } - public override Stream GetResourceForkStream() + public virtual Stream GetResourceForkStream() { return null; } - public override bool HasResourceFork() + public virtual bool HasResourceFork() { return false; } - public override bool Identify(byte[] buffer) + public virtual bool Identify(byte[] buffer) { if(buffer[0] != 0x42 || buffer[1] != 0x5A || buffer[2] != 0x68 || buffer[3] < 0x31 || buffer[3] > 0x39) return false; @@ -100,7 +97,7 @@ namespace DiscImageChef.Filters buffer[buffer.Length - 510] != 0x6C || buffer[buffer.Length - 509] != 0x79; } - public override bool Identify(Stream stream) + public virtual bool Identify(Stream stream) { byte[] buffer = new byte[4]; @@ -120,7 +117,7 @@ namespace DiscImageChef.Filters return buffer[0] != 0x6B || buffer[1] != 0x6F || buffer[2] != 0x6C || buffer[3] != 0x79; } - public override bool Identify(string path) + public virtual bool Identify(string path) { if(!File.Exists(path)) return false; @@ -145,7 +142,7 @@ namespace DiscImageChef.Filters return true; } - public override void Open(byte[] buffer) + public virtual void Open(byte[] buffer) { dataStream = new MemoryStream(buffer); basePath = null; @@ -156,7 +153,7 @@ namespace DiscImageChef.Filters opened = true; } - public override void Open(Stream stream) + public virtual void Open(Stream stream) { dataStream = stream; basePath = null; @@ -167,7 +164,7 @@ namespace DiscImageChef.Filters opened = true; } - public override void Open(string path) + public virtual void Open(string path) { dataStream = new FileStream(path, FileMode.Open, FileAccess.Read); basePath = Path.GetFullPath(path); @@ -183,32 +180,32 @@ namespace DiscImageChef.Filters opened = true; } - public override DateTime GetCreationTime() + public virtual DateTime GetCreationTime() { return creationTime; } - public override long GetDataForkLength() + public virtual long GetDataForkLength() { return decompressedSize; } - public override DateTime GetLastWriteTime() + public virtual DateTime GetLastWriteTime() { return lastWriteTime; } - public override long GetLength() + public virtual long GetLength() { return decompressedSize; } - public override long GetResourceForkLength() + public virtual long GetResourceForkLength() { return 0; } - public override string GetFilename() + public virtual string GetFilename() { if(basePath?.EndsWith(".bz2", StringComparison.InvariantCultureIgnoreCase) == true) return basePath.Substring(0, basePath.Length - 4); @@ -218,12 +215,12 @@ namespace DiscImageChef.Filters return basePath; } - public override string GetParentFolder() + public virtual string GetParentFolder() { return Path.GetDirectoryName(basePath); } - public override bool IsOpened() + public virtual bool IsOpened() { return opened; } diff --git a/DiscImageChef.Filters/DiscImageChef.Filters.csproj b/DiscImageChef.Filters/DiscImageChef.Filters.csproj index 7b083855..dd023ae0 100644 --- a/DiscImageChef.Filters/DiscImageChef.Filters.csproj +++ b/DiscImageChef.Filters/DiscImageChef.Filters.csproj @@ -38,7 +38,7 @@ - + diff --git a/DiscImageChef.Filters/Filters.cs b/DiscImageChef.Filters/Filters.cs index 8484f1cd..273ff4e8 100644 --- a/DiscImageChef.Filters/Filters.cs +++ b/DiscImageChef.Filters/Filters.cs @@ -32,6 +32,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Reflection; using DiscImageChef.Console; @@ -39,22 +40,20 @@ namespace DiscImageChef.Filters { public class FiltersList { - public SortedDictionary Filters; + public SortedDictionary Filters; /// /// Fills the list of all known filters /// public FiltersList() { - Assembly assembly = Assembly.GetAssembly(typeof(Filter)); - Filters = new SortedDictionary(); + Assembly assembly = Assembly.GetAssembly(typeof(IFilter)); + Filters = new SortedDictionary(); - foreach(Type type in assembly.GetTypes()) + foreach(Type type in assembly.GetTypes().Where(t => t.GetInterfaces().Contains(typeof(IFilter)))) try { - if(!type.IsSubclassOf(typeof(Filter))) continue; - - Filter filter = (Filter)type.GetConstructor(Type.EmptyTypes)?.Invoke(new object[] { }); + IFilter filter = (IFilter)type.GetConstructor(Type.EmptyTypes)?.Invoke(new object[] { }); if(filter != null && !Filters.ContainsKey(filter.Name.ToLower())) Filters.Add(filter.Name.ToLower(), filter); } @@ -66,17 +65,17 @@ namespace DiscImageChef.Filters /// /// Path /// The filter that allows reading the specified path - public Filter GetFilter(string path) + public IFilter GetFilter(string path) { - Filter noFilter = null; + IFilter noFilter = null; - foreach(Filter filter in Filters.Values) - if(filter.UUID != new Guid("12345678-AAAA-BBBB-CCCC-123456789000")) + foreach(IFilter filter in Filters.Values) + if(filter.Id != new Guid("12345678-AAAA-BBBB-CCCC-123456789000")) { if(!filter.Identify(path)) continue; - Filter foundFilter = - (Filter)filter.GetType().GetConstructor(Type.EmptyTypes)?.Invoke(new object[] { }); + IFilter foundFilter = + (IFilter)filter.GetType().GetConstructor(Type.EmptyTypes)?.Invoke(new object[] { }); foundFilter?.Open(path); @@ -95,7 +94,7 @@ namespace DiscImageChef.Filters /// Gets all known filters /// /// Known filters - public SortedDictionary GetFiltersList() + public SortedDictionary GetFiltersList() { return Filters; } diff --git a/DiscImageChef.Filters/GZip.cs b/DiscImageChef.Filters/GZip.cs index f8becc39..13e36861 100644 --- a/DiscImageChef.Filters/GZip.cs +++ b/DiscImageChef.Filters/GZip.cs @@ -39,7 +39,7 @@ namespace DiscImageChef.Filters /// /// Decompress gzip files while reading /// - public class GZip : Filter + public class GZip : IFilter { string basePath; DateTime creationTime; @@ -49,13 +49,10 @@ namespace DiscImageChef.Filters bool opened; Stream zStream; - public GZip() - { - Name = "GZip"; - UUID = new Guid("F4996661-4A29-42C9-A2C7-3904EF40F3B0"); - } + public virtual string Name => "GZip"; + public virtual Guid Id => new Guid("F4996661-4A29-42C9-A2C7-3904EF40F3B0"); - public override void Close() + public virtual void Close() { dataStream?.Close(); dataStream = null; @@ -63,37 +60,37 @@ namespace DiscImageChef.Filters opened = false; } - public override string GetBasePath() + public virtual string GetBasePath() { return basePath; } - public override Stream GetDataForkStream() + public virtual Stream GetDataForkStream() { return zStream; } - public override string GetPath() + public virtual string GetPath() { return basePath; } - public override Stream GetResourceForkStream() + public virtual Stream GetResourceForkStream() { return null; } - public override bool HasResourceFork() + public virtual bool HasResourceFork() { return false; } - public override bool Identify(byte[] buffer) + public virtual bool Identify(byte[] buffer) { return buffer[0] == 0x1F && buffer[1] == 0x8B && buffer[2] == 0x08; } - public override bool Identify(Stream stream) + public virtual bool Identify(Stream stream) { byte[] buffer = new byte[3]; @@ -104,7 +101,7 @@ namespace DiscImageChef.Filters return buffer[0] == 0x1F && buffer[1] == 0x8B && buffer[2] == 0x08; } - public override bool Identify(string path) + public virtual bool Identify(string path) { if(!File.Exists(path)) return false; @@ -118,7 +115,7 @@ namespace DiscImageChef.Filters return buffer[0] == 0x1F && buffer[1] == 0x8B && buffer[2] == 0x08; } - public override void Open(byte[] buffer) + public virtual void Open(byte[] buffer) { byte[] mtime_b = new byte[4]; byte[] isize_b = new byte[4]; @@ -144,7 +141,7 @@ namespace DiscImageChef.Filters opened = true; } - public override void Open(Stream stream) + public virtual void Open(Stream stream) { byte[] mtime_b = new byte[4]; byte[] isize_b = new byte[4]; @@ -170,7 +167,7 @@ namespace DiscImageChef.Filters opened = true; } - public override void Open(string path) + public virtual void Open(string path) { byte[] mtime_b = new byte[4]; byte[] isize_b = new byte[4]; @@ -197,32 +194,32 @@ namespace DiscImageChef.Filters opened = true; } - public override DateTime GetCreationTime() + public virtual DateTime GetCreationTime() { return creationTime; } - public override long GetDataForkLength() + public virtual long GetDataForkLength() { return decompressedSize; } - public override DateTime GetLastWriteTime() + public virtual DateTime GetLastWriteTime() { return lastWriteTime; } - public override long GetLength() + public virtual long GetLength() { return decompressedSize; } - public override long GetResourceForkLength() + public virtual long GetResourceForkLength() { return 0; } - public override string GetFilename() + public virtual string GetFilename() { if(basePath?.EndsWith(".gz", StringComparison.InvariantCultureIgnoreCase) == true) return basePath.Substring(0, basePath.Length - 3); @@ -232,12 +229,12 @@ namespace DiscImageChef.Filters return basePath; } - public override string GetParentFolder() + public virtual string GetParentFolder() { return Path.GetDirectoryName(basePath); } - public override bool IsOpened() + public virtual bool IsOpened() { return opened; } diff --git a/DiscImageChef.Filters/Filter.cs b/DiscImageChef.Filters/IFilter.cs similarity index 75% rename from DiscImageChef.Filters/Filter.cs rename to DiscImageChef.Filters/IFilter.cs index ff4672e6..66ab1822 100644 --- a/DiscImageChef.Filters/Filter.cs +++ b/DiscImageChef.Filters/IFilter.cs @@ -2,7 +2,7 @@ // The Disc Image Chef // ---------------------------------------------------------------------------- // -// Filename : Filter.cs +// Filename : IFilter.cs // Author(s) : Natalia Portillo // // Component : Filters. @@ -35,135 +35,138 @@ using System.IO; namespace DiscImageChef.Filters { - public abstract class Filter + public interface IFilter { - public string Name; - public Guid UUID; + /// Descriptive name of the plugin + string Name { get; } + /// Unique UUID of the plugin + Guid Id { get; } /// /// Closes all opened streams. /// - public abstract void Close(); + void Close(); /// /// Gets the path used to open this filter.
- /// UNIX: /path/to/archive.zip/path/to/file.bin => /path/to/archive.zip/path/to/file.bin
- /// Windows: C:\path\to\archive.zip\path\to\file.bin => C:\path\to\archive.zip\path\to\file.bin + /// UNIX: /path/to/archive.zip/path/to/file.bin => /path/to/archive.zip/path/to/file.bin
+ /// Windows: C:\path\to\archive.zip\path\to\file.bin => C:\path\to\archive.zip\path\to\file.bin ///
/// Path used to open this filter. - public abstract string GetBasePath(); + string GetBasePath(); /// /// Gets creation time of file referenced by this filter. /// /// The creation time. - public abstract DateTime GetCreationTime(); + DateTime GetCreationTime(); /// /// Gets length of this filter's data fork. /// /// The data fork length. - public abstract long GetDataForkLength(); + long GetDataForkLength(); /// /// Gets a stream to access the data fork contents. /// /// The data fork stream. - public abstract Stream GetDataForkStream(); + Stream GetDataForkStream(); /// /// Gets the filename for the file referenced by this filter.
- /// UNIX: /path/to/archive.zip/path/to/file.bin => file.bin
- /// Windows: C:\path\to\archive.zip\path\to\file.bin => file.bin + /// UNIX: /path/to/archive.zip/path/to/file.bin => file.bin
+ /// Windows: C:\path\to\archive.zip\path\to\file.bin => file.bin ///
/// The filename. - public abstract string GetFilename(); + string GetFilename(); /// /// Gets last write time of file referenced by this filter. /// /// The last write time. - public abstract DateTime GetLastWriteTime(); + DateTime GetLastWriteTime(); /// /// Gets length of file referenced by ths filter. /// /// The length. - public abstract long GetLength(); + long GetLength(); /// /// Gets full path to file referenced by this filter. If it's an archive, it's the path inside the archive.
- /// UNIX: /path/to/archive.zip/path/to/file.bin => /path/to/file.bin
- /// Windows: C:\path\to\archive.zip\path\to\file.bin => \path\to\file.bin + /// UNIX: /path/to/archive.zip/path/to/file.bin => /path/to/file.bin
+ /// Windows: C:\path\to\archive.zip\path\to\file.bin => \path\to\file.bin ///
/// The path. - public abstract string GetPath(); + string GetPath(); /// /// Gets path to parent folder to the file referenced by this filter. If it's an archive, it's the full path to the /// archive itself.
- /// UNIX: /path/to/archive.zip/path/to/file.bin => /path/to/archive.zip
- /// Windows: C:\path\to\archive.zip\path\to\file.bin => C:\path\to\archive.zip + /// UNIX: /path/to/archive.zip/path/to/file.bin => /path/to/archive.zip
+ /// Windows: C:\path\to\archive.zip\path\to\file.bin => C:\path\to\archive.zip ///
/// The parent folder. - public abstract string GetParentFolder(); + string GetParentFolder(); /// /// Gets length of this filter's resource fork. /// /// The resource fork length. - public abstract long GetResourceForkLength(); + long GetResourceForkLength(); /// /// Gets a stream to access the resource fork contents. /// /// The resource fork stream. - public abstract Stream GetResourceForkStream(); + Stream GetResourceForkStream(); /// /// Returns true if the file referenced by this filter has a resource fork /// - public abstract bool HasResourceFork(); + bool HasResourceFork(); /// /// Identifies if the specified path contains data recognizable by this filter instance /// /// Path. - public abstract bool Identify(string path); + bool Identify(string path); /// /// Identifies if the specified stream contains data recognizable by this filter instance /// /// Stream. - public abstract bool Identify(Stream stream); + bool Identify(Stream stream); /// /// Identifies if the specified buffer contains data recognizable by this filter instance /// /// Buffer. - public abstract bool Identify(byte[] buffer); + bool Identify(byte[] buffer); /// - /// Returns true if the filter has a file/stream/buffer currently opened and no has been issued. + /// Returns true if the filter has a file/stream/buffer currently opened and no + /// has been issued. /// - public abstract bool IsOpened(); + bool IsOpened(); /// /// Opens the specified path with this filter instance /// /// Path. - public abstract void Open(string path); + void Open(string path); /// /// Opens the specified stream with this filter instance /// /// Stream. - public abstract void Open(Stream stream); + void Open(Stream stream); /// /// Opens the specified buffer with this filter instance /// /// Buffer. - public abstract void Open(byte[] buffer); + void Open(byte[] buffer); } } \ No newline at end of file diff --git a/DiscImageChef.Filters/LZip.cs b/DiscImageChef.Filters/LZip.cs index be438b0e..7958dd19 100644 --- a/DiscImageChef.Filters/LZip.cs +++ b/DiscImageChef.Filters/LZip.cs @@ -40,7 +40,7 @@ namespace DiscImageChef.Filters /// /// Decompress lzip files while reading /// - public class LZip : Filter + public class LZip : IFilter { string basePath; DateTime creationTime; @@ -50,13 +50,10 @@ namespace DiscImageChef.Filters DateTime lastWriteTime; bool opened; - public LZip() - { - Name = "LZip"; - UUID = new Guid("09D715E9-20C0-48B1-A8D9-D8897CEC57C9"); - } + public virtual string Name => "LZip"; + public virtual Guid Id => new Guid("09D715E9-20C0-48B1-A8D9-D8897CEC57C9"); - public override void Close() + public virtual void Close() { dataStream?.Close(); dataStream = null; @@ -64,38 +61,38 @@ namespace DiscImageChef.Filters opened = false; } - public override string GetBasePath() + public virtual string GetBasePath() { return basePath; } - public override Stream GetDataForkStream() + public virtual Stream GetDataForkStream() { return innerStream; } - public override string GetPath() + public virtual string GetPath() { return basePath; } - public override Stream GetResourceForkStream() + public virtual Stream GetResourceForkStream() { return null; } - public override bool HasResourceFork() + public virtual bool HasResourceFork() { return false; } - public override bool Identify(byte[] buffer) + public virtual bool Identify(byte[] buffer) { return buffer[0] == 0x4C && buffer[1] == 0x5A && buffer[2] == 0x49 && buffer[3] == 0x50 && buffer[4] == 0x01; } - public override bool Identify(Stream stream) + public virtual bool Identify(Stream stream) { byte[] buffer = new byte[5]; @@ -107,7 +104,7 @@ namespace DiscImageChef.Filters buffer[4] == 0x01; } - public override bool Identify(string path) + public virtual bool Identify(string path) { if(!File.Exists(path)) return false; @@ -122,7 +119,7 @@ namespace DiscImageChef.Filters buffer[4] == 0x01; } - public override void Open(byte[] buffer) + public virtual void Open(byte[] buffer) { dataStream = new MemoryStream(buffer); basePath = null; @@ -134,7 +131,7 @@ namespace DiscImageChef.Filters opened = true; } - public override void Open(Stream stream) + public virtual void Open(Stream stream) { dataStream = stream; basePath = null; @@ -150,7 +147,7 @@ namespace DiscImageChef.Filters opened = true; } - public override void Open(string path) + public virtual void Open(string path) { dataStream = new FileStream(path, FileMode.Open, FileAccess.Read); basePath = Path.GetFullPath(path); @@ -171,32 +168,32 @@ namespace DiscImageChef.Filters opened = true; } - public override DateTime GetCreationTime() + public virtual DateTime GetCreationTime() { return creationTime; } - public override long GetDataForkLength() + public virtual long GetDataForkLength() { return decompressedSize; } - public override DateTime GetLastWriteTime() + public virtual DateTime GetLastWriteTime() { return lastWriteTime; } - public override long GetLength() + public virtual long GetLength() { return decompressedSize; } - public override long GetResourceForkLength() + public virtual long GetResourceForkLength() { return 0; } - public override string GetFilename() + public virtual string GetFilename() { if(basePath?.EndsWith(".lz", StringComparison.InvariantCultureIgnoreCase) == true) return basePath.Substring(0, basePath.Length - 3); @@ -206,12 +203,12 @@ namespace DiscImageChef.Filters return basePath; } - public override string GetParentFolder() + public virtual string GetParentFolder() { return Path.GetDirectoryName(basePath); } - public override bool IsOpened() + public virtual bool IsOpened() { return opened; } diff --git a/DiscImageChef.Filters/MacBinary.cs b/DiscImageChef.Filters/MacBinary.cs index f65cc251..cc69f257 100644 --- a/DiscImageChef.Filters/MacBinary.cs +++ b/DiscImageChef.Filters/MacBinary.cs @@ -41,7 +41,7 @@ namespace DiscImageChef.Filters /// /// Decodes MacBinary files /// - public class MacBinary : Filter + public class MacBinary : IFilter { const uint MACBINARY_MAGIC = 0x6D42494E; string basePath; @@ -56,13 +56,10 @@ namespace DiscImageChef.Filters long rsrcForkOff; Stream stream; - public MacBinary() - { - Name = "MacBinary"; - UUID = new Guid("D7C321D3-E51F-45DF-A150-F6BFDF0D7704"); - } + public virtual string Name => "MacBinary"; + public virtual Guid Id => new Guid("D7C321D3-E51F-45DF-A150-F6BFDF0D7704"); - public override void Close() + public virtual void Close() { bytes = null; stream?.Close(); @@ -72,22 +69,22 @@ namespace DiscImageChef.Filters opened = false; } - public override string GetBasePath() + public virtual string GetBasePath() { return basePath; } - public override DateTime GetCreationTime() + public virtual DateTime GetCreationTime() { return creationTime; } - public override long GetDataForkLength() + public virtual long GetDataForkLength() { return header.dataLength; } - public override Stream GetDataForkStream() + public virtual Stream GetDataForkStream() { if(header.dataLength == 0) return null; @@ -100,37 +97,37 @@ namespace DiscImageChef.Filters return null; } - public override string GetFilename() + public virtual string GetFilename() { return filename; } - public override DateTime GetLastWriteTime() + public virtual DateTime GetLastWriteTime() { return lastWriteTime; } - public override long GetLength() + public virtual long GetLength() { return header.dataLength + header.resourceLength; } - public override string GetParentFolder() + public virtual string GetParentFolder() { return Path.GetDirectoryName(basePath); } - public override string GetPath() + public virtual string GetPath() { return basePath; } - public override long GetResourceForkLength() + public virtual long GetResourceForkLength() { return header.resourceLength; } - public override Stream GetResourceForkStream() + public virtual Stream GetResourceForkStream() { if(header.resourceLength == 0) return null; @@ -143,12 +140,12 @@ namespace DiscImageChef.Filters return null; } - public override bool HasResourceFork() + public virtual bool HasResourceFork() { return header.resourceLength > 0; } - public override bool Identify(byte[] buffer) + public virtual bool Identify(byte[] buffer) { if(buffer == null || buffer.Length < 128) return false; @@ -161,7 +158,7 @@ namespace DiscImageChef.Filters (header.dataLength > 0 || header.resourceLength > 0); } - public override bool Identify(Stream stream) + public virtual bool Identify(Stream stream) { if(stream == null || stream.Length < 128) return false; @@ -175,7 +172,7 @@ namespace DiscImageChef.Filters (header.dataLength > 0 || header.resourceLength > 0); } - public override bool Identify(string path) + public virtual bool Identify(string path) { FileStream fstream = new FileStream(path, FileMode.Open, FileAccess.Read); if(fstream.Length < 128) return false; @@ -190,12 +187,12 @@ namespace DiscImageChef.Filters (header.dataLength > 0 || header.resourceLength > 0); } - public override bool IsOpened() + public virtual bool IsOpened() { return opened; } - public override void Open(byte[] buffer) + public virtual void Open(byte[] buffer) { MemoryStream ms = new MemoryStream(buffer); ms.Seek(0, SeekOrigin.Begin); @@ -222,7 +219,7 @@ namespace DiscImageChef.Filters bytes = buffer; } - public override void Open(Stream stream) + public virtual void Open(Stream stream) { stream.Seek(0, SeekOrigin.Begin); @@ -248,7 +245,7 @@ namespace DiscImageChef.Filters this.stream = stream; } - public override void Open(string path) + public virtual void Open(string path) { FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read); fs.Seek(0, SeekOrigin.Begin); diff --git a/DiscImageChef.Filters/PCExchange.cs b/DiscImageChef.Filters/PCExchange.cs index 50918e7c..86587ee1 100644 --- a/DiscImageChef.Filters/PCExchange.cs +++ b/DiscImageChef.Filters/PCExchange.cs @@ -42,7 +42,7 @@ namespace DiscImageChef.Filters /// /// Decodes PCExchange files /// - public class PCExchange : Filter + public class PCExchange : IFilter { const string FILE_ID = "FILEID.DAT"; const string FINDER_INFO = "FINDER.DAT"; @@ -57,89 +57,86 @@ namespace DiscImageChef.Filters long rsrcLen; string rsrcPath; - public PCExchange() - { - Name = "PCExchange"; - UUID = new Guid("9264EB9F-D634-4F9B-BE12-C24CD44988C6"); - } + public virtual string Name => "PCExchange"; + public virtual Guid Id => new Guid("9264EB9F-D634-4F9B-BE12-C24CD44988C6"); - public override void Close() + public virtual void Close() { opened = false; } - public override string GetBasePath() + public virtual string GetBasePath() { return basePath; } - public override DateTime GetCreationTime() + public virtual DateTime GetCreationTime() { return creationTime; } - public override long GetDataForkLength() + public virtual long GetDataForkLength() { return dataLen; } - public override Stream GetDataForkStream() + public virtual Stream GetDataForkStream() { return new FileStream(dataPath, FileMode.Open, FileAccess.Read); } - public override string GetFilename() + public virtual string GetFilename() { return Path.GetFileName(basePath); } - public override DateTime GetLastWriteTime() + public virtual DateTime GetLastWriteTime() { return lastWriteTime; } - public override long GetLength() + public virtual long GetLength() { return dataLen + rsrcLen; } - public override string GetParentFolder() + public virtual string GetParentFolder() { return Path.GetDirectoryName(basePath); } - public override string GetPath() + public virtual string GetPath() { return basePath; } - public override long GetResourceForkLength() + public virtual long GetResourceForkLength() { return rsrcLen; } - public override Stream GetResourceForkStream() + public virtual Stream GetResourceForkStream() { return new FileStream(rsrcPath, FileMode.Open, FileAccess.Read); } - public override bool HasResourceFork() + public virtual bool HasResourceFork() { return rsrcPath != null; } - public override bool Identify(byte[] buffer) + public virtual bool Identify(byte[] buffer) { return false; } - public override bool Identify(Stream stream) + public virtual bool Identify(Stream stream) { System.Console.WriteLine("parentFolder"); return false; } - public override bool Identify(string path) + public virtual bool Identify(string path) { string parentFolder = Path.GetDirectoryName(path); @@ -190,22 +187,22 @@ namespace DiscImageChef.Filters return dataFound && rsrcFound; } - public override bool IsOpened() + public virtual bool IsOpened() { return opened; } - public override void Open(byte[] buffer) + public virtual void Open(byte[] buffer) { throw new NotSupportedException(); } - public override void Open(Stream stream) + public virtual void Open(Stream stream) { throw new NotSupportedException(); } - public override void Open(string path) + public virtual void Open(string path) { string parentFolder = Path.GetDirectoryName(path); string baseFilename = Path.GetFileName(path); diff --git a/DiscImageChef.Filters/XZ.cs b/DiscImageChef.Filters/XZ.cs index 5f62e30b..1ca5b70f 100644 --- a/DiscImageChef.Filters/XZ.cs +++ b/DiscImageChef.Filters/XZ.cs @@ -39,7 +39,7 @@ namespace DiscImageChef.Filters /// /// Decompress xz files while reading /// - public class XZ : Filter + public class XZ : IFilter { string basePath; DateTime creationTime; @@ -49,13 +49,10 @@ namespace DiscImageChef.Filters DateTime lastWriteTime; bool opened; - public XZ() - { - Name = "XZ"; - UUID = new Guid("666A8617-0444-4C05-9F4F-DF0FD758D0D2"); - } + public virtual string Name => "XZ"; + public virtual Guid Id => new Guid("666A8617-0444-4C05-9F4F-DF0FD758D0D2"); - public override void Close() + public virtual void Close() { dataStream?.Close(); dataStream = null; @@ -63,39 +60,39 @@ namespace DiscImageChef.Filters opened = false; } - public override string GetBasePath() + public virtual string GetBasePath() { return basePath; } - public override Stream GetDataForkStream() + public virtual Stream GetDataForkStream() { return innerStream; } - public override string GetPath() + public virtual string GetPath() { return basePath; } - public override Stream GetResourceForkStream() + public virtual Stream GetResourceForkStream() { return null; } - public override bool HasResourceFork() + public virtual bool HasResourceFork() { return false; } - public override bool Identify(byte[] buffer) + public virtual bool Identify(byte[] buffer) { return buffer[0] == 0xFD && buffer[1] == 0x37 && buffer[2] == 0x7A && buffer[3] == 0x58 && buffer[4] == 0x5A && buffer[5] == 0x00 && buffer[buffer.Length - 2] == 0x59 && buffer[buffer.Length - 1] == 0x5A; } - public override bool Identify(Stream stream) + public virtual bool Identify(Stream stream) { byte[] buffer = new byte[6]; byte[] footer = new byte[2]; @@ -110,7 +107,7 @@ namespace DiscImageChef.Filters buffer[4] == 0x5A && buffer[5] == 0x00 && footer[0] == 0x59 && footer[1] == 0x5A; } - public override bool Identify(string path) + public virtual bool Identify(string path) { if(!File.Exists(path)) return false; @@ -175,7 +172,7 @@ namespace DiscImageChef.Filters return i; } - public override void Open(byte[] buffer) + public virtual void Open(byte[] buffer) { dataStream = new MemoryStream(buffer); basePath = null; @@ -186,7 +183,7 @@ namespace DiscImageChef.Filters opened = true; } - public override void Open(Stream stream) + public virtual void Open(Stream stream) { dataStream = stream; basePath = null; @@ -197,7 +194,7 @@ namespace DiscImageChef.Filters opened = true; } - public override void Open(string path) + public virtual void Open(string path) { dataStream = new FileStream(path, FileMode.Open, FileAccess.Read); basePath = Path.GetFullPath(path); @@ -213,32 +210,32 @@ namespace DiscImageChef.Filters opened = true; } - public override DateTime GetCreationTime() + public virtual DateTime GetCreationTime() { return creationTime; } - public override long GetDataForkLength() + public virtual long GetDataForkLength() { return decompressedSize; } - public override DateTime GetLastWriteTime() + public virtual DateTime GetLastWriteTime() { return lastWriteTime; } - public override long GetLength() + public virtual long GetLength() { return decompressedSize; } - public override long GetResourceForkLength() + public virtual long GetResourceForkLength() { return 0; } - public override string GetFilename() + public virtual string GetFilename() { if(basePath?.EndsWith(".xz", StringComparison.InvariantCultureIgnoreCase) == true) return basePath.Substring(0, basePath.Length - 3); @@ -248,12 +245,12 @@ namespace DiscImageChef.Filters : basePath; } - public override string GetParentFolder() + public virtual string GetParentFolder() { return Path.GetDirectoryName(basePath); } - public override bool IsOpened() + public virtual bool IsOpened() { return opened; } diff --git a/DiscImageChef.Filters/ZZZNoFilter.cs b/DiscImageChef.Filters/ZZZNoFilter.cs index e9966787..6cd05e98 100644 --- a/DiscImageChef.Filters/ZZZNoFilter.cs +++ b/DiscImageChef.Filters/ZZZNoFilter.cs @@ -38,7 +38,7 @@ namespace DiscImageChef.Filters /// /// No filter for reading files not recognized by any filter /// - public class ZZZNoFilter : Filter + public class ZZZNoFilter : IFilter { string basePath; DateTime creationTime; @@ -46,13 +46,10 @@ namespace DiscImageChef.Filters DateTime lastWriteTime; bool opened; - public ZZZNoFilter() - { - Name = "No filter"; - UUID = new Guid("12345678-AAAA-BBBB-CCCC-123456789000"); - } + public virtual string Name => "No filter"; + public virtual Guid Id => new Guid("12345678-AAAA-BBBB-CCCC-123456789000"); - public override void Close() + public virtual void Close() { dataStream?.Close(); dataStream = null; @@ -60,48 +57,48 @@ namespace DiscImageChef.Filters opened = false; } - public override string GetBasePath() + public virtual string GetBasePath() { return basePath; } - public override Stream GetDataForkStream() + public virtual Stream GetDataForkStream() { return dataStream; } - public override string GetPath() + public virtual string GetPath() { return basePath; } - public override Stream GetResourceForkStream() + public virtual Stream GetResourceForkStream() { return null; } - public override bool HasResourceFork() + public virtual bool HasResourceFork() { // TODO: Implement support for xattrs/ADS return false; } - public override bool Identify(byte[] buffer) + public virtual bool Identify(byte[] buffer) { return buffer != null && buffer.Length > 0; } - public override bool Identify(Stream stream) + public virtual bool Identify(Stream stream) { return stream != null && stream.Length > 0; } - public override bool Identify(string path) + public virtual bool Identify(string path) { return File.Exists(path); } - public override void Open(byte[] buffer) + public virtual void Open(byte[] buffer) { dataStream = new MemoryStream(buffer); basePath = null; @@ -110,7 +107,7 @@ namespace DiscImageChef.Filters opened = true; } - public override void Open(Stream stream) + public virtual void Open(Stream stream) { dataStream = stream; basePath = null; @@ -119,7 +116,7 @@ namespace DiscImageChef.Filters opened = true; } - public override void Open(string path) + public virtual void Open(string path) { dataStream = new FileStream(path, FileMode.Open, FileAccess.Read); basePath = Path.GetFullPath(path); @@ -129,42 +126,42 @@ namespace DiscImageChef.Filters opened = true; } - public override DateTime GetCreationTime() + public virtual DateTime GetCreationTime() { return creationTime; } - public override long GetDataForkLength() + public virtual long GetDataForkLength() { return dataStream.Length; } - public override DateTime GetLastWriteTime() + public virtual DateTime GetLastWriteTime() { return lastWriteTime; } - public override long GetLength() + public virtual long GetLength() { return dataStream.Length; } - public override long GetResourceForkLength() + public virtual long GetResourceForkLength() { return 0; } - public override string GetFilename() + public virtual string GetFilename() { return Path.GetFileName(basePath); } - public override string GetParentFolder() + public virtual string GetParentFolder() { return Path.GetDirectoryName(basePath); } - public override bool IsOpened() + public virtual bool IsOpened() { return opened; } diff --git a/DiscImageChef.Partitions/Acorn.cs b/DiscImageChef.Partitions/Acorn.cs index 26ef9b6a..ff730914 100644 --- a/DiscImageChef.Partitions/Acorn.cs +++ b/DiscImageChef.Partitions/Acorn.cs @@ -39,7 +39,7 @@ using DiscImageChef.DiscImages; namespace DiscImageChef.Partitions { - public class Acorn : PartitionPlugin + public class Acorn : IPartition { const ulong ADFS_SB_POS = 0xC00; const uint LINUX_MAGIC = 0xDEAFA1DE; @@ -50,13 +50,10 @@ namespace DiscImageChef.Partitions const uint TYPE_RISCIX_SCSI = 2; const uint TYPE_MASK = 15; - public Acorn() - { - Name = "Acorn FileCore partitions"; - PluginUuid = new Guid("A7C8FEBE-8D00-4933-B9F3-42184C8BA808"); - } + public virtual string Name => "Acorn FileCore partitions"; + public virtual Guid Id => new Guid("A7C8FEBE-8D00-4933-B9F3-42184C8BA808"); - public override bool GetInformation(ImagePlugin imagePlugin, out List partitions, ulong sectorOffset) + public virtual bool GetInformation(IMediaImage imagePlugin, out List partitions, ulong sectorOffset) { partitions = new List(); @@ -65,8 +62,8 @@ namespace DiscImageChef.Partitions // RISC OS always checks for the partition on 0. Afaik no emulator chains it. if(sectorOffset != 0) return false; - if(imagePlugin.ImageInfo.SectorSize > ADFS_SB_POS) sbSector = 0; - else sbSector = ADFS_SB_POS / imagePlugin.ImageInfo.SectorSize; + if(imagePlugin.Info.SectorSize > ADFS_SB_POS) sbSector = 0; + else sbSector = ADFS_SB_POS / imagePlugin.Info.SectorSize; byte[] sector = imagePlugin.ReadSector(sbSector); @@ -84,7 +81,7 @@ namespace DiscImageChef.Partitions int secCyl = bootBlock.discRecord.spt * heads; int mapSector = bootBlock.startCylinder * secCyl; - if((ulong)mapSector >= imagePlugin.ImageInfo.Sectors) return false; + if((ulong)mapSector >= imagePlugin.Info.Sectors) return false; byte[] map = imagePlugin.ReadSector((ulong)mapSector); @@ -97,7 +94,7 @@ namespace DiscImageChef.Partitions Size = (ulong)bootBlock.discRecord.disc_size_high * 0x100000000 + bootBlock.discRecord.disc_size, Length = ((ulong)bootBlock.discRecord.disc_size_high * 0x100000000 + bootBlock.discRecord.disc_size) / - imagePlugin.ImageInfo.SectorSize, + imagePlugin.Info.SectorSize, Type = "ADFS", Name = StringHandlers.CToString(bootBlock.discRecord.disc_name, Encoding.GetEncoding("iso-8859-1")) }; diff --git a/DiscImageChef.Partitions/AppleMap.cs b/DiscImageChef.Partitions/AppleMap.cs index d61869f4..99dbed49 100644 --- a/DiscImageChef.Partitions/AppleMap.cs +++ b/DiscImageChef.Partitions/AppleMap.cs @@ -42,7 +42,7 @@ namespace DiscImageChef.Partitions { // Information about structures learnt from Inside Macintosh // Constants from image testing - public class AppleMap : PartitionPlugin + public class AppleMap : IPartition { /// "ER", driver descriptor magic const ushort DDM_MAGIC = 0x4552; @@ -53,22 +53,19 @@ namespace DiscImageChef.Partitions /// Old indicator for HFS partition, "TFS1" const uint HFS_MAGIC_OLD = 0x54465331; - public AppleMap() - { - Name = "Apple Partition Map"; - PluginUuid = new Guid("36405F8D-4F1A-07F5-209C-223D735D6D22"); - } + public virtual string Name => "Apple Partition Map"; + public virtual Guid Id => new Guid("36405F8D-4F1A-07F5-209C-223D735D6D22"); - public override bool GetInformation(ImagePlugin imagePlugin, out List partitions, ulong sectorOffset) + public virtual bool GetInformation(IMediaImage imagePlugin, out List partitions, ulong sectorOffset) { uint sectorSize; - if(imagePlugin.ImageInfo.SectorSize == 2352 || imagePlugin.ImageInfo.SectorSize == 2448) sectorSize = 2048; - else sectorSize = imagePlugin.ImageInfo.SectorSize; + if(imagePlugin.Info.SectorSize == 2352 || imagePlugin.Info.SectorSize == 2448) sectorSize = 2048; + else sectorSize = imagePlugin.Info.SectorSize; partitions = new List(); - if(sectorOffset + 2 >= imagePlugin.ImageInfo.Sectors) return false; + if(sectorOffset + 2 >= imagePlugin.Info.Sectors) return false; byte[] ddmSector = imagePlugin.ReadSector(sectorOffset); @@ -313,24 +310,24 @@ namespace DiscImageChef.Partitions } _partition.Description = sb.ToString(); - if(_partition.Start < imagePlugin.ImageInfo.Sectors && _partition.End < imagePlugin.ImageInfo.Sectors) + if(_partition.Start < imagePlugin.Info.Sectors && _partition.End < imagePlugin.Info.Sectors) { partitions.Add(_partition); sequence++; } // Some CD and DVDs end with an Apple_Free that expands beyond the disc size... - else if(_partition.Start < imagePlugin.ImageInfo.Sectors) + else if(_partition.Start < imagePlugin.Info.Sectors) { DicConsole.DebugWriteLine("AppleMap Plugin", "Cutting last partition end ({0}) to media size ({1})", - _partition.End, imagePlugin.ImageInfo.Sectors - 1); - _partition.Length = imagePlugin.ImageInfo.Sectors - _partition.Start; + _partition.End, imagePlugin.Info.Sectors - 1); + _partition.Length = imagePlugin.Info.Sectors - _partition.Start; partitions.Add(_partition); sequence++; } else DicConsole.DebugWriteLine("AppleMap Plugin", "Not adding partition becaus start ({0}) is outside media size ({1})", - _partition.Start, imagePlugin.ImageInfo.Sectors - 1); + _partition.Start, imagePlugin.Info.Sectors - 1); } return partitions.Count > 0; diff --git a/DiscImageChef.Partitions/Apricot.cs b/DiscImageChef.Partitions/Apricot.cs index 49cb08b9..5840218d 100644 --- a/DiscImageChef.Partitions/Apricot.cs +++ b/DiscImageChef.Partitions/Apricot.cs @@ -39,7 +39,7 @@ using DiscImageChef.DiscImages; namespace DiscImageChef.Partitions { - public class Apricot : PartitionPlugin + public class Apricot : IPartition { readonly int[] baudRates = {50, 75, 110, 134, 150, 300, 600, 1200, 1800, 2400, 3600, 4800, 7200, 9600, 19200}; readonly string[] bootTypeCodes = @@ -56,13 +56,10 @@ namespace DiscImageChef.Partitions readonly string[] printDevices = {"Parallel", "Serial"}; readonly double[] stopBits = {1, 1.5, 2}; - public Apricot() - { - Name = "ACT Apricot partitions"; - PluginUuid = new Guid("8CBF5864-7B5A-47A0-8CEB-199C74FA22DE"); - } + public virtual string Name => "ACT Apricot partitions"; + public virtual Guid Id => new Guid("8CBF5864-7B5A-47A0-8CEB-199C74FA22DE"); - public override bool GetInformation(ImagePlugin imagePlugin, out List partitions, ulong sectorOffset) + public virtual bool GetInformation(IMediaImage imagePlugin, out List partitions, ulong sectorOffset) { partitions = new List(); @@ -79,7 +76,7 @@ namespace DiscImageChef.Partitions Marshal.FreeHGlobal(lblPtr); // Not much to check but... - ulong deviceSectors = imagePlugin.ImageInfo.Sectors; + ulong deviceSectors = imagePlugin.Info.Sectors; ulong deviceSizeAccordingToLabel = label.cylinders * label.heads * label.spt; if(label.operatingSystem > 4 || label.bootType > 5 || label.partitionCount > 8 || deviceSizeAccordingToLabel > deviceSectors || label.firstDataBlock > deviceSectors) return false; diff --git a/DiscImageChef.Partitions/Atari.cs b/DiscImageChef.Partitions/Atari.cs index 1298281b..acdb1a69 100644 --- a/DiscImageChef.Partitions/Atari.cs +++ b/DiscImageChef.Partitions/Atari.cs @@ -40,7 +40,7 @@ using DiscImageChef.DiscImages; namespace DiscImageChef.Partitions { - public class AtariPartitions : PartitionPlugin + public class AtariPartitions : IPartition { const uint TypeGEMDOS = 0x0047454D; const uint TypeBigGEMDOS = 0x0042474D; @@ -55,17 +55,14 @@ namespace DiscImageChef.Partitions const uint TypeMinix = 0x004D4958; const uint TypeMinix2 = 0x004D4E58; - public AtariPartitions() - { - Name = "Atari partitions"; - PluginUuid = new Guid("d1dd0f24-ec39-4c4d-9072-be31919a3b5e"); - } + public virtual string Name => "Atari partitions"; + public virtual Guid Id => new Guid("d1dd0f24-ec39-4c4d-9072-be31919a3b5e"); - public override bool GetInformation(ImagePlugin imagePlugin, out List partitions, ulong sectorOffset) + public virtual bool GetInformation(IMediaImage imagePlugin, out List partitions, ulong sectorOffset) { partitions = new List(); - if(imagePlugin.ImageInfo.SectorSize < 512) return false; + if(imagePlugin.Info.SectorSize < 512) return false; BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; @@ -159,13 +156,13 @@ namespace DiscImageChef.Partitions case TypeMinix2: validTable = true; - if(table.entries[i].start <= imagePlugin.ImageInfo.Sectors) + if(table.entries[i].start <= imagePlugin.Info.Sectors) { - if(table.entries[i].start + table.entries[i].length > imagePlugin.ImageInfo.Sectors) + if(table.entries[i].start + table.entries[i].length > imagePlugin.Info.Sectors) DicConsole.DebugWriteLine("Atari partition plugin", "WARNING: End of partition goes beyond device size"); - ulong sectorSize = imagePlugin.ImageInfo.SectorSize; + ulong sectorSize = imagePlugin.Info.SectorSize; if(sectorSize == 2448 || sectorSize == 2352) sectorSize = 2048; byte[] partType = new byte[3]; @@ -253,14 +250,14 @@ namespace DiscImageChef.Partitions extendedType != TypeMinix2) continue; validTable = true; - if(extendedTable.entries[j].start > imagePlugin.ImageInfo.Sectors) continue; + if(extendedTable.entries[j].start > imagePlugin.Info.Sectors) continue; if(extendedTable.entries[j].start + extendedTable.entries[j].length > - imagePlugin.ImageInfo.Sectors) + imagePlugin.Info.Sectors) DicConsole.DebugWriteLine("Atari partition plugin", "WARNING: End of partition goes beyond device size"); - ulong sectorSize = imagePlugin.ImageInfo.SectorSize; + ulong sectorSize = imagePlugin.Info.SectorSize; if(sectorSize == 2448 || sectorSize == 2352) sectorSize = 2048; byte[] partType = new byte[3]; @@ -335,13 +332,13 @@ namespace DiscImageChef.Partitions type != TypeRAW && type != TypeNetBSD && type != TypeNetBSDSwap && type != TypeSysV && type != TypeMac && type != TypeMinix && type != TypeMinix2) continue; - if(table.icdEntries[i].start > imagePlugin.ImageInfo.Sectors) continue; + if(table.icdEntries[i].start > imagePlugin.Info.Sectors) continue; - if(table.icdEntries[i].start + table.icdEntries[i].length > imagePlugin.ImageInfo.Sectors) + if(table.icdEntries[i].start + table.icdEntries[i].length > imagePlugin.Info.Sectors) DicConsole.DebugWriteLine("Atari partition plugin", "WARNING: End of partition goes beyond device size"); - ulong sectorSize = imagePlugin.ImageInfo.SectorSize; + ulong sectorSize = imagePlugin.Info.SectorSize; if(sectorSize == 2448 || sectorSize == 2352) sectorSize = 2048; byte[] partType = new byte[3]; diff --git a/DiscImageChef.Partitions/BSD.cs b/DiscImageChef.Partitions/BSD.cs index f160853e..fda4cdba 100644 --- a/DiscImageChef.Partitions/BSD.cs +++ b/DiscImageChef.Partitions/BSD.cs @@ -40,7 +40,7 @@ using DiscImageChef.DiscImages; namespace DiscImageChef.Partitions { - public class BSD : PartitionPlugin + public class BSD : IPartition { const uint DISKMAGIC = 0x82564557; const uint DISKCIGAM = 0x57455682; @@ -51,24 +51,21 @@ namespace DiscImageChef.Partitions /// Known byte offsets for BSD disklabel readonly uint[] labelOffsets = {0, 9, 64, 128, 516}; - public BSD() - { - Name = "BSD disklabel"; - PluginUuid = new Guid("246A6D93-4F1A-1F8A-344D-50187A5513A9"); - } + public virtual string Name => "BSD disklabel"; + public virtual Guid Id => new Guid("246A6D93-4F1A-1F8A-344D-50187A5513A9"); - public override bool GetInformation(ImagePlugin imagePlugin, out List partitions, ulong sectorOffset) + public virtual bool GetInformation(IMediaImage imagePlugin, out List partitions, ulong sectorOffset) { partitions = new List(); - uint run = (MAX_LABEL_SIZE + labelOffsets.Last()) / imagePlugin.ImageInfo.SectorSize; - if((MAX_LABEL_SIZE + labelOffsets.Last()) % imagePlugin.ImageInfo.SectorSize > 0) run++; + uint run = (MAX_LABEL_SIZE + labelOffsets.Last()) / imagePlugin.Info.SectorSize; + if((MAX_LABEL_SIZE + labelOffsets.Last()) % imagePlugin.Info.SectorSize > 0) run++; DiskLabel dl = new DiskLabel(); bool found = false; foreach(ulong location in labelLocations) { - if(location + run + sectorOffset >= imagePlugin.ImageInfo.Sectors) return false; + if(location + run + sectorOffset >= imagePlugin.Info.Sectors) return false; byte[] tmp = imagePlugin.ReadSectors(location + sectorOffset, run); foreach(uint offset in labelOffsets) @@ -141,9 +138,9 @@ namespace DiscImageChef.Partitions dl.d_partitions[i].p_fstype, fsTypeToString(dl.d_partitions[i].p_fstype)); Partition part = new Partition { - Start = dl.d_partitions[i].p_offset * dl.d_secsize / imagePlugin.ImageInfo.SectorSize, + Start = dl.d_partitions[i].p_offset * dl.d_secsize / imagePlugin.Info.SectorSize, Offset = dl.d_partitions[i].p_offset * dl.d_secsize, - Length = dl.d_partitions[i].p_size * dl.d_secsize / imagePlugin.ImageInfo.SectorSize, + Length = dl.d_partitions[i].p_size * dl.d_secsize / imagePlugin.Info.SectorSize, Size = dl.d_partitions[i].p_size * dl.d_secsize, Type = fsTypeToString(dl.d_partitions[i].p_fstype), Sequence = counter, @@ -156,7 +153,7 @@ namespace DiscImageChef.Partitions if(addSectorOffset) { part.Start += sectorOffset; - part.Offset += sectorOffset * imagePlugin.ImageInfo.SectorSize; + part.Offset += sectorOffset * imagePlugin.Info.SectorSize; } DicConsole.DebugWriteLine("BSD plugin", "part.start = {0}", part.Start); DicConsole.DebugWriteLine("BSD plugin", "Adding it..."); diff --git a/DiscImageChef.Partitions/DEC.cs b/DiscImageChef.Partitions/DEC.cs index c1f896c7..9c0c7f4e 100644 --- a/DiscImageChef.Partitions/DEC.cs +++ b/DiscImageChef.Partitions/DEC.cs @@ -39,22 +39,19 @@ using DiscImageChef.DiscImages; namespace DiscImageChef.Partitions { - public class DEC : PartitionPlugin + public class DEC : IPartition { const int PT_MAGIC = 0x032957; const int PT_VALID = 1; - public DEC() - { - Name = "DEC disklabel"; - PluginUuid = new Guid("58CEC3B7-3B93-4D47-86EE-D6DADE9D444F"); - } + public virtual string Name => "DEC disklabel"; + public virtual Guid Id => new Guid("58CEC3B7-3B93-4D47-86EE-D6DADE9D444F"); - public override bool GetInformation(ImagePlugin imagePlugin, out List partitions, ulong sectorOffset) + public virtual bool GetInformation(IMediaImage imagePlugin, out List partitions, ulong sectorOffset) { partitions = new List(); - if(31 + sectorOffset >= imagePlugin.ImageInfo.Sectors) return false; + if(31 + sectorOffset >= imagePlugin.Info.Sectors) return false; byte[] sector = imagePlugin.ReadSector(31 + sectorOffset); if(sector.Length < 512) return false; diff --git a/DiscImageChef.Partitions/DiscImageChef.Partitions.csproj b/DiscImageChef.Partitions/DiscImageChef.Partitions.csproj index e8a04215..378ef229 100644 --- a/DiscImageChef.Partitions/DiscImageChef.Partitions.csproj +++ b/DiscImageChef.Partitions/DiscImageChef.Partitions.csproj @@ -39,7 +39,7 @@ - + diff --git a/DiscImageChef.Partitions/DragonFlyBSD.cs b/DiscImageChef.Partitions/DragonFlyBSD.cs index 2ce96dc2..dc606933 100644 --- a/DiscImageChef.Partitions/DragonFlyBSD.cs +++ b/DiscImageChef.Partitions/DragonFlyBSD.cs @@ -38,23 +38,20 @@ using DiscImageChef.DiscImages; namespace DiscImageChef.Partitions { - public class DragonFlyBSD : PartitionPlugin + public class DragonFlyBSD : IPartition { const uint DISK_MAGIC64 = 0xC4464C59; - public DragonFlyBSD() - { - Name = "DragonFly BSD 64-bit disklabel"; - PluginUuid = new Guid("D49E41A6-D952-4760-9D94-03DAE2450C5F"); - } + public virtual string Name => "DragonFly BSD 64-bit disklabel"; + public virtual Guid Id => new Guid("D49E41A6-D952-4760-9D94-03DAE2450C5F"); - public override bool GetInformation(ImagePlugin imagePlugin, out List partitions, ulong sectorOffset) + public virtual bool GetInformation(IMediaImage imagePlugin, out List partitions, ulong sectorOffset) { partitions = new List(); - uint nSectors = 2048 / imagePlugin.ImageInfo.SectorSize; - if(2048 % imagePlugin.ImageInfo.SectorSize > 0) nSectors++; + uint nSectors = 2048 / imagePlugin.Info.SectorSize; + if(2048 % imagePlugin.Info.SectorSize > 0) nSectors++; - if(sectorOffset + nSectors >= imagePlugin.ImageInfo.Sectors) return false; + if(sectorOffset + nSectors >= imagePlugin.Info.Sectors) return false; byte[] sectors = imagePlugin.ReadSectors(sectorOffset, nSectors); if(sectors.Length < 2048) return false; @@ -72,10 +69,10 @@ namespace DiscImageChef.Partitions { Partition part = new Partition { - Start = entry.p_boffset / imagePlugin.ImageInfo.SectorSize + sectorOffset, - Offset = entry.p_boffset + sectorOffset * imagePlugin.ImageInfo.SectorSize, + Start = entry.p_boffset / imagePlugin.Info.SectorSize + sectorOffset, + Offset = entry.p_boffset + sectorOffset * imagePlugin.Info.SectorSize, Size = entry.p_bsize, - Length = entry.p_bsize / imagePlugin.ImageInfo.SectorSize, + Length = entry.p_bsize / imagePlugin.Info.SectorSize, Name = entry.p_stor_uuid.ToString(), Sequence = counter, Scheme = Name, @@ -84,7 +81,7 @@ namespace DiscImageChef.Partitions : BSD.fsTypeToString((BSD.fsType)entry.p_fstype) }; - if(entry.p_bsize % imagePlugin.ImageInfo.SectorSize > 0) part.Length++; + if(entry.p_bsize % imagePlugin.Info.SectorSize > 0) part.Length++; if(entry.p_bsize <= 0 || entry.p_boffset <= 0) continue; diff --git a/DiscImageChef.Partitions/GPT.cs b/DiscImageChef.Partitions/GPT.cs index 91edab1f..ba714be9 100644 --- a/DiscImageChef.Partitions/GPT.cs +++ b/DiscImageChef.Partitions/GPT.cs @@ -40,22 +40,19 @@ using DiscImageChef.DiscImages; namespace DiscImageChef.Partitions { - public class GuidPartitionTable : PartitionPlugin + public class GuidPartitionTable : IPartition { const ulong GPT_MAGIC = 0x5452415020494645; const uint GPT_REVISION1 = 0x00010000; - public GuidPartitionTable() - { - Name = "GUID Partition Table"; - PluginUuid = new Guid("CBC9D281-C1D0-44E8-9038-4D66FD2678AB"); - } + public virtual string Name => "GUID Partition Table"; + public virtual Guid Id => new Guid("CBC9D281-C1D0-44E8-9038-4D66FD2678AB"); - public override bool GetInformation(ImagePlugin imagePlugin, out List partitions, ulong sectorOffset) + public virtual bool GetInformation(IMediaImage imagePlugin, out List partitions, ulong sectorOffset) { partitions = new List(); - if(sectorOffset + 2 >= imagePlugin.ImageInfo.Sectors) return false; + if(sectorOffset + 2 >= imagePlugin.Info.Sectors) return false; byte[] hdrBytes = imagePlugin.ReadSector(1 + sectorOffset); GptHeader hdr; @@ -66,7 +63,7 @@ namespace DiscImageChef.Partitions DicConsole.DebugWriteLine("GPT Plugin", "hdr.signature = 0x{0:X16}", signature); if(signature != GPT_MAGIC) - if(imagePlugin.ImageInfo.XmlMediaType == XmlMediaType.OpticalDisc) + if(imagePlugin.Info.XmlMediaType == XmlMediaType.OpticalDisc) { hdrBytes = imagePlugin.ReadSector(sectorOffset); signature = BitConverter.ToUInt64(hdrBytes, 512); @@ -121,11 +118,11 @@ namespace DiscImageChef.Partitions { divisor = 1; modulo = 0; - sectorSize = imagePlugin.ImageInfo.SectorSize; + sectorSize = imagePlugin.Info.SectorSize; } - uint totalEntriesSectors = hdr.entries * hdr.entriesSize / imagePlugin.ImageInfo.SectorSize; - if(hdr.entries * hdr.entriesSize % imagePlugin.ImageInfo.SectorSize > 0) totalEntriesSectors++; + uint totalEntriesSectors = hdr.entries * hdr.entriesSize / imagePlugin.Info.SectorSize; + if(hdr.entries * hdr.entriesSize % imagePlugin.Info.SectorSize > 0) totalEntriesSectors++; byte[] temp = imagePlugin.ReadSectors(hdr.entryLBA / divisor, totalEntriesSectors + modulo); byte[] entriesBytes = new byte[temp.Length - modulo * 512]; @@ -165,8 +162,8 @@ namespace DiscImageChef.Partitions DicConsole.DebugWriteLine("GPT Plugin", "entry.attributes = 0x{0:X16}", entry.attributes); DicConsole.DebugWriteLine("GPT Plugin", "entry.name = {0}", entry.name); - if(entry.startLBA / divisor > imagePlugin.ImageInfo.Sectors || - entry.endLBA / divisor > imagePlugin.ImageInfo.Sectors) return false; + if(entry.startLBA / divisor > imagePlugin.Info.Sectors || + entry.endLBA / divisor > imagePlugin.Info.Sectors) return false; Partition part = new Partition { diff --git a/DiscImageChef.Partitions/Human68k.cs b/DiscImageChef.Partitions/Human68k.cs index 839d6660..90d0058c 100644 --- a/DiscImageChef.Partitions/Human68k.cs +++ b/DiscImageChef.Partitions/Human68k.cs @@ -40,28 +40,25 @@ using DiscImageChef.DiscImages; namespace DiscImageChef.Partitions { - public class Human68K : PartitionPlugin + public class Human68K : IPartition { const uint X68K_MAGIC = 0x5836384B; - public Human68K() - { - Name = "Human 68k partitions"; - PluginUuid = new Guid("246A6D93-4F1A-1F8A-344D-50187A5513A9"); - } + public virtual string Name => "Human 68k partitions"; + public virtual Guid Id => new Guid("246A6D93-4F1A-1F8A-344D-50187A5513A9"); - public override bool GetInformation(ImagePlugin imagePlugin, out List partitions, ulong sectorOffset) + public virtual bool GetInformation(IMediaImage imagePlugin, out List partitions, ulong sectorOffset) { partitions = new List(); byte[] sector; ulong sectsPerUnit; - DicConsole.DebugWriteLine("Human68k plugin", "sectorSize = {0}", imagePlugin.ImageInfo.SectorSize); + DicConsole.DebugWriteLine("Human68k plugin", "sectorSize = {0}", imagePlugin.Info.SectorSize); - if(sectorOffset + 4 >= imagePlugin.ImageInfo.Sectors) return false; + if(sectorOffset + 4 >= imagePlugin.Info.Sectors) return false; - switch(imagePlugin.ImageInfo.SectorSize) + switch(imagePlugin.Info.SectorSize) { case 256: sector = imagePlugin.ReadSector(4 + sectorOffset); @@ -100,7 +97,7 @@ namespace DiscImageChef.Partitions DicConsole.DebugWriteLine("Human68k plugin", "entry.stateStart = {0}", entry.stateStart); DicConsole.DebugWriteLine("Human68k plugin", "entry.length = {0}", entry.length); DicConsole.DebugWriteLine("Human68k plugin", "sectsPerUnit = {0} {1}", sectsPerUnit, - imagePlugin.ImageInfo.SectorSize); + imagePlugin.Info.SectorSize); Partition part = new Partition { diff --git a/DiscImageChef.Partitions/PartitionPlugin.cs b/DiscImageChef.Partitions/IPartition.cs similarity index 88% rename from DiscImageChef.Partitions/PartitionPlugin.cs rename to DiscImageChef.Partitions/IPartition.cs index 295eac4c..52c9639d 100644 --- a/DiscImageChef.Partitions/PartitionPlugin.cs +++ b/DiscImageChef.Partitions/IPartition.cs @@ -2,7 +2,7 @@ // The Disc Image Chef // ---------------------------------------------------------------------------- // -// Filename : PartitionPlugin.cs +// Filename : IPartition.cs // Author(s) : Natalia Portillo // // Component : Partitioning scheme plugins. @@ -41,12 +41,12 @@ namespace DiscImageChef.Partitions /// /// Abstract class to implement partitioning schemes interpreting plugins. /// - public abstract class PartitionPlugin + public interface IPartition { /// Plugin name. - public string Name; + string Name { get; } /// Plugin UUID. - public Guid PluginUuid; + Guid Id { get; } /// /// Interprets a partitioning scheme. @@ -55,7 +55,6 @@ namespace DiscImageChef.Partitions /// Disk image. /// Returns list of partitions. /// At which sector to start searching for the partition scheme. - public abstract bool GetInformation(ImagePlugin imagePlugin, out List partitions, - ulong sectorOffset); + bool GetInformation(IMediaImage imagePlugin, out List partitions, ulong sectorOffset); } } \ No newline at end of file diff --git a/DiscImageChef.Partitions/MBR.cs b/DiscImageChef.Partitions/MBR.cs index a903a024..341dd184 100644 --- a/DiscImageChef.Partitions/MBR.cs +++ b/DiscImageChef.Partitions/MBR.cs @@ -41,7 +41,7 @@ using DiscImageChef.Helpers; namespace DiscImageChef.Partitions { // TODO: Support AAP extensions - public class MBR : PartitionPlugin + public class MBR : IPartition { const ulong GPT_MAGIC = 0x5452415020494645; @@ -184,25 +184,22 @@ namespace DiscImageChef.Partitions "VMWare VMKCORE", "Linux RAID, FreeDOS", "SpeedStor, LANStep, PS/2 IML", "Xenix bad block" }; - public MBR() - { - Name = "Master Boot Record"; - PluginUuid = new Guid("5E8A34E8-4F1A-59E6-4BF7-7EA647063A76"); - } + public virtual string Name => "Master Boot Record"; + public virtual Guid Id => new Guid("5E8A34E8-4F1A-59E6-4BF7-7EA647063A76"); - public override bool GetInformation(ImagePlugin imagePlugin, out List partitions, ulong sectorOffset) + public virtual bool GetInformation(IMediaImage imagePlugin, out List partitions, ulong sectorOffset) { ulong counter = 0; partitions = new List(); - if(imagePlugin.ImageInfo.SectorSize < 512) return false; + if(imagePlugin.Info.SectorSize < 512) return false; - uint sectorSize = imagePlugin.ImageInfo.SectorSize; + uint sectorSize = imagePlugin.Info.SectorSize; // Divider of sector size in MBR between real sector size ulong divider = 1; - if(imagePlugin.ImageInfo.XmlMediaType == XmlMediaType.OpticalDisc) + if(imagePlugin.Info.XmlMediaType == XmlMediaType.OpticalDisc) { sectorSize = 512; divider = 4; @@ -229,7 +226,7 @@ namespace DiscImageChef.Partitions typeof(DiskManagerMasterBootRecord)); handle.Free(); - DicConsole.DebugWriteLine("MBR plugin", "xmlmedia = {0}", imagePlugin.ImageInfo.XmlMediaType); + DicConsole.DebugWriteLine("MBR plugin", "xmlmedia = {0}", imagePlugin.Info.XmlMediaType); DicConsole.DebugWriteLine("MBR plugin", "mbr.magic = {0:X4}", mbr.magic); if(mbr.magic != MBR_MAGIC) return false; // Not MBR @@ -242,7 +239,7 @@ namespace DiscImageChef.Partitions if(signature == GPT_MAGIC) return false; - if(signature != GPT_MAGIC && imagePlugin.ImageInfo.XmlMediaType == XmlMediaType.OpticalDisc) + if(signature != GPT_MAGIC && imagePlugin.Info.XmlMediaType == XmlMediaType.OpticalDisc) { hdrBytes = imagePlugin.ReadSector(sectorOffset); signature = BitConverter.ToUInt64(hdrBytes, 512); @@ -288,10 +285,10 @@ namespace DiscImageChef.Partitions entry.end_head != 0 || entry.end_sector != 0; if(entry.lba_start == 0 && entry.lba_sectors == 0 && valid) { - lbaStart = CHS.ToLBA(startCylinder, entry.start_head, startSector, imagePlugin.ImageInfo.Heads, - imagePlugin.ImageInfo.SectorsPerTrack); - lbaSectors = CHS.ToLBA(endCylinder, entry.end_head, entry.end_sector, imagePlugin.ImageInfo.Heads, - imagePlugin.ImageInfo.SectorsPerTrack) - lbaStart; + lbaStart = CHS.ToLBA(startCylinder, entry.start_head, startSector, imagePlugin.Info.Heads, + imagePlugin.Info.SectorsPerTrack); + lbaSectors = CHS.ToLBA(endCylinder, entry.end_head, entry.end_sector, imagePlugin.Info.Heads, + imagePlugin.Info.SectorsPerTrack) - lbaStart; } // For optical media @@ -300,15 +297,15 @@ namespace DiscImageChef.Partitions if(minix && lbaStart == sectorOffset) minix = false; - if(lbaStart > imagePlugin.ImageInfo.Sectors) + if(lbaStart > imagePlugin.Info.Sectors) { valid = false; extended = false; } // Some buggy implementations do some rounding errors getting a few sectors beyond device size - if(lbaStart + lbaSectors > imagePlugin.ImageInfo.Sectors) - lbaSectors = imagePlugin.ImageInfo.Sectors - lbaStart; + if(lbaStart + lbaSectors > imagePlugin.Info.Sectors) + lbaSectors = imagePlugin.Info.Sectors - lbaStart; DicConsole.DebugWriteLine("MBR plugin", "entry.status {0}", entry.status); DicConsole.DebugWriteLine("MBR plugin", "entry.type {0}", entry.type); @@ -334,7 +331,7 @@ namespace DiscImageChef.Partitions if(valid && !minix) { Partition part = new Partition(); - if((lbaStart > 0 || imagePlugin.ImageInfo.XmlMediaType == XmlMediaType.OpticalDisc) && + if((lbaStart > 0 || imagePlugin.Info.XmlMediaType == XmlMediaType.OpticalDisc) && lbaSectors > 0) { part.Start = lbaStart + sectorOffset; @@ -413,9 +410,9 @@ namespace DiscImageChef.Partitions if(ebrEntry.lba_start == 0 && ebrEntry.lba_sectors == 0 && extValid) { extStart = CHS.ToLBA(startCylinder, ebrEntry.start_head, startSector, - imagePlugin.ImageInfo.Heads, imagePlugin.ImageInfo.SectorsPerTrack); + imagePlugin.Info.Heads, imagePlugin.Info.SectorsPerTrack); extSectors = CHS.ToLBA(endCylinder, ebrEntry.end_head, ebrEntry.end_sector, - imagePlugin.ImageInfo.Heads, imagePlugin.ImageInfo.SectorsPerTrack) - + imagePlugin.Info.Heads, imagePlugin.Info.SectorsPerTrack) - extStart; } extMinix |= ebrEntry.type == 0x81 || ebrEntry.type == 0x80; @@ -437,11 +434,11 @@ namespace DiscImageChef.Partitions } extStart += lbaStart; - extValid &= extStart <= imagePlugin.ImageInfo.Sectors; + extValid &= extStart <= imagePlugin.Info.Sectors; // Some buggy implementations do some rounding errors getting a few sectors beyond device size - if(extStart + extSectors > imagePlugin.ImageInfo.Sectors) - extSectors = imagePlugin.ImageInfo.Sectors - extStart; + if(extStart + extSectors > imagePlugin.Info.Sectors) + extSectors = imagePlugin.Info.Sectors - extStart; if(extValid && extMinix) // Let's mix the fun if(GetMinix(imagePlugin, lbaStart, divider, sectorOffset, sectorSize, @@ -474,7 +471,7 @@ namespace DiscImageChef.Partitions DicConsole.DebugWriteLine("MBR plugin", "next_start {0}", nextStart); processingExtended &= nextStart != 0; - processingExtended &= nextStart <= imagePlugin.ImageInfo.Sectors; + processingExtended &= nextStart <= imagePlugin.Info.Sectors; lbaStart = nextStart; } } @@ -483,7 +480,7 @@ namespace DiscImageChef.Partitions return partitions.Count != 0; } - static bool GetMinix(ImagePlugin imagePlugin, ulong start, ulong divider, ulong sectorOffset, uint sectorSize, + static bool GetMinix(IMediaImage imagePlugin, ulong start, ulong divider, ulong sectorOffset, uint sectorSize, out List partitions) { partitions = new List(); @@ -529,10 +526,10 @@ namespace DiscImageChef.Partitions mnxEntry.end_head != 0 || mnxEntry.end_sector != 0; if(mnxEntry.lba_start == 0 && mnxEntry.lba_sectors == 0 && mnxValid) { - mnxStart = CHS.ToLBA(startCylinder, mnxEntry.start_head, startSector, imagePlugin.ImageInfo.Heads, - imagePlugin.ImageInfo.SectorsPerTrack); + mnxStart = CHS.ToLBA(startCylinder, mnxEntry.start_head, startSector, imagePlugin.Info.Heads, + imagePlugin.Info.SectorsPerTrack); mnxSectors = CHS.ToLBA(endCylinder, mnxEntry.end_head, mnxEntry.end_sector, - imagePlugin.ImageInfo.Heads, imagePlugin.ImageInfo.SectorsPerTrack) - + imagePlugin.Info.Heads, imagePlugin.Info.SectorsPerTrack) - mnxStart; } diff --git a/DiscImageChef.Partitions/NeXT.cs b/DiscImageChef.Partitions/NeXT.cs index 4f132247..0f9fb2c2 100644 --- a/DiscImageChef.Partitions/NeXT.cs +++ b/DiscImageChef.Partitions/NeXT.cs @@ -42,34 +42,31 @@ using DiscImageChef.DiscImages; // Information learnt from XNU source and testing against real disks namespace DiscImageChef.Partitions { - public class NeXTDisklabel : PartitionPlugin + public class NeXTDisklabel : IPartition { + /// "NeXT" const uint NEXT_MAGIC1 = 0x4E655854; - // "NeXT" + /// "dlV2" const uint NEXT_MAGIC2 = 0x646C5632; - // "dlV2" + /// "dlV3" const uint NEXT_MAGIC3 = 0x646C5633; - // "dlV3" + /// 180 const ushort DISKTAB_START = 0xB4; - // 180 + /// 44 const ushort DISKTAB_ENTRY_SIZE = 0x2C; - // 44 - public NeXTDisklabel() - { - Name = "NeXT Disklabel"; - PluginUuid = new Guid("246A6D93-4F1A-1F8A-344D-50187A5513A9"); - } + public virtual string Name => "NeXT Disklabel"; + public virtual Guid Id => new Guid("246A6D93-4F1A-1F8A-344D-50187A5513A9"); - public override bool GetInformation(ImagePlugin imagePlugin, out List partitions, ulong sectorOffset) + public virtual bool GetInformation(IMediaImage imagePlugin, out List partitions, ulong sectorOffset) { bool magicFound = false; byte[] labelSector; uint sectorSize; - if(imagePlugin.ImageInfo.SectorSize == 2352 || imagePlugin.ImageInfo.SectorSize == 2448) sectorSize = 2048; - else sectorSize = imagePlugin.ImageInfo.SectorSize; + if(imagePlugin.Info.SectorSize == 2352 || imagePlugin.Info.SectorSize == 2448) sectorSize = 2048; + else sectorSize = imagePlugin.Info.SectorSize; partitions = new List(); @@ -77,8 +74,7 @@ namespace DiscImageChef.Partitions ulong labelPosition = 0; - foreach(ulong i in - new ulong[] {0, 4, 15, 16}.TakeWhile(i => i + sectorOffset < imagePlugin.ImageInfo.Sectors)) + foreach(ulong i in new ulong[] {0, 4, 15, 16}.TakeWhile(i => i + sectorOffset < imagePlugin.Info.Sectors)) { labelSector = imagePlugin.ReadSector(i + sectorOffset); uint magic = BigEndianBitConverter.ToUInt32(labelSector, 0x00); @@ -91,8 +87,8 @@ namespace DiscImageChef.Partitions if(!magicFound) return false; - uint sectorsToRead = 7680 / imagePlugin.ImageInfo.SectorSize; - if(7680 % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++; + uint sectorsToRead = 7680 / imagePlugin.Info.SectorSize; + if(7680 % imagePlugin.Info.SectorSize > 0) sectorsToRead++; labelSector = imagePlugin.ReadSectors(labelPosition, sectorsToRead); @@ -184,10 +180,10 @@ namespace DiscImageChef.Partitions Scheme = Name }; - if(part.Start + part.Length > imagePlugin.ImageInfo.Sectors) + if(part.Start + part.Length > imagePlugin.Info.Sectors) { DicConsole.DebugWriteLine("NeXT Plugin", "Partition bigger than device, reducing..."); - part.Length = imagePlugin.ImageInfo.Sectors - part.Start; + part.Length = imagePlugin.Info.Sectors - part.Start; part.Size = part.Length * sectorSize; DicConsole.DebugWriteLine("NeXT Plugin", "label.dl_dt.d_partitions[{0}].p_size = {1}", i, part.Length); diff --git a/DiscImageChef.Partitions/PC98.cs b/DiscImageChef.Partitions/PC98.cs index f189f2d4..8952f33e 100644 --- a/DiscImageChef.Partitions/PC98.cs +++ b/DiscImageChef.Partitions/PC98.cs @@ -41,15 +41,12 @@ using DiscImageChef.Helpers; namespace DiscImageChef.Partitions { - public class PC98 : PartitionPlugin + public class PC98 : IPartition { - public PC98() - { - Name = "NEC PC-9800 partition table"; - PluginUuid = new Guid("27333401-C7C2-447D-961C-22AD0641A09A"); - } + public virtual string Name => "NEC PC-9800 partition table"; + public virtual Guid Id => new Guid("27333401-C7C2-447D-961C-22AD0641A09A"); - public override bool GetInformation(ImagePlugin imagePlugin, out List partitions, ulong sectorOffset) + public virtual bool GetInformation(IMediaImage imagePlugin, out List partitions, ulong sectorOffset) { partitions = new List(); @@ -84,27 +81,25 @@ namespace DiscImageChef.Partitions DicConsole.DebugWriteLine("PC98 plugin", "entry.dp_name = \"{0}\"", StringHandlers.CToString(entry.dp_name, Encoding.GetEncoding(932))); - if(entry.dp_scyl == entry.dp_ecyl || entry.dp_ecyl <= 0 || - entry.dp_scyl > imagePlugin.ImageInfo.Cylinders || entry.dp_ecyl > imagePlugin.ImageInfo.Cylinders || - entry.dp_shd > imagePlugin.ImageInfo.Heads || entry.dp_ehd > imagePlugin.ImageInfo.Heads || - entry.dp_ssect > imagePlugin.ImageInfo.SectorsPerTrack || - entry.dp_esect > imagePlugin.ImageInfo.SectorsPerTrack) continue; + if(entry.dp_scyl == entry.dp_ecyl || entry.dp_ecyl <= 0 || entry.dp_scyl > imagePlugin.Info.Cylinders || + entry.dp_ecyl > imagePlugin.Info.Cylinders || entry.dp_shd > imagePlugin.Info.Heads || + entry.dp_ehd > imagePlugin.Info.Heads || entry.dp_ssect > imagePlugin.Info.SectorsPerTrack || + entry.dp_esect > imagePlugin.Info.SectorsPerTrack) continue; Partition part = new Partition { Start = - CHS.ToLBA(entry.dp_scyl, entry.dp_shd, (uint)(entry.dp_ssect + 1), imagePlugin.ImageInfo.Heads, - imagePlugin.ImageInfo.SectorsPerTrack), + CHS.ToLBA(entry.dp_scyl, entry.dp_shd, (uint)(entry.dp_ssect + 1), imagePlugin.Info.Heads, + imagePlugin.Info.SectorsPerTrack), Type = DecodePC98Sid(entry.dp_sid), Name = StringHandlers.CToString(entry.dp_name, Encoding.GetEncoding(932)).Trim(), Sequence = counter, Scheme = Name }; - part.Offset = part.Start * imagePlugin.ImageInfo.SectorSize; - part.Length = CHS.ToLBA(entry.dp_ecyl, entry.dp_ehd, (uint)(entry.dp_esect + 1), - imagePlugin.ImageInfo.Heads, imagePlugin.ImageInfo.SectorsPerTrack) - - part.Start; - part.Size = part.Length * imagePlugin.ImageInfo.SectorSize; + part.Offset = part.Start * imagePlugin.Info.SectorSize; + part.Length = CHS.ToLBA(entry.dp_ecyl, entry.dp_ehd, (uint)(entry.dp_esect + 1), imagePlugin.Info.Heads, + imagePlugin.Info.SectorsPerTrack) - part.Start; + part.Size = part.Length * imagePlugin.Info.SectorSize; DicConsole.DebugWriteLine("PC98 plugin", "part.Start = {0}", part.Start); DicConsole.DebugWriteLine("PC98 plugin", "part.Type = {0}", part.Type); @@ -115,7 +110,7 @@ namespace DiscImageChef.Partitions DicConsole.DebugWriteLine("PC98 plugin", "part.Size = {0}", part.Size); if((entry.dp_mid & 0x20) != 0x20 && (entry.dp_mid & 0x44) != 0x44 || - part.Start >= imagePlugin.ImageInfo.Sectors || part.End > imagePlugin.ImageInfo.Sectors) continue; + part.Start >= imagePlugin.Info.Sectors || part.End > imagePlugin.Info.Sectors) continue; partitions.Add(part); counter++; diff --git a/DiscImageChef.Partitions/Plan9.cs b/DiscImageChef.Partitions/Plan9.cs index 80f37cc0..ef93ffe3 100644 --- a/DiscImageChef.Partitions/Plan9.cs +++ b/DiscImageChef.Partitions/Plan9.cs @@ -43,19 +43,16 @@ namespace DiscImageChef.Partitions // "part type start end\n" // One line per partition, start and end relative to offset // e.g.: "part nvram 10110 10112\npart fossil 10112 3661056\n" - public class Plan9 : PartitionPlugin + public class Plan9 : IPartition { - public Plan9() - { - Name = "Plan9 partition table"; - PluginUuid = new Guid("F0BF4FFC-056E-4E7C-8B65-4EAEE250ADD9"); - } + public virtual string Name => "Plan9 partition table"; + public virtual Guid Id => new Guid("F0BF4FFC-056E-4E7C-8B65-4EAEE250ADD9"); - public override bool GetInformation(ImagePlugin imagePlugin, out List partitions, ulong sectorOffset) + public virtual bool GetInformation(IMediaImage imagePlugin, out List partitions, ulong sectorOffset) { partitions = new List(); - if(sectorOffset + 2 >= imagePlugin.ImageInfo.Sectors) return false; + if(sectorOffset + 2 >= imagePlugin.Info.Sectors) return false; byte[] sector = imagePlugin.ReadSector(sectorOffset + 1); // While all of Plan9 is supposedly UTF-8, it uses ASCII strcmp for reading its partition table @@ -69,10 +66,10 @@ namespace DiscImageChef.Partitions Partition part = new Partition { Length = end - start + 1, - Offset = (start + sectorOffset) * imagePlugin.ImageInfo.SectorSize, + Offset = (start + sectorOffset) * imagePlugin.Info.SectorSize, Scheme = Name, Sequence = (ulong)partitions.Count, - Size = (end - start + 1) * imagePlugin.ImageInfo.SectorSize, + Size = (end - start + 1) * imagePlugin.Info.SectorSize, Start = start + sectorOffset, Type = tokens[1] }; diff --git a/DiscImageChef.Partitions/RDB.cs b/DiscImageChef.Partitions/RDB.cs index eb3c89b9..fdb46d3b 100644 --- a/DiscImageChef.Partitions/RDB.cs +++ b/DiscImageChef.Partitions/RDB.cs @@ -41,7 +41,7 @@ using DiscImageChef.DiscImages; namespace DiscImageChef.Partitions { - public class AmigaRigidDiskBlock : PartitionPlugin + public class AmigaRigidDiskBlock : IPartition { /// /// RDB magic number "RDSK" @@ -275,13 +275,10 @@ namespace DiscImageChef.Partitions /// const uint FLAGS_NO_AUTOMOUNT = 0x00000002; - public AmigaRigidDiskBlock() - { - Name = "Amiga Rigid Disk Block"; - PluginUuid = new Guid("8D72ED97-1854-4170-9CE4-6E8446FD9863"); - } + public virtual string Name => "Amiga Rigid Disk Block"; + public virtual Guid Id => new Guid("8D72ED97-1854-4170-9CE4-6E8446FD9863"); - public override bool GetInformation(ImagePlugin imagePlugin, out List partitions, ulong sectorOffset) + public virtual bool GetInformation(IMediaImage imagePlugin, out List partitions, ulong sectorOffset) { partitions = new List(); BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; @@ -290,9 +287,9 @@ namespace DiscImageChef.Partitions while(rdbBlock < 16) { - if(imagePlugin.ImageInfo.Sectors <= rdbBlock) return false; + if(imagePlugin.Info.Sectors <= rdbBlock) return false; - if(rdbBlock + sectorOffset >= imagePlugin.ImageInfo.Sectors) break; + if(rdbBlock + sectorOffset >= imagePlugin.Info.Sectors) break; byte[] tmpSector = imagePlugin.ReadSector(rdbBlock + sectorOffset); uint magic = BigEndianBitConverter.ToUInt32(tmpSector, 0); diff --git a/DiscImageChef.Partitions/RioKarma.cs b/DiscImageChef.Partitions/RioKarma.cs index 4f34a1bb..d1f8bb99 100644 --- a/DiscImageChef.Partitions/RioKarma.cs +++ b/DiscImageChef.Partitions/RioKarma.cs @@ -39,18 +39,15 @@ using DiscImageChef.DiscImages; namespace DiscImageChef.Partitions { - public class RioKarma : PartitionPlugin + public class RioKarma : IPartition { const ushort KARMA_MAGIC = 0xAB56; const byte ENTRY_MAGIC = 0x4D; - public RioKarma() - { - Name = "Rio Karma partitioning"; - PluginUuid = new Guid("246A6D93-4F1A-1F8A-344D-50187A5513A9"); - } + public virtual string Name => "Rio Karma partitioning"; + public virtual Guid Id => new Guid("246A6D93-4F1A-1F8A-344D-50187A5513A9"); - public override bool GetInformation(ImagePlugin imagePlugin, out List partitions, ulong sectorOffset) + public virtual bool GetInformation(IMediaImage imagePlugin, out List partitions, ulong sectorOffset) { partitions = new List(); diff --git a/DiscImageChef.Partitions/SGI.cs b/DiscImageChef.Partitions/SGI.cs index 826db486..c460de1d 100644 --- a/DiscImageChef.Partitions/SGI.cs +++ b/DiscImageChef.Partitions/SGI.cs @@ -44,17 +44,14 @@ using DiscImageChef.DiscImages; namespace DiscImageChef.Partitions { [SuppressMessage("ReSharper", "InconsistentNaming")] - public class SGI : PartitionPlugin + public class SGI : IPartition { const int SGI_MAGIC = 0x0BE5A941; - public SGI() - { - Name = "SGI Disk Volume Header"; - PluginUuid = new Guid("AEF5AB45-4880-4CE8-8735-F0A402E2E5F2"); - } + public virtual string Name => "SGI Disk Volume Header"; + public virtual Guid Id => new Guid("AEF5AB45-4880-4CE8-8735-F0A402E2E5F2"); - public override bool GetInformation(ImagePlugin imagePlugin, out List partitions, ulong sectorOffset) + public virtual bool GetInformation(IMediaImage imagePlugin, out List partitions, ulong sectorOffset) { partitions = new List(); @@ -121,12 +118,9 @@ namespace DiscImageChef.Partitions Partition part = new Partition { - Start = - dvh.partitions[i].first_block * dvh.device_params.dp_secbytes / - imagePlugin.ImageInfo.SectorSize, + Start = dvh.partitions[i].first_block * dvh.device_params.dp_secbytes / imagePlugin.Info.SectorSize, Offset = dvh.partitions[i].first_block * dvh.device_params.dp_secbytes, - Length = - dvh.partitions[i].num_blocks * dvh.device_params.dp_secbytes / imagePlugin.ImageInfo.SectorSize, + Length = dvh.partitions[i].num_blocks * dvh.device_params.dp_secbytes / imagePlugin.Info.SectorSize, Size = dvh.partitions[i].num_blocks * dvh.device_params.dp_secbytes, Type = TypeToString(dvh.partitions[i].type), Sequence = counter, diff --git a/DiscImageChef.Partitions/Sun.cs b/DiscImageChef.Partitions/Sun.cs index cc9147a7..9877bec0 100644 --- a/DiscImageChef.Partitions/Sun.cs +++ b/DiscImageChef.Partitions/Sun.cs @@ -42,7 +42,7 @@ using DiscImageChef.DiscImages; namespace DiscImageChef.Partitions { [SuppressMessage("ReSharper", "InconsistentNaming")] - public class SunDisklabel : PartitionPlugin + public class SunDisklabel : IPartition { /// Sun disklabel magic number const ushort DKL_MAGIC = 0xDABE; @@ -70,19 +70,16 @@ namespace DiscImageChef.Partitions const int LEN_DKL_PAD16 = DK_LABEL_SIZE - (456 + // sizeof(dk_vtoc16) 4 * 4 + 12 * 2 + 2 * 2); - public SunDisklabel() - { - Name = "Sun Disklabel"; - PluginUuid = new Guid("50F35CC4-8375-4445-8DCB-1BA550C931A3"); - } + public virtual string Name => "Sun Disklabel"; + public virtual Guid Id => new Guid("50F35CC4-8375-4445-8DCB-1BA550C931A3"); - public override bool GetInformation(ImagePlugin imagePlugin, out List partitions, ulong sectorOffset) + public virtual bool GetInformation(IMediaImage imagePlugin, out List partitions, ulong sectorOffset) { partitions = new List(); - if(imagePlugin.ImageInfo.SectorSize < 512) return false; + if(imagePlugin.Info.SectorSize < 512) return false; - if(sectorOffset + 2 >= imagePlugin.ImageInfo.Sectors) return false; + if(sectorOffset + 2 >= imagePlugin.Info.Sectors) return false; bool useDkl = false, useDkl8 = false, useDkl16 = false; @@ -162,16 +159,16 @@ namespace DiscImageChef.Partitions { Size = (ulong)dkl.dkl_map[i].dkl_nblk * DK_LABEL_SIZE, Length = - (ulong)(dkl.dkl_map[i].dkl_nblk * DK_LABEL_SIZE / imagePlugin.ImageInfo.SectorSize), + (ulong)(dkl.dkl_map[i].dkl_nblk * DK_LABEL_SIZE / imagePlugin.Info.SectorSize), Sequence = (ulong)i, Offset = ((ulong)dkl.dkl_map[i].dkl_cylno * sectorsPerCylinder + sectorOffset) * DK_LABEL_SIZE, Start = ((ulong)dkl.dkl_map[i].dkl_cylno * sectorsPerCylinder + sectorOffset) * - DK_LABEL_SIZE / imagePlugin.ImageInfo.SectorSize, + DK_LABEL_SIZE / imagePlugin.Info.SectorSize, Type = "SunOS partition", Scheme = Name }; - if(part.Start < imagePlugin.ImageInfo.Sectors && part.End <= imagePlugin.ImageInfo.Sectors) + if(part.Start < imagePlugin.Info.Sectors && part.End <= imagePlugin.Info.Sectors) partitions.Add(part); } } @@ -229,12 +226,12 @@ namespace DiscImageChef.Partitions Description = SunFlagsToString(dkl8.dkl_vtoc.v_part[i].p_flag), Size = (ulong)dkl8.dkl_map[i].dkl_nblk * DK_LABEL_SIZE, Length = - (ulong)(dkl8.dkl_map[i].dkl_nblk * DK_LABEL_SIZE / imagePlugin.ImageInfo.SectorSize), + (ulong)(dkl8.dkl_map[i].dkl_nblk * DK_LABEL_SIZE / imagePlugin.Info.SectorSize), Sequence = (ulong)i, Offset = ((ulong)dkl8.dkl_map[i].dkl_cylno * sectorsPerCylinder + sectorOffset) * DK_LABEL_SIZE, Start = ((ulong)dkl8.dkl_map[i].dkl_cylno * sectorsPerCylinder + sectorOffset) * - DK_LABEL_SIZE / imagePlugin.ImageInfo.SectorSize, + DK_LABEL_SIZE / imagePlugin.Info.SectorSize, Type = SunIdToString(dkl8.dkl_vtoc.v_part[i].p_tag), Scheme = Name }; @@ -242,7 +239,7 @@ namespace DiscImageChef.Partitions part.Description += $"\nPartition timestamped on {DateHandlers.UnixToDateTime(dkl8.dkl_vtoc.v_timestamp[i])}"; - if(part.Start < imagePlugin.ImageInfo.Sectors && part.End <= imagePlugin.ImageInfo.Sectors) + if(part.Start < imagePlugin.Info.Sectors && part.End <= imagePlugin.Info.Sectors) partitions.Add(part); } } @@ -297,19 +294,19 @@ namespace DiscImageChef.Partitions Size = (ulong)dkl16.dkl_vtoc.v_part[i].p_size * dkl16.dkl_vtoc.v_sectorsz, Length = (ulong)(dkl16.dkl_vtoc.v_part[i].p_size * dkl16.dkl_vtoc.v_sectorsz / - imagePlugin.ImageInfo.SectorSize), + imagePlugin.Info.SectorSize), Sequence = (ulong)i, Offset = ((ulong)dkl16.dkl_vtoc.v_part[i].p_start + sectorOffset) * dkl16.dkl_vtoc.v_sectorsz, Start = ((ulong)dkl16.dkl_vtoc.v_part[i].p_start + sectorOffset) * - dkl16.dkl_vtoc.v_sectorsz / imagePlugin.ImageInfo.SectorSize, + dkl16.dkl_vtoc.v_sectorsz / imagePlugin.Info.SectorSize, Type = SunIdToString(dkl16.dkl_vtoc.v_part[i].p_tag), Scheme = Name }; if(dkl16.dkl_vtoc.v_timestamp[i] != 0) part.Description += $"\nPartition timestamped on {DateHandlers.UnixToDateTime(dkl16.dkl_vtoc.v_timestamp[i])}"; - if(part.Start < imagePlugin.ImageInfo.Sectors && part.End <= imagePlugin.ImageInfo.Sectors) + if(part.Start < imagePlugin.Info.Sectors && part.End <= imagePlugin.Info.Sectors) partitions.Add(part); } } diff --git a/DiscImageChef.Partitions/UNIX.cs b/DiscImageChef.Partitions/UNIX.cs index 858eff17..cb016b6a 100644 --- a/DiscImageChef.Partitions/UNIX.cs +++ b/DiscImageChef.Partitions/UNIX.cs @@ -41,7 +41,7 @@ namespace DiscImageChef.Partitions // These partitions are hardwired in kernel sources for some UNIX versions predating System V. // They depend on exact device, indeed the kernel chooses what to use depending on the disk driver, so that's what we do. // Currently only DEC devices used in Ultrix are added, probably it's missing a lot of entries. - public class UNIX : PartitionPlugin + public class UNIX : IPartition { readonly Partition[] RA60 = { @@ -1369,20 +1369,17 @@ namespace DiscImageChef.Partitions } }; - public UNIX() - { - Name = "UNIX hardwired"; - PluginUuid = new Guid("9ED7E30B-53BF-4619-87A0-5D2002155617"); - } + public virtual string Name => "UNIX hardwired"; + public virtual Guid Id => new Guid("9ED7E30B-53BF-4619-87A0-5D2002155617"); - public override bool GetInformation(ImagePlugin imagePlugin, out List partitions, ulong sectorOffset) + public virtual bool GetInformation(IMediaImage imagePlugin, out List partitions, ulong sectorOffset) { partitions = new List(); Partition[] parts; if(sectorOffset != 0) return false; - switch(imagePlugin.ImageInfo.MediaType) + switch(imagePlugin.Info.MediaType) { case MediaType.RA60: parts = RA60; diff --git a/DiscImageChef.Partitions/VTOC.cs b/DiscImageChef.Partitions/VTOC.cs index 228a8471..d97193d5 100644 --- a/DiscImageChef.Partitions/VTOC.cs +++ b/DiscImageChef.Partitions/VTOC.cs @@ -40,7 +40,7 @@ using DiscImageChef.DiscImages; namespace DiscImageChef.Partitions { - public class VTOC : PartitionPlugin + public class VTOC : IPartition { const uint PD_MAGIC = 0xCA5E600D; const uint VTOC_SANE = 0x600DDEEE; @@ -49,13 +49,10 @@ namespace DiscImageChef.Partitions const int V_NUMPAR = 16; const uint XPDVERS = 3; /* 1st version of extended pdinfo */ - public VTOC() - { - Name = "UNIX VTOC"; - PluginUuid = new Guid("6D35A66F-8D77-426F-A562-D88F6A1F1702"); - } + public virtual string Name => "UNIX VTOC"; + public virtual Guid Id => new Guid("6D35A66F-8D77-426F-A562-D88F6A1F1702"); - public override bool GetInformation(ImagePlugin imagePlugin, out List partitions, ulong sectorOffset) + public virtual bool GetInformation(IMediaImage imagePlugin, out List partitions, ulong sectorOffset) { partitions = new List(); @@ -65,8 +62,7 @@ namespace DiscImageChef.Partitions bool magicFound = false; bool absolute = false; - foreach(ulong i in - new ulong[] {0, 1, 8, 29}.TakeWhile(i => i + sectorOffset < imagePlugin.ImageInfo.Sectors)) + foreach(ulong i in new ulong[] {0, 1, 8, 29}.TakeWhile(i => i + sectorOffset < imagePlugin.Info.Sectors)) { pdsector = imagePlugin.ReadSector(i + sectorOffset); magic = BitConverter.ToUInt32(pdsector, 4); @@ -205,14 +201,14 @@ namespace DiscImageChef.Partitions if(!magicFound) { DicConsole.DebugWriteLine("VTOC plugin", "Searching for VTOC on relative byte {0}", pd.vtoc_ptr); - ulong relSecPtr = pd.vtoc_ptr / imagePlugin.ImageInfo.SectorSize; - uint relSecOff = pd.vtoc_ptr % imagePlugin.ImageInfo.SectorSize; - uint secCount = (relSecOff + pd.vtoc_len) / imagePlugin.ImageInfo.SectorSize; - if((relSecOff + pd.vtoc_len) % imagePlugin.ImageInfo.SectorSize > 0) secCount++; + ulong relSecPtr = pd.vtoc_ptr / imagePlugin.Info.SectorSize; + uint relSecOff = pd.vtoc_ptr % imagePlugin.Info.SectorSize; + uint secCount = (relSecOff + pd.vtoc_len) / imagePlugin.Info.SectorSize; + if((relSecOff + pd.vtoc_len) % imagePlugin.Info.SectorSize > 0) secCount++; DicConsole.DebugWriteLine("VTOC plugin", "Going to read {0} sectors from sector {1}, getting VTOC from byte {2}", secCount, relSecPtr + sectorOffset, relSecOff); - if(relSecPtr + sectorOffset + secCount >= imagePlugin.ImageInfo.Sectors) + if(relSecPtr + sectorOffset + secCount >= imagePlugin.Info.Sectors) { DicConsole.DebugWriteLine("VTOC plugin", "Going to read past device size, aborting..."); return false; @@ -331,8 +327,8 @@ namespace DiscImageChef.Partitions { Partition part = new Partition { - Start = (ulong)(parts[i].p_start * bps) / imagePlugin.ImageInfo.SectorSize, - Length = (ulong)(parts[i].p_size * bps) / imagePlugin.ImageInfo.SectorSize, + Start = (ulong)(parts[i].p_start * bps) / imagePlugin.Info.SectorSize, + Length = (ulong)(parts[i].p_size * bps) / imagePlugin.Info.SectorSize, Offset = (ulong)(parts[i].p_start * bps), Size = (ulong)(parts[i].p_size * bps), Sequence = (ulong)i, @@ -345,7 +341,7 @@ namespace DiscImageChef.Partitions if(!useOld && !absolute) { part.Start += sectorOffset; - part.Offset += sectorOffset * imagePlugin.ImageInfo.SectorSize; + part.Offset += sectorOffset * imagePlugin.Info.SectorSize; } if(parts[i].p_flag.HasFlag(pFlag.V_VALID)) info += " (valid)"; @@ -357,7 +353,7 @@ namespace DiscImageChef.Partitions part.Description = "UNIX slice" + info + "."; - if(part.End < imagePlugin.ImageInfo.Sectors) partitions.Add(part); + if(part.End < imagePlugin.Info.Sectors) partitions.Add(part); } return partitions.Count > 0; diff --git a/DiscImageChef.Partitions/XENIX.cs b/DiscImageChef.Partitions/XENIX.cs index df61dbb0..e0908eb6 100644 --- a/DiscImageChef.Partitions/XENIX.cs +++ b/DiscImageChef.Partitions/XENIX.cs @@ -40,7 +40,7 @@ using DiscImageChef.DiscImages; namespace DiscImageChef.Partitions { // TODO: Find better documentation, this is working for XENIX 2 but not for SCO OpenServer... - public class XENIX : PartitionPlugin + public class XENIX : IPartition { const ushort PAMAGIC = 0x1234; const int MAXPARTS = 16; @@ -48,17 +48,14 @@ namespace DiscImageChef.Partitions // Can't find this in any documentation but everything is aligned to this offset (in sectors) const uint XENIX_OFFSET = 977; - public XENIX() - { - Name = "XENIX"; - PluginUuid = new Guid("53BE01DE-E68B-469F-A17F-EC2E4BD61CD9"); - } + public virtual string Name => "XENIX"; + public virtual Guid Id => new Guid("53BE01DE-E68B-469F-A17F-EC2E4BD61CD9"); - public override bool GetInformation(ImagePlugin imagePlugin, out List partitions, ulong sectorOffset) + public virtual bool GetInformation(IMediaImage imagePlugin, out List partitions, ulong sectorOffset) { partitions = new List(); - if(42 + sectorOffset >= imagePlugin.ImageInfo.Sectors) return false; + if(42 + sectorOffset >= imagePlugin.Info.Sectors) return false; byte[] tblsector = imagePlugin.ReadSector(42 + sectorOffset); @@ -80,19 +77,19 @@ namespace DiscImageChef.Partitions Partition part = new Partition { Start = - (ulong)((xnxtbl.p[i].p_off + XENIX_OFFSET) * XENIX_BSIZE) / imagePlugin.ImageInfo.SectorSize + + (ulong)((xnxtbl.p[i].p_off + XENIX_OFFSET) * XENIX_BSIZE) / imagePlugin.Info.SectorSize + sectorOffset, - Length = (ulong)(xnxtbl.p[i].p_size * XENIX_BSIZE) / imagePlugin.ImageInfo.SectorSize, + Length = (ulong)(xnxtbl.p[i].p_size * XENIX_BSIZE) / imagePlugin.Info.SectorSize, Offset = (ulong)((xnxtbl.p[i].p_off + XENIX_OFFSET) * XENIX_BSIZE) + - imagePlugin.ImageInfo.SectorSize * sectorOffset, + imagePlugin.Info.SectorSize * sectorOffset, Size = (ulong)(xnxtbl.p[i].p_size * XENIX_BSIZE), Sequence = (ulong)i, Type = "XENIX", Scheme = Name }; - if(part.End < imagePlugin.ImageInfo.Sectors) partitions.Add(part); + if(part.End < imagePlugin.Info.Sectors) partitions.Add(part); } return partitions.Count > 0; diff --git a/DiscImageChef.Partitions/Xbox.cs b/DiscImageChef.Partitions/Xbox.cs index 711dcd16..72218e3c 100644 --- a/DiscImageChef.Partitions/Xbox.cs +++ b/DiscImageChef.Partitions/Xbox.cs @@ -38,7 +38,7 @@ using DiscImageChef.DiscImages; namespace DiscImageChef.Partitions { - public class Xbox : PartitionPlugin + public class Xbox : IPartition { const uint XboxCigam = 0x46415458; const uint XboxMagic = 0x58544146; @@ -60,13 +60,10 @@ namespace DiscImageChef.Partitions const uint XBOX360_DEVKIT_MAGIC = 0x00020000; - public Xbox() - { - Name = "Xbox partitioning"; - PluginUuid = new Guid("E3F6FB91-D358-4F22-A550-81E92D50EB78"); - } + public virtual string Name => "Xbox partitioning"; + public virtual Guid Id => new Guid("E3F6FB91-D358-4F22-A550-81E92D50EB78"); - public override bool GetInformation(ImagePlugin imagePlugin, out List partitions, ulong sectorOffset) + public virtual bool GetInformation(IMediaImage imagePlugin, out List partitions, ulong sectorOffset) { partitions = new List(); @@ -79,17 +76,16 @@ namespace DiscImageChef.Partitions Xbox360DevKitPartitionTable table = BigEndianMarshal.ByteArrayToStructureBigEndian(sector); - if(table.magic == XBOX360_DEVKIT_MAGIC && - table.contentOff + table.contentLen <= imagePlugin.ImageInfo.Sectors && - table.dashboardOff + table.dashboardLen <= imagePlugin.ImageInfo.Sectors) + if(table.magic == XBOX360_DEVKIT_MAGIC && table.contentOff + table.contentLen <= imagePlugin.Info.Sectors && + table.dashboardOff + table.dashboardLen <= imagePlugin.Info.Sectors) { Partition contentPart = new Partition { Description = "Content volume", - Size = (ulong)table.contentLen * imagePlugin.ImageInfo.SectorSize, + Size = (ulong)table.contentLen * imagePlugin.Info.SectorSize, Length = table.contentLen, Sequence = 1, - Offset = (ulong)table.contentOff * imagePlugin.ImageInfo.SectorSize, + Offset = (ulong)table.contentOff * imagePlugin.Info.SectorSize, Start = table.contentOff, Scheme = Name }; @@ -97,10 +93,10 @@ namespace DiscImageChef.Partitions Partition dashboardPart = new Partition { Description = "Dashboard volume", - Size = (ulong)table.dashboardLen * imagePlugin.ImageInfo.SectorSize, + Size = (ulong)table.dashboardLen * imagePlugin.Info.SectorSize, Length = table.dashboardLen, Sequence = 2, - Offset = (ulong)table.dashboardOff * imagePlugin.ImageInfo.SectorSize, + Offset = (ulong)table.dashboardOff * imagePlugin.Info.SectorSize, Start = table.dashboardOff, Scheme = Name }; @@ -113,9 +109,9 @@ namespace DiscImageChef.Partitions uint temp; - if(imagePlugin.ImageInfo.Sectors > (ulong)(MemoryUnitDataOff / imagePlugin.ImageInfo.SectorSize)) + if(imagePlugin.Info.Sectors > (ulong)(MemoryUnitDataOff / imagePlugin.Info.SectorSize)) { - sector = imagePlugin.ReadSector((ulong)(MemoryUnitDataOff / imagePlugin.ImageInfo.SectorSize)); + sector = imagePlugin.ReadSector((ulong)(MemoryUnitDataOff / imagePlugin.Info.SectorSize)); temp = BitConverter.ToUInt32(sector, 0); if(temp == XboxCigam) @@ -124,7 +120,7 @@ namespace DiscImageChef.Partitions { Description = "System cache", Size = MemoryUnitDataOff, - Length = (ulong)(MemoryUnitDataOff / imagePlugin.ImageInfo.SectorSize), + Length = (ulong)(MemoryUnitDataOff / imagePlugin.Info.SectorSize), Sequence = 1, Offset = 0, Start = 0, @@ -134,8 +130,8 @@ namespace DiscImageChef.Partitions Partition dataPart = new Partition { Description = "Data volume", - Size = imagePlugin.ImageInfo.Sectors * imagePlugin.ImageInfo.SectorSize - MemoryUnitDataOff, - Length = imagePlugin.ImageInfo.Sectors - sysCachePart.Length, + Size = imagePlugin.Info.Sectors * imagePlugin.Info.SectorSize - MemoryUnitDataOff, + Length = imagePlugin.Info.Sectors - sysCachePart.Length, Sequence = 2, Offset = MemoryUnitDataOff, Start = sysCachePart.Length, @@ -149,11 +145,10 @@ namespace DiscImageChef.Partitions } } - if(imagePlugin.ImageInfo.Sectors <= (ulong)(Xbox360DataOff / imagePlugin.ImageInfo.SectorSize)) - return false; + if(imagePlugin.Info.Sectors <= (ulong)(Xbox360DataOff / imagePlugin.Info.SectorSize)) return false; { - sector = imagePlugin.ReadSector((ulong)(Xbox360DataOff / imagePlugin.ImageInfo.SectorSize)); + sector = imagePlugin.ReadSector((ulong)(Xbox360DataOff / imagePlugin.Info.SectorSize)); temp = BitConverter.ToUInt32(sector, 0); if(temp != XboxCigam) return false; @@ -162,10 +157,10 @@ namespace DiscImageChef.Partitions { Description = "Security sectors", Size = Xbox360SecuritySectorLen, - Length = (ulong)(Xbox360SecuritySectorLen / imagePlugin.ImageInfo.SectorSize), + Length = (ulong)(Xbox360SecuritySectorLen / imagePlugin.Info.SectorSize), Sequence = 1, Offset = Xbox360SecuritySectorOff, - Start = (ulong)(Xbox360SecuritySectorOff / imagePlugin.ImageInfo.SectorSize), + Start = (ulong)(Xbox360SecuritySectorOff / imagePlugin.Info.SectorSize), Scheme = Name }; @@ -173,10 +168,10 @@ namespace DiscImageChef.Partitions { Description = "System cache", Size = Xbox360SystemCacheLen, - Length = (ulong)(Xbox360SystemCacheLen / imagePlugin.ImageInfo.SectorSize), + Length = (ulong)(Xbox360SystemCacheLen / imagePlugin.Info.SectorSize), Sequence = 2, Offset = Xbox360SystemCacheOff, - Start = (ulong)(Xbox360SystemCacheOff / imagePlugin.ImageInfo.SectorSize), + Start = (ulong)(Xbox360SystemCacheOff / imagePlugin.Info.SectorSize), Scheme = Name }; @@ -184,10 +179,10 @@ namespace DiscImageChef.Partitions { Description = "Game cache", Size = Xbox360GameCacheLen, - Length = (ulong)(Xbox360GameCacheLen / imagePlugin.ImageInfo.SectorSize), + Length = (ulong)(Xbox360GameCacheLen / imagePlugin.Info.SectorSize), Sequence = 3, Offset = Xbox360GameCacheOff, - Start = (ulong)(Xbox360GameCacheOff / imagePlugin.ImageInfo.SectorSize), + Start = (ulong)(Xbox360GameCacheOff / imagePlugin.Info.SectorSize), Scheme = Name }; @@ -195,10 +190,10 @@ namespace DiscImageChef.Partitions { Description = "System volume", Size = Xbox368SysExtLen, - Length = (ulong)(Xbox368SysExtLen / imagePlugin.ImageInfo.SectorSize), + Length = (ulong)(Xbox368SysExtLen / imagePlugin.Info.SectorSize), Sequence = 4, Offset = Xbox368SysExtOff, - Start = (ulong)(Xbox368SysExtOff / imagePlugin.ImageInfo.SectorSize), + Start = (ulong)(Xbox368SysExtOff / imagePlugin.Info.SectorSize), Scheme = Name }; @@ -206,10 +201,10 @@ namespace DiscImageChef.Partitions { Description = "System volume 2", Size = Xbox360SysExt2Len, - Length = (ulong)(Xbox360SysExt2Len / imagePlugin.ImageInfo.SectorSize), + Length = (ulong)(Xbox360SysExt2Len / imagePlugin.Info.SectorSize), Sequence = 5, Offset = Xbox360SysExt2Off, - Start = (ulong)(Xbox360SysExt2Off / imagePlugin.ImageInfo.SectorSize), + Start = (ulong)(Xbox360SysExt2Off / imagePlugin.Info.SectorSize), Scheme = Name }; @@ -217,10 +212,10 @@ namespace DiscImageChef.Partitions { Description = "Xbox backwards compatibility", Size = Xbox360CompatLen, - Length = (ulong)(Xbox360CompatLen / imagePlugin.ImageInfo.SectorSize), + Length = (ulong)(Xbox360CompatLen / imagePlugin.Info.SectorSize), Sequence = 6, Offset = Xbox360CompatOff, - Start = (ulong)(Xbox360CompatOff / imagePlugin.ImageInfo.SectorSize), + Start = (ulong)(Xbox360CompatOff / imagePlugin.Info.SectorSize), Scheme = Name }; @@ -229,11 +224,11 @@ namespace DiscImageChef.Partitions Description = "Data volume", Sequence = 7, Offset = Xbox360DataOff, - Start = (ulong)(Xbox360DataOff / imagePlugin.ImageInfo.SectorSize), + Start = (ulong)(Xbox360DataOff / imagePlugin.Info.SectorSize), Scheme = Name }; - dataPart.Length = imagePlugin.ImageInfo.Sectors - dataPart.Start; - dataPart.Size = dataPart.Length * imagePlugin.ImageInfo.SectorSize; + dataPart.Length = imagePlugin.Info.Sectors - dataPart.Start; + dataPart.Size = dataPart.Length * imagePlugin.Info.SectorSize; partitions.Add(securityPart); partitions.Add(sysCachePart); diff --git a/DiscImageChef.Tests/Devices/IomegaJaz.cs b/DiscImageChef.Tests/Devices/IomegaJaz.cs index 7960b113..4b6d366c 100644 --- a/DiscImageChef.Tests/Devices/IomegaJaz.cs +++ b/DiscImageChef.Tests/Devices/IomegaJaz.cs @@ -51,13 +51,13 @@ namespace DiscImageChef.Tests.Devices for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "devices", "jaz", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new ZZZRawImage(); + IMediaImage image = new ZZZRawImage(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Devices/LS120.cs b/DiscImageChef.Tests/Devices/LS120.cs index 37fe7f15..ab9ee4e8 100644 --- a/DiscImageChef.Tests/Devices/LS120.cs +++ b/DiscImageChef.Tests/Devices/LS120.cs @@ -51,13 +51,13 @@ namespace DiscImageChef.Tests.Devices for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "devices", "ls120", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new ZZZRawImage(); + IMediaImage image = new ZZZRawImage(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Devices/PocketZip.cs b/DiscImageChef.Tests/Devices/PocketZip.cs index f9c7eb7f..1d5216db 100644 --- a/DiscImageChef.Tests/Devices/PocketZip.cs +++ b/DiscImageChef.Tests/Devices/PocketZip.cs @@ -51,13 +51,13 @@ namespace DiscImageChef.Tests.Devices for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "devices", "pocketzip", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new ZZZRawImage(); + IMediaImage image = new ZZZRawImage(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/ADFS.cs b/DiscImageChef.Tests/Filesystems/ADFS.cs index aab8a0fb..a82d4e41 100644 --- a/DiscImageChef.Tests/Filesystems/ADFS.cs +++ b/DiscImageChef.Tests/Filesystems/ADFS.cs @@ -72,28 +72,28 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "adfs", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new ZZZRawImage(); + IMediaImage image = new ZZZRawImage(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - Filesystem fs = new AcornADFS(); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + IFilesystem fs = new AcornADFS(); Partition wholePart = new Partition { Name = "Whole device", - Length = image.ImageInfo.Sectors, - Size = image.ImageInfo.Sectors * image.ImageInfo.SectorSize + Length = image.Info.Sectors, + Size = image.Info.Sectors * image.Info.SectorSize }; Assert.AreEqual(true, fs.Identify(image, wholePart), testfiles[i]); - fs.GetInformation(image, wholePart, out _); - Assert.AreEqual(bootable[i], fs.XmlFSType.Bootable, testfiles[i]); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("Acorn Advanced Disc Filing System", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, wholePart, out _, null); + Assert.AreEqual(bootable[i], fs.XmlFsType.Bootable, testfiles[i]); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("Acorn Advanced Disc Filing System", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/AFFS.cs b/DiscImageChef.Tests/Filesystems/AFFS.cs index 7e389b3d..a7d7a7b6 100644 --- a/DiscImageChef.Tests/Filesystems/AFFS.cs +++ b/DiscImageChef.Tests/Filesystems/AFFS.cs @@ -61,27 +61,27 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "affs", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new ZZZRawImage(); + IMediaImage image = new ZZZRawImage(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - Filesystem fs = new AmigaDOSPlugin(); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + IFilesystem fs = new AmigaDOSPlugin(); Partition wholePart = new Partition { Name = "Whole device", - Length = image.ImageInfo.Sectors, - Size = image.ImageInfo.Sectors * image.ImageInfo.SectorSize + Length = image.Info.Sectors, + Size = image.Info.Sectors * image.Info.SectorSize }; Assert.AreEqual(true, fs.Identify(image, wholePart), testfiles[i]); - fs.GetInformation(image, wholePart, out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("Amiga FFS", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, wholePart, out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("Amiga FFS", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } @@ -109,14 +109,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "affs_mbr", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new AmigaDOSPlugin(); + IFilesystem fs = new AmigaDOSPlugin(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "0x2D" || partitions[j].Type == "0x2E") @@ -127,12 +127,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("Amiga FFS", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("Amiga FFS", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } @@ -160,14 +160,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "affs_mbr_rdb", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new AmigaDOSPlugin(); + IFilesystem fs = new AmigaDOSPlugin(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "\"DOS\\1\"" || partitions[j].Type == "\"DOS\\3\"") @@ -178,12 +178,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("Amiga FFS", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("Amiga FFS", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } @@ -220,14 +220,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "affs_rdb", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new AmigaDOSPlugin(); + IFilesystem fs = new AmigaDOSPlugin(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "\"DOS\\1\"" || partitions[j].Type == "\"DOS\\3\"" || @@ -239,12 +239,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("Amiga FFS", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("Amiga FFS", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/AFFS2.cs b/DiscImageChef.Tests/Filesystems/AFFS2.cs index 12425319..79e2afa1 100644 --- a/DiscImageChef.Tests/Filesystems/AFFS2.cs +++ b/DiscImageChef.Tests/Filesystems/AFFS2.cs @@ -59,14 +59,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "affs2_rdb", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new AmigaDOSPlugin(); + IFilesystem fs = new AmigaDOSPlugin(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "\"DOS\\7\"") @@ -77,12 +77,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("Amiga FFS2", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("Amiga FFS2", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/AFS.cs b/DiscImageChef.Tests/Filesystems/AFS.cs index b15692c3..8fec50a1 100644 --- a/DiscImageChef.Tests/Filesystems/AFS.cs +++ b/DiscImageChef.Tests/Filesystems/AFS.cs @@ -73,27 +73,27 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "afs", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new ZZZRawImage(); + IMediaImage image = new ZZZRawImage(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - Filesystem fs = new SysVfs(); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + IFilesystem fs = new SysVfs(); Partition wholePart = new Partition { Name = "Whole device", - Length = image.ImageInfo.Sectors, - Size = image.ImageInfo.Sectors * image.ImageInfo.SectorSize + Length = image.Info.Sectors, + Size = image.Info.Sectors * image.Info.SectorSize }; Assert.AreEqual(true, fs.Identify(image, wholePart), testfiles[i]); - fs.GetInformation(image, wholePart, out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual(type[i], fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, wholePart, out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual(type[i], fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } @@ -123,14 +123,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "afs_mbr", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new SysVfs(); + IFilesystem fs = new SysVfs(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "XENIX") @@ -141,12 +141,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual(type[i], fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual(type[i], fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/AOFS.cs b/DiscImageChef.Tests/Filesystems/AOFS.cs index 5316ba85..33619607 100644 --- a/DiscImageChef.Tests/Filesystems/AOFS.cs +++ b/DiscImageChef.Tests/Filesystems/AOFS.cs @@ -61,27 +61,27 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "aofs", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new ZZZRawImage(); + IMediaImage image = new ZZZRawImage(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - Filesystem fs = new AmigaDOSPlugin(); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + IFilesystem fs = new AmigaDOSPlugin(); Partition wholePart = new Partition { Name = "Whole device", - Length = image.ImageInfo.Sectors, - Size = image.ImageInfo.Sectors * image.ImageInfo.SectorSize + Length = image.Info.Sectors, + Size = image.Info.Sectors * image.Info.SectorSize }; Assert.AreEqual(true, fs.Identify(image, wholePart), testfiles[i]); - fs.GetInformation(image, wholePart, out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("Amiga OFS", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, wholePart, out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("Amiga OFS", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } @@ -109,14 +109,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "aofs_mbr", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new AmigaDOSPlugin(); + IFilesystem fs = new AmigaDOSPlugin(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "0x2C") @@ -127,12 +127,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("Amiga OFS", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("Amiga OFS", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } @@ -160,14 +160,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "aofs_mbr_rdb", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new AmigaDOSPlugin(); + IFilesystem fs = new AmigaDOSPlugin(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "\"DOS\\0\"") @@ -178,12 +178,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("Amiga OFS", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("Amiga OFS", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } @@ -212,14 +212,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "aofs_rdb", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new AmigaDOSPlugin(); + IFilesystem fs = new AmigaDOSPlugin(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "\"DOS\\0\"" || partitions[j].Type == "\"DOS\\2\"" || @@ -231,12 +231,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("Amiga OFS", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("Amiga OFS", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/Atheos.cs b/DiscImageChef.Tests/Filesystems/Atheos.cs index fe7d92b8..51b08f27 100644 --- a/DiscImageChef.Tests/Filesystems/Atheos.cs +++ b/DiscImageChef.Tests/Filesystems/Atheos.cs @@ -59,14 +59,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "atheos_mbr", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new AtheOS(); + IFilesystem fs = new AtheOS(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "0x2A") @@ -77,12 +77,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("AtheOS filesystem", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("AtheOS filesystem", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/BeFS.cs b/DiscImageChef.Tests/Filesystems/BeFS.cs index 68350749..427a759a 100644 --- a/DiscImageChef.Tests/Filesystems/BeFS.cs +++ b/DiscImageChef.Tests/Filesystems/BeFS.cs @@ -63,28 +63,28 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "befs", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new ZZZRawImage(); + IMediaImage image = new ZZZRawImage(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - Filesystem fs = new BeFS(); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + IFilesystem fs = new BeFS(); Partition wholePart = new Partition { Name = "Whole device", - Length = image.ImageInfo.Sectors, - Size = image.ImageInfo.Sectors * image.ImageInfo.SectorSize + Length = image.Info.Sectors, + Size = image.Info.Sectors * image.Info.SectorSize }; Assert.AreEqual(true, fs.Identify(image, wholePart), testfiles[i]); - fs.GetInformation(image, wholePart, out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("BeFS", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); - Assert.AreEqual(oemid[i], fs.XmlFSType.SystemIdentifier, testfiles[i]); + fs.GetInformation(image, wholePart, out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("BeFS", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); + Assert.AreEqual(oemid[i], fs.XmlFsType.SystemIdentifier, testfiles[i]); } } } @@ -114,14 +114,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "befs_apm", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new BeFS(); + IFilesystem fs = new BeFS(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "Be_BFS") @@ -132,13 +132,13 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("BeFS", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); - Assert.AreEqual(oemid[i], fs.XmlFSType.SystemIdentifier, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("BeFS", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); + Assert.AreEqual(oemid[i], fs.XmlFsType.SystemIdentifier, testfiles[i]); } } } @@ -166,14 +166,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "befs_gpt", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new BeFS(); + IFilesystem fs = new BeFS(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "Haiku BFS") @@ -184,12 +184,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("BeFS", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("BeFS", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } @@ -218,14 +218,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "befs_mbr", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new BeFS(); + IFilesystem fs = new BeFS(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "0xEB") @@ -236,12 +236,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("BeFS", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("BeFS", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/COHERENT.cs b/DiscImageChef.Tests/Filesystems/COHERENT.cs index 2d98112a..77b76f7d 100644 --- a/DiscImageChef.Tests/Filesystems/COHERENT.cs +++ b/DiscImageChef.Tests/Filesystems/COHERENT.cs @@ -68,27 +68,27 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "coherent", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new ZZZRawImage(); + IMediaImage image = new ZZZRawImage(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - Filesystem fs = new SysVfs(); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + IFilesystem fs = new SysVfs(); Partition wholePart = new Partition { Name = "Whole device", - Length = image.ImageInfo.Sectors, - Size = image.ImageInfo.Sectors * image.ImageInfo.SectorSize + Length = image.Info.Sectors, + Size = image.Info.Sectors * image.Info.SectorSize }; Assert.AreEqual(true, fs.Identify(image, wholePart), testfiles[i]); - fs.GetInformation(image, wholePart, out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual(type[i], fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, wholePart, out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual(type[i], fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } @@ -118,14 +118,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "coherent_mbr", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new SysVfs(); + IFilesystem fs = new SysVfs(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "0x09") @@ -136,12 +136,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual(type[i], fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual(type[i], fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/DTFS.cs b/DiscImageChef.Tests/Filesystems/DTFS.cs index 29039664..e4eb8c73 100644 --- a/DiscImageChef.Tests/Filesystems/DTFS.cs +++ b/DiscImageChef.Tests/Filesystems/DTFS.cs @@ -69,27 +69,27 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "dtfs", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new ZZZRawImage(); + IMediaImage image = new ZZZRawImage(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - Filesystem fs = new SysVfs(); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + IFilesystem fs = new SysVfs(); Partition wholePart = new Partition { Name = "Whole device", - Length = image.ImageInfo.Sectors, - Size = image.ImageInfo.Sectors * image.ImageInfo.SectorSize + Length = image.Info.Sectors, + Size = image.Info.Sectors * image.Info.SectorSize }; Assert.AreEqual(true, fs.Identify(image, wholePart), testfiles[i]); - fs.GetInformation(image, wholePart, out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual(type[i], fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, wholePart, out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual(type[i], fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } @@ -119,14 +119,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "dtfs_mbr", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new SysVfs(); + IFilesystem fs = new SysVfs(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "XENIX") @@ -137,12 +137,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual(type[i], fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual(type[i], fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/EAFS.cs b/DiscImageChef.Tests/Filesystems/EAFS.cs index 6800c502..a2826442 100644 --- a/DiscImageChef.Tests/Filesystems/EAFS.cs +++ b/DiscImageChef.Tests/Filesystems/EAFS.cs @@ -73,27 +73,27 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "eafs", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new ZZZRawImage(); + IMediaImage image = new ZZZRawImage(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - Filesystem fs = new SysVfs(); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + IFilesystem fs = new SysVfs(); Partition wholePart = new Partition { Name = "Whole device", - Length = image.ImageInfo.Sectors, - Size = image.ImageInfo.Sectors * image.ImageInfo.SectorSize + Length = image.Info.Sectors, + Size = image.Info.Sectors * image.Info.SectorSize }; Assert.AreEqual(true, fs.Identify(image, wholePart), testfiles[i]); - fs.GetInformation(image, wholePart, out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual(type[i], fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, wholePart, out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual(type[i], fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } @@ -123,14 +123,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "eafs_mbr", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new SysVfs(); + IFilesystem fs = new SysVfs(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "XENIX") @@ -141,12 +141,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual(type[i], fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual(type[i], fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/F2FS.cs b/DiscImageChef.Tests/Filesystems/F2FS.cs index 8528ddde..d6726f9e 100644 --- a/DiscImageChef.Tests/Filesystems/F2FS.cs +++ b/DiscImageChef.Tests/Filesystems/F2FS.cs @@ -60,15 +60,15 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "f2fs", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - PartitionPlugin parts = new MBR(); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + IPartition parts = new MBR(); Assert.AreEqual(true, parts.GetInformation(image, out List partitions, 0), testfiles[i]); - Filesystem fs = new F2FS(); + IFilesystem fs = new F2FS(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "0x83") @@ -79,12 +79,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("F2FS filesystem", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("F2FS filesystem", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/FAT12.cs b/DiscImageChef.Tests/Filesystems/FAT12.cs index a7b83112..8b1dfe61 100644 --- a/DiscImageChef.Tests/Filesystems/FAT12.cs +++ b/DiscImageChef.Tests/Filesystems/FAT12.cs @@ -1710,28 +1710,28 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "fat12", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new ZZZRawImage(); + IMediaImage image = new ZZZRawImage(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - Filesystem fs = new FAT(); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + IFilesystem fs = new FAT(); Partition wholePart = new Partition { Name = "Whole device", - Length = image.ImageInfo.Sectors, - Size = image.ImageInfo.Sectors * image.ImageInfo.SectorSize + Length = image.Info.Sectors, + Size = image.Info.Sectors * image.Info.SectorSize }; Assert.AreEqual(true, fs.Identify(image, wholePart), testfiles[i]); - fs.GetInformation(image, wholePart, out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("FAT12", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); - Assert.AreEqual(oemid[i], fs.XmlFSType.SystemIdentifier, testfiles[i]); + fs.GetInformation(image, wholePart, out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("FAT12", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); + Assert.AreEqual(oemid[i], fs.XmlFsType.SystemIdentifier, testfiles[i]); } } } @@ -1761,14 +1761,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "fat12_apm", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new FAT(); + IFilesystem fs = new FAT(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "DOS_FAT_12") @@ -1779,13 +1779,13 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("FAT12", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); - Assert.AreEqual(oemid[i], fs.XmlFSType.SystemIdentifier, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("FAT12", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); + Assert.AreEqual(oemid[i], fs.XmlFsType.SystemIdentifier, testfiles[i]); } } } @@ -1815,14 +1815,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "fat12_gpt", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new FAT(); + IFilesystem fs = new FAT(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "Microsoft Basic data") @@ -1833,13 +1833,13 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("FAT12", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); - Assert.AreEqual(oemid[i], fs.XmlFSType.SystemIdentifier, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("FAT12", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); + Assert.AreEqual(oemid[i], fs.XmlFsType.SystemIdentifier, testfiles[i]); } } } @@ -1937,22 +1937,22 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "fat12_mbr", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new FAT(); + IFilesystem fs = new FAT(); Assert.AreEqual(true, fs.Identify(image, partitions[0]), testfiles[i]); - fs.GetInformation(image, partitions[0], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("FAT12", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); - Assert.AreEqual(oemid[i], fs.XmlFSType.SystemIdentifier, testfiles[i]); + fs.GetInformation(image, partitions[0], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("FAT12", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); + Assert.AreEqual(oemid[i], fs.XmlFsType.SystemIdentifier, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/FAT16.cs b/DiscImageChef.Tests/Filesystems/FAT16.cs index 979ea8f4..39b8252d 100644 --- a/DiscImageChef.Tests/Filesystems/FAT16.cs +++ b/DiscImageChef.Tests/Filesystems/FAT16.cs @@ -117,28 +117,28 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "fat16", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new ZZZRawImage(); + IMediaImage image = new ZZZRawImage(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - Filesystem fs = new FAT(); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + IFilesystem fs = new FAT(); Partition wholePart = new Partition { Name = "Whole device", - Length = image.ImageInfo.Sectors, - Size = image.ImageInfo.Sectors * image.ImageInfo.SectorSize + Length = image.Info.Sectors, + Size = image.Info.Sectors * image.Info.SectorSize }; Assert.AreEqual(true, fs.Identify(image, wholePart), testfiles[i]); - fs.GetInformation(image, wholePart, out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("FAT16", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); - Assert.AreEqual(oemid[i], fs.XmlFSType.SystemIdentifier, testfiles[i]); + fs.GetInformation(image, wholePart, out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("FAT16", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); + Assert.AreEqual(oemid[i], fs.XmlFsType.SystemIdentifier, testfiles[i]); } } } @@ -168,14 +168,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "fat16_apm", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new FAT(); + IFilesystem fs = new FAT(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "DOS_FAT_16") @@ -186,13 +186,13 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("FAT16", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); - Assert.AreEqual(oemid[i], fs.XmlFSType.SystemIdentifier, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("FAT16", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); + Assert.AreEqual(oemid[i], fs.XmlFsType.SystemIdentifier, testfiles[i]); } } } @@ -222,14 +222,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "fat16_atari", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new FAT(); + IFilesystem fs = new FAT(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "GEM" || partitions[j].Type == "BGM") @@ -240,13 +240,13 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("FAT16", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); - Assert.AreEqual(oemid[i], fs.XmlFSType.SystemIdentifier, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("FAT16", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); + Assert.AreEqual(oemid[i], fs.XmlFsType.SystemIdentifier, testfiles[i]); } } } @@ -276,14 +276,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "fat16_gpt", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new FAT(); + IFilesystem fs = new FAT(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "Microsoft Basic data") @@ -294,13 +294,13 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("FAT16", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); - Assert.AreEqual(oemid[i], fs.XmlFSType.SystemIdentifier, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("FAT16", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); + Assert.AreEqual(oemid[i], fs.XmlFsType.SystemIdentifier, testfiles[i]); } } } @@ -400,22 +400,22 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "fat16_mbr", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new FAT(); + IFilesystem fs = new FAT(); Assert.AreEqual(true, fs.Identify(image, partitions[0]), testfiles[i]); - fs.GetInformation(image, partitions[0], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("FAT16", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); - Assert.AreEqual(oemid[i], fs.XmlFSType.SystemIdentifier, testfiles[i]); + fs.GetInformation(image, partitions[0], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("FAT16", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); + Assert.AreEqual(oemid[i], fs.XmlFsType.SystemIdentifier, testfiles[i]); } } } @@ -445,14 +445,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "fat16_rdb", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new FAT(); + IFilesystem fs = new FAT(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "0x06") @@ -463,13 +463,13 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("FAT16", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); - Assert.AreEqual(oemid[i], fs.XmlFSType.SystemIdentifier, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("FAT16", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); + Assert.AreEqual(oemid[i], fs.XmlFsType.SystemIdentifier, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/FAT32.cs b/DiscImageChef.Tests/Filesystems/FAT32.cs index e0f16e66..81edd004 100644 --- a/DiscImageChef.Tests/Filesystems/FAT32.cs +++ b/DiscImageChef.Tests/Filesystems/FAT32.cs @@ -61,14 +61,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "fat32_apm", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new FAT(); + IFilesystem fs = new FAT(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "DOS_FAT_32") @@ -79,13 +79,13 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("FAT32", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); - Assert.AreEqual(oemid[i], fs.XmlFSType.SystemIdentifier, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("FAT32", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); + Assert.AreEqual(oemid[i], fs.XmlFsType.SystemIdentifier, testfiles[i]); } } } @@ -115,14 +115,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "fat32_gpt", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new FAT(); + IFilesystem fs = new FAT(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "Microsoft Basic data") @@ -133,13 +133,13 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("FAT32", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); - Assert.AreEqual(oemid[i], fs.XmlFSType.SystemIdentifier, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("FAT32", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); + Assert.AreEqual(oemid[i], fs.XmlFsType.SystemIdentifier, testfiles[i]); } } } @@ -203,22 +203,22 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "fat32_mbr", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new FAT(); + IFilesystem fs = new FAT(); Assert.AreEqual(true, fs.Identify(image, partitions[0]), testfiles[i]); - fs.GetInformation(image, partitions[0], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("FAT32", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); - Assert.AreEqual(oemid[i], fs.XmlFSType.SystemIdentifier, testfiles[i]); + fs.GetInformation(image, partitions[0], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("FAT32", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); + Assert.AreEqual(oemid[i], fs.XmlFsType.SystemIdentifier, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/HAMMER.cs b/DiscImageChef.Tests/Filesystems/HAMMER.cs index 18332d2b..3a3e90e5 100644 --- a/DiscImageChef.Tests/Filesystems/HAMMER.cs +++ b/DiscImageChef.Tests/Filesystems/HAMMER.cs @@ -60,14 +60,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "hammer_mbr", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new HAMMER(); + IFilesystem fs = new HAMMER(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "Hammer") @@ -78,12 +78,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("HAMMER", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("HAMMER", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/HFS.cs b/DiscImageChef.Tests/Filesystems/HFS.cs index 6e3cc6a3..d8e18daf 100644 --- a/DiscImageChef.Tests/Filesystems/HFS.cs +++ b/DiscImageChef.Tests/Filesystems/HFS.cs @@ -73,27 +73,27 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "hfs", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new ZZZRawImage(); + IMediaImage image = new ZZZRawImage(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - Filesystem fs = new AppleHFS(); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + IFilesystem fs = new AppleHFS(); Partition wholePart = new Partition { Name = "Whole device", - Length = image.ImageInfo.Sectors, - Size = image.ImageInfo.Sectors * image.ImageInfo.SectorSize + Length = image.Info.Sectors, + Size = image.Info.Sectors * image.Info.SectorSize }; Assert.AreEqual(true, fs.Identify(image, wholePart), testfiles[i]); - fs.GetInformation(image, wholePart, out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("HFS", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, wholePart, out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("HFS", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } @@ -162,14 +162,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "hfs_apm", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new AppleHFS(); + IFilesystem fs = new AppleHFS(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "Apple_HFS") @@ -180,12 +180,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("HFS", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("HFS", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } @@ -219,14 +219,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "hfs_cdrom", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new ZZZRawImage(); + IMediaImage image = new ZZZRawImage(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new AppleHFS(); + IFilesystem fs = new AppleHFS(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "Apple_HFS") @@ -237,12 +237,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("HFS", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("HFS", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } @@ -273,14 +273,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "hfs_mbr", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new AppleHFS(); + IFilesystem fs = new AppleHFS(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "0xAF") @@ -291,12 +291,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("HFS", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("HFS", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } @@ -324,14 +324,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "hfs_rdb", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new AppleHFS(); + IFilesystem fs = new AppleHFS(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "\"RES\\86\"") @@ -342,12 +342,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("HFS", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("HFS", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/HFSPlus.cs b/DiscImageChef.Tests/Filesystems/HFSPlus.cs index caf960e2..e01a4bdb 100644 --- a/DiscImageChef.Tests/Filesystems/HFSPlus.cs +++ b/DiscImageChef.Tests/Filesystems/HFSPlus.cs @@ -95,14 +95,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "hfsplus_apm", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new AppleHFSPlus(); + IFilesystem fs = new AppleHFSPlus(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "Apple_HFS") @@ -113,13 +113,13 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("HFS+", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); - Assert.AreEqual(oemid[i], fs.XmlFSType.SystemIdentifier, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("HFS+", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); + Assert.AreEqual(oemid[i], fs.XmlFsType.SystemIdentifier, testfiles[i]); } } } @@ -149,14 +149,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "hfsplus_gpt", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new AppleHFSPlus(); + IFilesystem fs = new AppleHFSPlus(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "Apple HFS") @@ -167,13 +167,13 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("HFS+", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); - Assert.AreEqual(oemid[i], fs.XmlFSType.SystemIdentifier, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("HFS+", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); + Assert.AreEqual(oemid[i], fs.XmlFsType.SystemIdentifier, testfiles[i]); } } } @@ -216,14 +216,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "hfsplus_mbr", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new AppleHFSPlus(); + IFilesystem fs = new AppleHFSPlus(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "0xAF") @@ -234,13 +234,13 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("HFS+", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); - Assert.AreEqual(oemid[i], fs.XmlFSType.SystemIdentifier, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("HFS+", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); + Assert.AreEqual(oemid[i], fs.XmlFsType.SystemIdentifier, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/HFSX.cs b/DiscImageChef.Tests/Filesystems/HFSX.cs index 62067059..d9a85ebc 100644 --- a/DiscImageChef.Tests/Filesystems/HFSX.cs +++ b/DiscImageChef.Tests/Filesystems/HFSX.cs @@ -69,14 +69,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "hfsx_apm", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new AppleHFSPlus(); + IFilesystem fs = new AppleHFSPlus(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "Apple_HFSX") @@ -87,13 +87,13 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("HFSX", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); - Assert.AreEqual(oemid[i], fs.XmlFSType.SystemIdentifier, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("HFSX", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); + Assert.AreEqual(oemid[i], fs.XmlFsType.SystemIdentifier, testfiles[i]); } } } @@ -123,14 +123,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "hfsx_gpt", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new AppleHFSPlus(); + IFilesystem fs = new AppleHFSPlus(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "Apple HFS") @@ -141,13 +141,13 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("HFSX", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); - Assert.AreEqual(oemid[i], fs.XmlFSType.SystemIdentifier, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("HFSX", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); + Assert.AreEqual(oemid[i], fs.XmlFsType.SystemIdentifier, testfiles[i]); } } } @@ -182,14 +182,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "hfsx_mbr", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new AppleHFSPlus(); + IFilesystem fs = new AppleHFSPlus(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "0xAF") @@ -200,13 +200,13 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("HFSX", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); - Assert.AreEqual(oemid[i], fs.XmlFSType.SystemIdentifier, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("HFSX", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); + Assert.AreEqual(oemid[i], fs.XmlFsType.SystemIdentifier, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/HPFS.cs b/DiscImageChef.Tests/Filesystems/HPFS.cs index 8adcd7e0..942df209 100644 --- a/DiscImageChef.Tests/Filesystems/HPFS.cs +++ b/DiscImageChef.Tests/Filesystems/HPFS.cs @@ -80,22 +80,22 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "hpfs", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new HPFS(); + IFilesystem fs = new HPFS(); Assert.AreEqual(true, fs.Identify(image, partitions[0]), testfiles[i]); - fs.GetInformation(image, partitions[0], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("HPFS", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); - Assert.AreEqual(oemid[i], fs.XmlFSType.SystemIdentifier, testfiles[i]); + fs.GetInformation(image, partitions[0], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("HPFS", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); + Assert.AreEqual(oemid[i], fs.XmlFsType.SystemIdentifier, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/HTFS.cs b/DiscImageChef.Tests/Filesystems/HTFS.cs index 83c67fc9..2f32b0ee 100644 --- a/DiscImageChef.Tests/Filesystems/HTFS.cs +++ b/DiscImageChef.Tests/Filesystems/HTFS.cs @@ -69,27 +69,27 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "htfs", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new ZZZRawImage(); + IMediaImage image = new ZZZRawImage(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - Filesystem fs = new SysVfs(); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + IFilesystem fs = new SysVfs(); Partition wholePart = new Partition { Name = "Whole device", - Length = image.ImageInfo.Sectors, - Size = image.ImageInfo.Sectors * image.ImageInfo.SectorSize + Length = image.Info.Sectors, + Size = image.Info.Sectors * image.Info.SectorSize }; Assert.AreEqual(true, fs.Identify(image, wholePart), testfiles[i]); - fs.GetInformation(image, wholePart, out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual(type[i], fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, wholePart, out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual(type[i], fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } @@ -119,14 +119,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "htfs_mbr", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new SysVfs(); + IFilesystem fs = new SysVfs(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "XENIX") @@ -137,12 +137,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual(type[i], fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual(type[i], fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/ISO9660.cs b/DiscImageChef.Tests/Filesystems/ISO9660.cs index d6952988..3c92bea7 100644 --- a/DiscImageChef.Tests/Filesystems/ISO9660.cs +++ b/DiscImageChef.Tests/Filesystems/ISO9660.cs @@ -120,29 +120,29 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "iso9660", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new ZZZRawImage(); + IMediaImage image = new ZZZRawImage(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - Filesystem fs = new ISO9660(); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + IFilesystem fs = new ISO9660(); Partition wholePart = new Partition { Name = "Whole device", - Length = image.ImageInfo.Sectors, - Size = image.ImageInfo.Sectors * image.ImageInfo.SectorSize + Length = image.Info.Sectors, + Size = image.Info.Sectors * image.Info.SectorSize }; Assert.AreEqual(true, fs.Identify(image, wholePart), testfiles[i]); - fs.GetInformation(image, wholePart, out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("ISO9660", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); - Assert.AreEqual(sysid[i], fs.XmlFSType.SystemIdentifier, testfiles[i]); - Assert.AreEqual(appid[i], fs.XmlFSType.ApplicationIdentifier, testfiles[i]); + fs.GetInformation(image, wholePart, out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("ISO9660", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); + Assert.AreEqual(sysid[i], fs.XmlFsType.SystemIdentifier, testfiles[i]); + Assert.AreEqual(appid[i], fs.XmlFsType.ApplicationIdentifier, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/JFS2.cs b/DiscImageChef.Tests/Filesystems/JFS2.cs index e0f5cdef..5865925d 100644 --- a/DiscImageChef.Tests/Filesystems/JFS2.cs +++ b/DiscImageChef.Tests/Filesystems/JFS2.cs @@ -60,14 +60,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "jfs2", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new JFS(); + IFilesystem fs = new JFS(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "0x83" || partitions[j].Type == "0x07") @@ -78,12 +78,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("JFS filesystem", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("JFS filesystem", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/LisaFS.cs b/DiscImageChef.Tests/Filesystems/LisaFS.cs index e7318f96..5ad1f954 100644 --- a/DiscImageChef.Tests/Filesystems/LisaFS.cs +++ b/DiscImageChef.Tests/Filesystems/LisaFS.cs @@ -85,28 +85,28 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "lisafs", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new DiskCopy42(); + IMediaImage image = new DiskCopy42(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - Filesystem fs = new LisaFS(); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + IFilesystem fs = new LisaFS(); Partition wholePart = new Partition { Name = "Whole device", - Length = image.ImageInfo.Sectors, - Size = image.ImageInfo.Sectors * image.ImageInfo.SectorSize + Length = image.Info.Sectors, + Size = image.Info.Sectors * image.Info.SectorSize }; Assert.AreEqual(true, fs.Identify(image, wholePart), testfiles[i]); - fs.GetInformation(image, wholePart, out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("LisaFS", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); - Assert.AreEqual(oemid[i], fs.XmlFSType.SystemIdentifier, testfiles[i]); + fs.GetInformation(image, wholePart, out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("LisaFS", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); + Assert.AreEqual(oemid[i], fs.XmlFsType.SystemIdentifier, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/Locus.cs b/DiscImageChef.Tests/Filesystems/Locus.cs index 2a9fab12..e4b15912 100644 --- a/DiscImageChef.Tests/Filesystems/Locus.cs +++ b/DiscImageChef.Tests/Filesystems/Locus.cs @@ -62,28 +62,28 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "locus", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new ZZZRawImage(); + IMediaImage image = new ZZZRawImage(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - Filesystem fs = new DiscImageChef.Filesystems.Locus(); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + IFilesystem fs = new DiscImageChef.Filesystems.Locus(); Partition wholePart = new Partition { Name = "Whole device", - Length = image.ImageInfo.Sectors, - Size = image.ImageInfo.Sectors * image.ImageInfo.SectorSize + Length = image.Info.Sectors, + Size = image.Info.Sectors * image.Info.SectorSize }; Assert.AreEqual(true, fs.Identify(image, wholePart), testfiles[i]); - fs.GetInformation(image, wholePart, out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("Locus filesystem", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); - Assert.AreEqual(oemid[i], fs.XmlFSType.SystemIdentifier, testfiles[i]); + fs.GetInformation(image, wholePart, out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("Locus filesystem", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); + Assert.AreEqual(oemid[i], fs.XmlFsType.SystemIdentifier, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/MFS.cs b/DiscImageChef.Tests/Filesystems/MFS.cs index 247a1fba..fb8518b2 100644 --- a/DiscImageChef.Tests/Filesystems/MFS.cs +++ b/DiscImageChef.Tests/Filesystems/MFS.cs @@ -69,27 +69,27 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "mfs", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new ZZZRawImage(); + IMediaImage image = new ZZZRawImage(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - Filesystem fs = new AppleMFS(); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + IFilesystem fs = new AppleMFS(); Partition wholePart = new Partition { Name = "Whole device", - Length = image.ImageInfo.Sectors, - Size = image.ImageInfo.Sectors * image.ImageInfo.SectorSize + Length = image.Info.Sectors, + Size = image.Info.Sectors * image.Info.SectorSize }; Assert.AreEqual(true, fs.Identify(image, wholePart), testfiles[i]); - fs.GetInformation(image, wholePart, out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("MFS", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, wholePart, out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("MFS", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/MINIX.cs b/DiscImageChef.Tests/Filesystems/MINIX.cs index 389ab80a..000c1ee2 100644 --- a/DiscImageChef.Tests/Filesystems/MINIX.cs +++ b/DiscImageChef.Tests/Filesystems/MINIX.cs @@ -64,25 +64,25 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "minixv1", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new ZZZRawImage(); + IMediaImage image = new ZZZRawImage(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - Filesystem fs = new MinixFS(); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + IFilesystem fs = new MinixFS(); Partition wholePart = new Partition { Name = "Whole device", - Length = image.ImageInfo.Sectors, - Size = image.ImageInfo.Sectors * image.ImageInfo.SectorSize + Length = image.Info.Sectors, + Size = image.Info.Sectors * image.Info.SectorSize }; Assert.AreEqual(true, fs.Identify(image, wholePart), testfiles[i]); - fs.GetInformation(image, wholePart, out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual(types[i], fs.XmlFSType.Type, testfiles[i]); + fs.GetInformation(image, wholePart, out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual(types[i], fs.XmlFsType.Type, testfiles[i]); } } } @@ -108,14 +108,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "minixv1_mbr", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new MinixFS(); + IFilesystem fs = new MinixFS(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "0x80" || partitions[j].Type == "0x81" || partitions[j].Type == "MINIX") @@ -126,10 +126,10 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual(types[i], fs.XmlFSType.Type, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual(types[i], fs.XmlFsType.Type, testfiles[i]); } } } @@ -162,25 +162,25 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "minixv2", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new ZZZRawImage(); + IMediaImage image = new ZZZRawImage(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - Filesystem fs = new MinixFS(); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + IFilesystem fs = new MinixFS(); Partition wholePart = new Partition { Name = "Whole device", - Length = image.ImageInfo.Sectors, - Size = image.ImageInfo.Sectors * image.ImageInfo.SectorSize + Length = image.Info.Sectors, + Size = image.Info.Sectors * image.Info.SectorSize }; Assert.AreEqual(true, fs.Identify(image, wholePart), testfiles[i]); - fs.GetInformation(image, wholePart, out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual(types[i], fs.XmlFSType.Type, testfiles[i]); + fs.GetInformation(image, wholePart, out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual(types[i], fs.XmlFsType.Type, testfiles[i]); } } } @@ -206,14 +206,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "minixv2_mbr", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new MinixFS(); + IFilesystem fs = new MinixFS(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "0x81" || partitions[j].Type == "MINIX") @@ -224,10 +224,10 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual(types[i], fs.XmlFSType.Type, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual(types[i], fs.XmlFsType.Type, testfiles[i]); } } } @@ -260,25 +260,25 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "minixv3", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new ZZZRawImage(); + IMediaImage image = new ZZZRawImage(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - Filesystem fs = new MinixFS(); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + IFilesystem fs = new MinixFS(); Partition wholePart = new Partition { Name = "Whole device", - Length = image.ImageInfo.Sectors, - Size = image.ImageInfo.Sectors * image.ImageInfo.SectorSize + Length = image.Info.Sectors, + Size = image.Info.Sectors * image.Info.SectorSize }; Assert.AreEqual(true, fs.Identify(image, wholePart), testfiles[i]); - fs.GetInformation(image, wholePart, out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual(types[i], fs.XmlFSType.Type, testfiles[i]); + fs.GetInformation(image, wholePart, out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual(types[i], fs.XmlFsType.Type, testfiles[i]); } } } @@ -304,14 +304,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "minixv3_mbr", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new MinixFS(); + IFilesystem fs = new MinixFS(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "0x81" || partitions[j].Type == "MINIX") @@ -322,10 +322,10 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual(types[i], fs.XmlFSType.Type, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual(types[i], fs.XmlFsType.Type, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/NILFS2.cs b/DiscImageChef.Tests/Filesystems/NILFS2.cs index 52d1b859..41ff8723 100644 --- a/DiscImageChef.Tests/Filesystems/NILFS2.cs +++ b/DiscImageChef.Tests/Filesystems/NILFS2.cs @@ -59,14 +59,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "nilfs2", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new NILFS2(); + IFilesystem fs = new NILFS2(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "0x83") @@ -77,12 +77,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("NILFS2 filesystem", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("NILFS2 filesystem", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/NTFS.cs b/DiscImageChef.Tests/Filesystems/NTFS.cs index 55dd4db7..845d23fb 100644 --- a/DiscImageChef.Tests/Filesystems/NTFS.cs +++ b/DiscImageChef.Tests/Filesystems/NTFS.cs @@ -61,14 +61,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "ntfs_gpt", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new NTFS(); + IFilesystem fs = new NTFS(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "Microsoft Basic data") @@ -79,13 +79,13 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("NTFS", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); - Assert.AreEqual(oemid[i], fs.XmlFSType.SystemIdentifier, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("NTFS", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); + Assert.AreEqual(oemid[i], fs.XmlFsType.SystemIdentifier, testfiles[i]); } } } @@ -123,14 +123,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "ntfs_mbr", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new NTFS(); + IFilesystem fs = new NTFS(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "0x07" || @@ -143,13 +143,13 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("NTFS", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); - Assert.AreEqual(oemid[i], fs.XmlFSType.SystemIdentifier, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("NTFS", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); + Assert.AreEqual(oemid[i], fs.XmlFsType.SystemIdentifier, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/PFS3.cs b/DiscImageChef.Tests/Filesystems/PFS3.cs index 33b2038e..6cfd016d 100644 --- a/DiscImageChef.Tests/Filesystems/PFS3.cs +++ b/DiscImageChef.Tests/Filesystems/PFS3.cs @@ -61,14 +61,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "pfs3", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new PFS(); + IFilesystem fs = new PFS(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "\"PFS\\1\"") @@ -79,13 +79,13 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("PFS v3", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); - Assert.AreEqual(oemid[i], fs.XmlFSType.SystemIdentifier, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("PFS v3", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); + Assert.AreEqual(oemid[i], fs.XmlFsType.SystemIdentifier, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/ProDOS.cs b/DiscImageChef.Tests/Filesystems/ProDOS.cs index 6e3a67b1..71c3c9b1 100644 --- a/DiscImageChef.Tests/Filesystems/ProDOS.cs +++ b/DiscImageChef.Tests/Filesystems/ProDOS.cs @@ -67,14 +67,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "prodos_apm", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new ProDOSPlugin(); + IFilesystem fs = new ProDOSPlugin(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "Apple_ProDOS") @@ -85,12 +85,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("ProDOS", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("ProDOS", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/QNX4.cs b/DiscImageChef.Tests/Filesystems/QNX4.cs index 3f019a66..babc4821 100644 --- a/DiscImageChef.Tests/Filesystems/QNX4.cs +++ b/DiscImageChef.Tests/Filesystems/QNX4.cs @@ -59,25 +59,25 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "qnx4", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new ZZZRawImage(); + IMediaImage image = new ZZZRawImage(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - Filesystem fs = new QNX4(); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + IFilesystem fs = new QNX4(); Partition wholePart = new Partition { Name = "Whole device", - Length = image.ImageInfo.Sectors, - Size = image.ImageInfo.Sectors * image.ImageInfo.SectorSize + Length = image.Info.Sectors, + Size = image.Info.Sectors * image.Info.SectorSize }; Assert.AreEqual(true, fs.Identify(image, wholePart), testfiles[i]); - fs.GetInformation(image, wholePart, out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("QNX4 filesystem", fs.XmlFSType.Type, testfiles[i]); + fs.GetInformation(image, wholePart, out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("QNX4 filesystem", fs.XmlFsType.Type, testfiles[i]); } } } @@ -101,14 +101,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "qnx4_mbr", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new QNX4(); + IFilesystem fs = new QNX4(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "0x4D") @@ -119,10 +119,10 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("QNX4 filesystem", fs.XmlFSType.Type, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("QNX4 filesystem", fs.XmlFsType.Type, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/ReFS.cs b/DiscImageChef.Tests/Filesystems/ReFS.cs index 006dda32..daaaa69a 100644 --- a/DiscImageChef.Tests/Filesystems/ReFS.cs +++ b/DiscImageChef.Tests/Filesystems/ReFS.cs @@ -61,12 +61,12 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "refs_mbr", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); int part = -1; for(int j = 0; j < partitions.Count; j++) diff --git a/DiscImageChef.Tests/Filesystems/Reiser3.cs b/DiscImageChef.Tests/Filesystems/Reiser3.cs index 89756b25..793b4c10 100644 --- a/DiscImageChef.Tests/Filesystems/Reiser3.cs +++ b/DiscImageChef.Tests/Filesystems/Reiser3.cs @@ -57,14 +57,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "reiser3", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new Reiser(); + IFilesystem fs = new Reiser(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "0x83") @@ -75,10 +75,10 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual(reiserversion[i], fs.XmlFSType.Type, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual(reiserversion[i], fs.XmlFsType.Type, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/Reiser4.cs b/DiscImageChef.Tests/Filesystems/Reiser4.cs index 780e6176..88a19a62 100644 --- a/DiscImageChef.Tests/Filesystems/Reiser4.cs +++ b/DiscImageChef.Tests/Filesystems/Reiser4.cs @@ -59,14 +59,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "reiser4", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new DiscImageChef.Filesystems.Reiser4(); + IFilesystem fs = new DiscImageChef.Filesystems.Reiser4(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "0x83") @@ -77,12 +77,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("Reiser 4 filesystem", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("Reiser 4 filesystem", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/SFS.cs b/DiscImageChef.Tests/Filesystems/SFS.cs index 2f3c9132..a3dbf895 100644 --- a/DiscImageChef.Tests/Filesystems/SFS.cs +++ b/DiscImageChef.Tests/Filesystems/SFS.cs @@ -59,14 +59,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "sfs_mbr", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new SFS(); + IFilesystem fs = new SFS(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "0x2F") @@ -77,12 +77,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("SmartFileSystem", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("SmartFileSystem", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } @@ -110,14 +110,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "sfs_mbr_rdb", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new SFS(); + IFilesystem fs = new SFS(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "\"SFS\\0\"") @@ -128,12 +128,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("SmartFileSystem", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("SmartFileSystem", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } @@ -161,14 +161,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "sfs_rdb", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new SFS(); + IFilesystem fs = new SFS(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "\"SFS\\0\"" || partitions[j].Type == "\"SFS\\2\"") @@ -179,12 +179,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("SmartFileSystem", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("SmartFileSystem", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/SysV.cs b/DiscImageChef.Tests/Filesystems/SysV.cs index fd48d77c..f156c455 100644 --- a/DiscImageChef.Tests/Filesystems/SysV.cs +++ b/DiscImageChef.Tests/Filesystems/SysV.cs @@ -74,27 +74,27 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "s5fs", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new ZZZRawImage(); + IMediaImage image = new ZZZRawImage(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - Filesystem fs = new SysVfs(); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + IFilesystem fs = new SysVfs(); Partition wholePart = new Partition { Name = "Whole device", - Length = image.ImageInfo.Sectors, - Size = image.ImageInfo.Sectors * image.ImageInfo.SectorSize + Length = image.Info.Sectors, + Size = image.Info.Sectors * image.Info.SectorSize }; Assert.AreEqual(true, fs.Identify(image, wholePart), testfiles[i]); - fs.GetInformation(image, wholePart, out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual(type[i], fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, wholePart, out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual(type[i], fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } @@ -125,14 +125,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "s5fs_mbr", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new SysVfs(); + IFilesystem fs = new SysVfs(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "UNIX: /usr" || partitions[j].Type == "XENIX") @@ -143,12 +143,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual(type[i], fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual(type[i], fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } @@ -178,14 +178,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "s5fs_rdb", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new SysVfs(); + IFilesystem fs = new SysVfs(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "\"UNI\\1\"") @@ -196,12 +196,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual(type[i], fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual(type[i], fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/UDF.cs b/DiscImageChef.Tests/Filesystems/UDF.cs index 30728256..00b47997 100644 --- a/DiscImageChef.Tests/Filesystems/UDF.cs +++ b/DiscImageChef.Tests/Filesystems/UDF.cs @@ -99,27 +99,27 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "udf", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - Filesystem fs = new UDF(); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + IFilesystem fs = new UDF(); Partition wholePart = new Partition { Name = "Whole device", - Length = image.ImageInfo.Sectors, - Size = image.ImageInfo.Sectors * image.ImageInfo.SectorSize + Length = image.Info.Sectors, + Size = image.Info.Sectors * image.Info.SectorSize }; Assert.AreEqual(true, fs.Identify(image, wholePart), testfiles[i]); - fs.GetInformation(image, wholePart, out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual(udfversion[i], fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSetIdentifier, testfiles[i]); - Assert.AreEqual(oemid[i], fs.XmlFSType.SystemIdentifier, testfiles[i]); + fs.GetInformation(image, wholePart, out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual(udfversion[i], fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSetIdentifier, testfiles[i]); + Assert.AreEqual(oemid[i], fs.XmlFsType.SystemIdentifier, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/UFS.cs b/DiscImageChef.Tests/Filesystems/UFS.cs index 61e97a66..4ea97179 100644 --- a/DiscImageChef.Tests/Filesystems/UFS.cs +++ b/DiscImageChef.Tests/Filesystems/UFS.cs @@ -72,27 +72,27 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "ufs", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new ZZZRawImage(); + IMediaImage image = new ZZZRawImage(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - Filesystem fs = new FFSPlugin(); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + IFilesystem fs = new FFSPlugin(); Partition wholePart = new Partition { Name = "Whole device", - Length = image.ImageInfo.Sectors, - Size = image.ImageInfo.Sectors * image.ImageInfo.SectorSize + Length = image.Info.Sectors, + Size = image.Info.Sectors * image.Info.SectorSize }; Assert.AreEqual(true, fs.Identify(image, wholePart), testfiles[i]); - fs.GetInformation(image, wholePart, out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual(type[i], fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, wholePart, out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual(type[i], fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } @@ -130,14 +130,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "ufs_apm", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new FFSPlugin(); + IFilesystem fs = new FFSPlugin(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "Apple_UFS") @@ -148,12 +148,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual(type[i], fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual(type[i], fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } @@ -224,14 +224,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "ufs_mbr", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new FFSPlugin(); + IFilesystem fs = new FFSPlugin(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "0x63" || partitions[j].Type == "0xA8" || partitions[j].Type == "0xA5" || @@ -244,12 +244,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual(type[i], fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual(type[i], fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } @@ -283,14 +283,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "ufs_next", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new FFSPlugin(); + IFilesystem fs = new FFSPlugin(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "4.3BSD" || partitions[j].Type == "4.4BSD") @@ -301,12 +301,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual(type[i], fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual(type[i], fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } @@ -342,14 +342,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "ufs_next", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new ZZZRawImage(); + IMediaImage image = new ZZZRawImage(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new FFSPlugin(); + IFilesystem fs = new FFSPlugin(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "4.3BSD" || partitions[j].Type == "4.4BSD") @@ -360,12 +360,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual(type[i], fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual(type[i], fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } @@ -395,14 +395,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "ufs_rdb", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new FFSPlugin(); + IFilesystem fs = new FFSPlugin(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "\"UNI\\2\"") @@ -413,12 +413,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual(type[i], fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual(type[i], fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } @@ -448,14 +448,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "ufs_suni86", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new FFSPlugin(); + IFilesystem fs = new FFSPlugin(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "Replacement sectors") @@ -466,12 +466,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual(type[i], fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual(type[i], fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/UNIXBFS.cs b/DiscImageChef.Tests/Filesystems/UNIXBFS.cs index 3cb260f9..5c445141 100644 --- a/DiscImageChef.Tests/Filesystems/UNIXBFS.cs +++ b/DiscImageChef.Tests/Filesystems/UNIXBFS.cs @@ -67,26 +67,26 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "unixbfs", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new ZZZRawImage(); + IMediaImage image = new ZZZRawImage(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - Filesystem fs = new BFS(); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + IFilesystem fs = new BFS(); Partition wholePart = new Partition { Name = "Whole device", - Length = image.ImageInfo.Sectors, - Size = image.ImageInfo.Sectors * image.ImageInfo.SectorSize + Length = image.Info.Sectors, + Size = image.Info.Sectors * image.Info.SectorSize }; Assert.AreEqual(true, fs.Identify(image, wholePart), testfiles[i]); - fs.GetInformation(image, wholePart, out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("BFS", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); + fs.GetInformation(image, wholePart, out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("BFS", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); } } } @@ -112,14 +112,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "unixbfs_mbr", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new BFS(); + IFilesystem fs = new BFS(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "0x83") @@ -130,11 +130,11 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("BFS", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("BFS", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); } } } @@ -164,14 +164,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "unixbfs_rdb", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new BFS(); + IFilesystem fs = new BFS(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "\"UNI\\0\"") @@ -182,12 +182,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual(type[i], fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual(type[i], fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/XENIX.cs b/DiscImageChef.Tests/Filesystems/XENIX.cs index 6d82e012..146cdfcc 100644 --- a/DiscImageChef.Tests/Filesystems/XENIX.cs +++ b/DiscImageChef.Tests/Filesystems/XENIX.cs @@ -69,27 +69,27 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "xenix", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new ZZZRawImage(); + IMediaImage image = new ZZZRawImage(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - Filesystem fs = new SysVfs(); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + IFilesystem fs = new SysVfs(); Partition wholePart = new Partition { Name = "Whole device", - Length = image.ImageInfo.Sectors, - Size = image.ImageInfo.Sectors * image.ImageInfo.SectorSize + Length = image.Info.Sectors, + Size = image.Info.Sectors * image.Info.SectorSize }; Assert.AreEqual(true, fs.Identify(image, wholePart), testfiles[i]); - fs.GetInformation(image, wholePart, out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual(type[i], fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, wholePart, out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual(type[i], fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } @@ -119,14 +119,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "xenix_mbr", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new SysVfs(); + IFilesystem fs = new SysVfs(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "XENIX") @@ -137,12 +137,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual(type[i], fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual(type[i], fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/XFS.cs b/DiscImageChef.Tests/Filesystems/XFS.cs index 2edcd1a9..ae800616 100644 --- a/DiscImageChef.Tests/Filesystems/XFS.cs +++ b/DiscImageChef.Tests/Filesystems/XFS.cs @@ -59,14 +59,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "xfs_mbr", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new XFS(); + IFilesystem fs = new XFS(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "0x83") @@ -77,12 +77,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("XFS filesystem", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("XFS filesystem", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/Xia.cs b/DiscImageChef.Tests/Filesystems/Xia.cs index 07d81686..bcc4a0fa 100644 --- a/DiscImageChef.Tests/Filesystems/Xia.cs +++ b/DiscImageChef.Tests/Filesystems/Xia.cs @@ -59,14 +59,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "xia_mbr", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new Xia(); + IFilesystem fs = new Xia(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "0x83") @@ -77,12 +77,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("Xia filesystem", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("Xia filesystem", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/ZFS.cs b/DiscImageChef.Tests/Filesystems/ZFS.cs index 37f02041..c979bb65 100644 --- a/DiscImageChef.Tests/Filesystems/ZFS.cs +++ b/DiscImageChef.Tests/Filesystems/ZFS.cs @@ -58,26 +58,26 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "zfs", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - Filesystem fs = new ZFS(); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + IFilesystem fs = new ZFS(); Partition wholePart = new Partition { Name = "Whole device", - Length = image.ImageInfo.Sectors, - Size = image.ImageInfo.Sectors * image.ImageInfo.SectorSize + Length = image.Info.Sectors, + Size = image.Info.Sectors * image.Info.SectorSize }; Assert.AreEqual(true, fs.Identify(image, wholePart), testfiles[i]); - fs.GetInformation(image, wholePart, out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("ZFS filesystem", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, wholePart, out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("ZFS filesystem", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/btrfs.cs b/DiscImageChef.Tests/Filesystems/btrfs.cs index c6f421e9..1bc46d3a 100644 --- a/DiscImageChef.Tests/Filesystems/btrfs.cs +++ b/DiscImageChef.Tests/Filesystems/btrfs.cs @@ -60,15 +60,15 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "btrfs", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - PartitionPlugin parts = new MBR(); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + IPartition parts = new MBR(); Assert.AreEqual(true, parts.GetInformation(image, out List partitions, 0), testfiles[i]); - Filesystem fs = new BTRFS(); + IFilesystem fs = new BTRFS(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "0x83") @@ -79,12 +79,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("B-tree file system", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("B-tree file system", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/exFAT.cs b/DiscImageChef.Tests/Filesystems/exFAT.cs index c99379a5..4894dee5 100644 --- a/DiscImageChef.Tests/Filesystems/exFAT.cs +++ b/DiscImageChef.Tests/Filesystems/exFAT.cs @@ -59,14 +59,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "exfat_apm", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new exFAT(); + IFilesystem fs = new exFAT(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "Windows_NTFS") @@ -77,12 +77,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("exFAT", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("exFAT", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } @@ -110,14 +110,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "exfat_gpt", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new exFAT(); + IFilesystem fs = new exFAT(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "Microsoft Basic data") @@ -128,12 +128,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("exFAT", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("exFAT", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } @@ -161,14 +161,14 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "exfat_mbr", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); List partitions = Core.Partitions.GetAll(image); - Filesystem fs = new exFAT(); + IFilesystem fs = new exFAT(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "0x07") @@ -179,12 +179,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual("exFAT", fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual("exFAT", fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filesystems/ext2.cs b/DiscImageChef.Tests/Filesystems/ext2.cs index 281228d0..bdb1bd38 100644 --- a/DiscImageChef.Tests/Filesystems/ext2.cs +++ b/DiscImageChef.Tests/Filesystems/ext2.cs @@ -70,15 +70,15 @@ namespace DiscImageChef.Tests.Filesystems for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "filesystems", "ext2", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - PartitionPlugin parts = new MBR(); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + IPartition parts = new MBR(); Assert.AreEqual(true, parts.GetInformation(image, out List partitions, 0), testfiles[i]); - Filesystem fs = new ext2FS(); + IFilesystem fs = new ext2FS(); int part = -1; for(int j = 0; j < partitions.Count; j++) if(partitions[j].Type == "0x83") @@ -89,12 +89,12 @@ namespace DiscImageChef.Tests.Filesystems Assert.AreNotEqual(-1, part, $"Partition not found on {testfiles[i]}"); Assert.AreEqual(true, fs.Identify(image, partitions[part]), testfiles[i]); - fs.GetInformation(image, partitions[part], out _); - Assert.AreEqual(clusters[i], fs.XmlFSType.Clusters, testfiles[i]); - Assert.AreEqual(clustersize[i], fs.XmlFSType.ClusterSize, testfiles[i]); - Assert.AreEqual(extversion[i], fs.XmlFSType.Type, testfiles[i]); - Assert.AreEqual(volumename[i], fs.XmlFSType.VolumeName, testfiles[i]); - Assert.AreEqual(volumeserial[i], fs.XmlFSType.VolumeSerial, testfiles[i]); + fs.GetInformation(image, partitions[part], out _, null); + Assert.AreEqual(clusters[i], fs.XmlFsType.Clusters, testfiles[i]); + Assert.AreEqual(clustersize[i], fs.XmlFsType.ClusterSize, testfiles[i]); + Assert.AreEqual(extversion[i], fs.XmlFsType.Type, testfiles[i]); + Assert.AreEqual(volumename[i], fs.XmlFsType.VolumeName, testfiles[i]); + Assert.AreEqual(volumeserial[i], fs.XmlFsType.VolumeSerial, testfiles[i]); } } } diff --git a/DiscImageChef.Tests/Filters/AppleDoubleDave.cs b/DiscImageChef.Tests/Filters/AppleDoubleDave.cs index 6aceaacc..17ec83bb 100644 --- a/DiscImageChef.Tests/Filters/AppleDoubleDave.cs +++ b/DiscImageChef.Tests/Filters/AppleDoubleDave.cs @@ -67,14 +67,14 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckFilterId() { - Filter filter = new AppleDouble(); + IFilter filter = new AppleDouble(); Assert.AreEqual(true, filter.Identify(location)); } [Test] public void Test() { - Filter filter = new AppleDouble(); + IFilter filter = new AppleDouble(); filter.Open(location); Assert.AreEqual(true, filter.IsOpened()); Assert.AreEqual(737280, filter.GetDataForkLength()); @@ -88,7 +88,7 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckContents() { - Filter filter = new AppleDouble(); + IFilter filter = new AppleDouble(); filter.Open(location); Stream str = filter.GetDataForkStream(); byte[] data = new byte[737280]; @@ -105,7 +105,7 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckResource() { - Filter filter = new AppleDouble(); + IFilter filter = new AppleDouble(); filter.Open(location); Stream str = filter.GetResourceForkStream(); byte[] data = new byte[286]; diff --git a/DiscImageChef.Tests/Filters/AppleDoubleDos.cs b/DiscImageChef.Tests/Filters/AppleDoubleDos.cs index c9d26290..8c490955 100644 --- a/DiscImageChef.Tests/Filters/AppleDoubleDos.cs +++ b/DiscImageChef.Tests/Filters/AppleDoubleDos.cs @@ -66,14 +66,14 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckFilterId() { - Filter filter = new AppleDouble(); + IFilter filter = new AppleDouble(); Assert.AreEqual(true, filter.Identify(location)); } [Test] public void Test() { - Filter filter = new AppleDouble(); + IFilter filter = new AppleDouble(); filter.Open(location); Assert.AreEqual(true, filter.IsOpened()); Assert.AreEqual(737280, filter.GetDataForkLength()); @@ -87,7 +87,7 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckContents() { - Filter filter = new AppleDouble(); + IFilter filter = new AppleDouble(); filter.Open(location); Stream str = filter.GetDataForkStream(); byte[] data = new byte[737280]; @@ -104,7 +104,7 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckResource() { - Filter filter = new AppleDouble(); + IFilter filter = new AppleDouble(); filter.Open(location); Stream str = filter.GetResourceForkStream(); byte[] data = new byte[286]; diff --git a/DiscImageChef.Tests/Filters/AppleDoubleNetatalk.cs b/DiscImageChef.Tests/Filters/AppleDoubleNetatalk.cs index 94ca3345..c8ce4bf6 100644 --- a/DiscImageChef.Tests/Filters/AppleDoubleNetatalk.cs +++ b/DiscImageChef.Tests/Filters/AppleDoubleNetatalk.cs @@ -67,14 +67,14 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckFilterId() { - Filter filter = new AppleDouble(); + IFilter filter = new AppleDouble(); Assert.AreEqual(true, filter.Identify(location)); } [Test] public void Test() { - Filter filter = new AppleDouble(); + IFilter filter = new AppleDouble(); filter.Open(location); Assert.AreEqual(true, filter.IsOpened()); Assert.AreEqual(737280, filter.GetDataForkLength()); @@ -88,7 +88,7 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckContents() { - Filter filter = new AppleDouble(); + IFilter filter = new AppleDouble(); filter.Open(location); Stream str = filter.GetDataForkStream(); byte[] data = new byte[737280]; @@ -105,7 +105,7 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckResource() { - Filter filter = new AppleDouble(); + IFilter filter = new AppleDouble(); filter.Open(location); Stream str = filter.GetResourceForkStream(); byte[] data = new byte[286]; diff --git a/DiscImageChef.Tests/Filters/AppleDoubleOsX.cs b/DiscImageChef.Tests/Filters/AppleDoubleOsX.cs index 4f8e6df7..a5365249 100644 --- a/DiscImageChef.Tests/Filters/AppleDoubleOsX.cs +++ b/DiscImageChef.Tests/Filters/AppleDoubleOsX.cs @@ -66,14 +66,14 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckFilterId() { - Filter filter = new AppleDouble(); + IFilter filter = new AppleDouble(); Assert.AreEqual(true, filter.Identify(location)); } [Test] public void Test() { - Filter filter = new AppleDouble(); + IFilter filter = new AppleDouble(); filter.Open(location); Assert.AreEqual(true, filter.IsOpened()); Assert.AreEqual(737280, filter.GetDataForkLength()); @@ -87,7 +87,7 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckContents() { - Filter filter = new AppleDouble(); + IFilter filter = new AppleDouble(); filter.Open(location); Stream str = filter.GetDataForkStream(); byte[] data = new byte[737280]; @@ -104,7 +104,7 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckResource() { - Filter filter = new AppleDouble(); + IFilter filter = new AppleDouble(); filter.Open(location); Stream str = filter.GetResourceForkStream(); byte[] data = new byte[286]; diff --git a/DiscImageChef.Tests/Filters/AppleDoubleProDos.cs b/DiscImageChef.Tests/Filters/AppleDoubleProDos.cs index 656f0e6e..12f0071f 100644 --- a/DiscImageChef.Tests/Filters/AppleDoubleProDos.cs +++ b/DiscImageChef.Tests/Filters/AppleDoubleProDos.cs @@ -66,14 +66,14 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckFilterId() { - Filter filter = new AppleDouble(); + IFilter filter = new AppleDouble(); Assert.AreEqual(true, filter.Identify(location)); } [Test] public void Test() { - Filter filter = new AppleDouble(); + IFilter filter = new AppleDouble(); filter.Open(location); Assert.AreEqual(true, filter.IsOpened()); Assert.AreEqual(737280, filter.GetDataForkLength()); @@ -87,7 +87,7 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckContents() { - Filter filter = new AppleDouble(); + IFilter filter = new AppleDouble(); filter.Open(location); Stream str = filter.GetDataForkStream(); byte[] data = new byte[737280]; @@ -104,7 +104,7 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckResource() { - Filter filter = new AppleDouble(); + IFilter filter = new AppleDouble(); filter.Open(location); Stream str = filter.GetResourceForkStream(); byte[] data = new byte[286]; diff --git a/DiscImageChef.Tests/Filters/AppleDoubleUnAr.cs b/DiscImageChef.Tests/Filters/AppleDoubleUnAr.cs index b79e6ef3..8586a9b4 100644 --- a/DiscImageChef.Tests/Filters/AppleDoubleUnAr.cs +++ b/DiscImageChef.Tests/Filters/AppleDoubleUnAr.cs @@ -66,14 +66,14 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckFilterId() { - Filter filter = new AppleDouble(); + IFilter filter = new AppleDouble(); Assert.AreEqual(true, filter.Identify(location)); } [Test] public void Test() { - Filter filter = new AppleDouble(); + IFilter filter = new AppleDouble(); filter.Open(location); Assert.AreEqual(true, filter.IsOpened()); Assert.AreEqual(737280, filter.GetDataForkLength()); @@ -87,7 +87,7 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckContents() { - Filter filter = new AppleDouble(); + IFilter filter = new AppleDouble(); filter.Open(location); Stream str = filter.GetDataForkStream(); byte[] data = new byte[737280]; @@ -104,7 +104,7 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckResource() { - Filter filter = new AppleDouble(); + IFilter filter = new AppleDouble(); filter.Open(location); Stream str = filter.GetResourceForkStream(); byte[] data = new byte[286]; diff --git a/DiscImageChef.Tests/Filters/AppleDoubleUnix.cs b/DiscImageChef.Tests/Filters/AppleDoubleUnix.cs index 30b810a7..78995ce5 100644 --- a/DiscImageChef.Tests/Filters/AppleDoubleUnix.cs +++ b/DiscImageChef.Tests/Filters/AppleDoubleUnix.cs @@ -66,14 +66,14 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckFilterId() { - Filter filter = new AppleDouble(); + IFilter filter = new AppleDouble(); Assert.AreEqual(true, filter.Identify(location)); } [Test] public void Test() { - Filter filter = new AppleDouble(); + IFilter filter = new AppleDouble(); filter.Open(location); Assert.AreEqual(true, filter.IsOpened()); Assert.AreEqual(737280, filter.GetDataForkLength()); @@ -87,7 +87,7 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckContents() { - Filter filter = new AppleDouble(); + IFilter filter = new AppleDouble(); filter.Open(location); Stream str = filter.GetDataForkStream(); byte[] data = new byte[737280]; @@ -104,7 +104,7 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckResource() { - Filter filter = new AppleDouble(); + IFilter filter = new AppleDouble(); filter.Open(location); Stream str = filter.GetResourceForkStream(); byte[] data = new byte[286]; diff --git a/DiscImageChef.Tests/Filters/AppleSingle.cs b/DiscImageChef.Tests/Filters/AppleSingle.cs index 98b30adc..cddc2713 100644 --- a/DiscImageChef.Tests/Filters/AppleSingle.cs +++ b/DiscImageChef.Tests/Filters/AppleSingle.cs @@ -58,14 +58,14 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckFilterId() { - Filter filter = new DiscImageChef.Filters.AppleSingle(); + IFilter filter = new DiscImageChef.Filters.AppleSingle(); Assert.AreEqual(true, filter.Identify(location)); } [Test] public void Test() { - Filter filter = new DiscImageChef.Filters.AppleSingle(); + IFilter filter = new DiscImageChef.Filters.AppleSingle(); filter.Open(location); Assert.AreEqual(true, filter.IsOpened()); Assert.AreEqual(737280, filter.GetDataForkLength()); @@ -79,7 +79,7 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckContents() { - Filter filter = new DiscImageChef.Filters.AppleSingle(); + IFilter filter = new DiscImageChef.Filters.AppleSingle(); filter.Open(location); Stream str = filter.GetDataForkStream(); byte[] data = new byte[737280]; @@ -96,7 +96,7 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckResource() { - Filter filter = new DiscImageChef.Filters.AppleSingle(); + IFilter filter = new DiscImageChef.Filters.AppleSingle(); filter.Open(location); Stream str = filter.GetResourceForkStream(); byte[] data = new byte[286]; diff --git a/DiscImageChef.Tests/Filters/BZip2.cs b/DiscImageChef.Tests/Filters/BZip2.cs index d412606c..60a34808 100644 --- a/DiscImageChef.Tests/Filters/BZip2.cs +++ b/DiscImageChef.Tests/Filters/BZip2.cs @@ -59,14 +59,14 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckFilterId() { - Filter filter = new DiscImageChef.Filters.BZip2(); + IFilter filter = new DiscImageChef.Filters.BZip2(); Assert.AreEqual(true, filter.Identify(location)); } [Test] public void Test() { - Filter filter = new DiscImageChef.Filters.BZip2(); + IFilter filter = new DiscImageChef.Filters.BZip2(); filter.Open(location); Assert.AreEqual(true, filter.IsOpened()); Assert.AreEqual(1048576, filter.GetDataForkLength()); @@ -80,7 +80,7 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckContents() { - Filter filter = new DiscImageChef.Filters.BZip2(); + IFilter filter = new DiscImageChef.Filters.BZip2(); filter.Open(location); Stream str = filter.GetDataForkStream(); byte[] data = new byte[1048576]; diff --git a/DiscImageChef.Tests/Filters/GZip.cs b/DiscImageChef.Tests/Filters/GZip.cs index fa26dc28..4f4a6653 100644 --- a/DiscImageChef.Tests/Filters/GZip.cs +++ b/DiscImageChef.Tests/Filters/GZip.cs @@ -59,14 +59,14 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckFilterId() { - Filter filter = new DiscImageChef.Filters.GZip(); + IFilter filter = new DiscImageChef.Filters.GZip(); Assert.AreEqual(true, filter.Identify(location)); } [Test] public void Test() { - Filter filter = new DiscImageChef.Filters.GZip(); + IFilter filter = new DiscImageChef.Filters.GZip(); filter.Open(location); Assert.AreEqual(true, filter.IsOpened()); Assert.AreEqual(1048576, filter.GetDataForkLength()); @@ -80,7 +80,7 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckContents() { - Filter filter = new DiscImageChef.Filters.GZip(); + IFilter filter = new DiscImageChef.Filters.GZip(); filter.Open(location); Stream str = filter.GetDataForkStream(); byte[] data = new byte[1048576]; diff --git a/DiscImageChef.Tests/Filters/LZip.cs b/DiscImageChef.Tests/Filters/LZip.cs index 16d5bdae..4cf29287 100644 --- a/DiscImageChef.Tests/Filters/LZip.cs +++ b/DiscImageChef.Tests/Filters/LZip.cs @@ -59,14 +59,14 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckFilterId() { - Filter filter = new DiscImageChef.Filters.LZip(); + IFilter filter = new DiscImageChef.Filters.LZip(); Assert.AreEqual(true, filter.Identify(location)); } [Test] public void Test() { - Filter filter = new DiscImageChef.Filters.LZip(); + IFilter filter = new DiscImageChef.Filters.LZip(); filter.Open(location); Assert.AreEqual(true, filter.IsOpened()); Assert.AreEqual(1048576, filter.GetDataForkLength()); @@ -80,7 +80,7 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckContents() { - Filter filter = new DiscImageChef.Filters.LZip(); + IFilter filter = new DiscImageChef.Filters.LZip(); filter.Open(location); Stream str = filter.GetDataForkStream(); byte[] data = new byte[1048576]; diff --git a/DiscImageChef.Tests/Filters/MacBinary1.cs b/DiscImageChef.Tests/Filters/MacBinary1.cs index e32f3471..25ada52e 100644 --- a/DiscImageChef.Tests/Filters/MacBinary1.cs +++ b/DiscImageChef.Tests/Filters/MacBinary1.cs @@ -58,14 +58,14 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckFilterId() { - Filter filter = new DiscImageChef.Filters.AppleSingle(); + IFilter filter = new DiscImageChef.Filters.AppleSingle(); Assert.AreEqual(true, filter.Identify(location)); } [Test] public void Test() { - Filter filter = new DiscImageChef.Filters.AppleSingle(); + IFilter filter = new DiscImageChef.Filters.AppleSingle(); filter.Open(location); Assert.AreEqual(true, filter.IsOpened()); Assert.AreEqual(737280, filter.GetDataForkLength()); @@ -79,7 +79,7 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckContents() { - Filter filter = new DiscImageChef.Filters.AppleSingle(); + IFilter filter = new DiscImageChef.Filters.AppleSingle(); filter.Open(location); Stream str = filter.GetDataForkStream(); byte[] data = new byte[737280]; @@ -96,7 +96,7 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckResource() { - Filter filter = new DiscImageChef.Filters.AppleSingle(); + IFilter filter = new DiscImageChef.Filters.AppleSingle(); filter.Open(location); Stream str = filter.GetResourceForkStream(); byte[] data = new byte[286]; diff --git a/DiscImageChef.Tests/Filters/MacBinary2.cs b/DiscImageChef.Tests/Filters/MacBinary2.cs index 65db0a44..4e02a1f5 100644 --- a/DiscImageChef.Tests/Filters/MacBinary2.cs +++ b/DiscImageChef.Tests/Filters/MacBinary2.cs @@ -58,14 +58,14 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckFilterId() { - Filter filter = new MacBinary(); + IFilter filter = new MacBinary(); Assert.AreEqual(true, filter.Identify(location)); } [Test] public void Test() { - Filter filter = new MacBinary(); + IFilter filter = new MacBinary(); filter.Open(location); Assert.AreEqual(true, filter.IsOpened()); Assert.AreEqual(737280, filter.GetDataForkLength()); @@ -79,7 +79,7 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckContents() { - Filter filter = new MacBinary(); + IFilter filter = new MacBinary(); filter.Open(location); Stream str = filter.GetDataForkStream(); byte[] data = new byte[737280]; @@ -96,7 +96,7 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckResource() { - Filter filter = new MacBinary(); + IFilter filter = new MacBinary(); filter.Open(location); Stream str = filter.GetResourceForkStream(); byte[] data = new byte[286]; diff --git a/DiscImageChef.Tests/Filters/MacBinary3.cs b/DiscImageChef.Tests/Filters/MacBinary3.cs index b75efaaa..8fe846bf 100644 --- a/DiscImageChef.Tests/Filters/MacBinary3.cs +++ b/DiscImageChef.Tests/Filters/MacBinary3.cs @@ -58,14 +58,14 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckFilterId() { - Filter filter = new MacBinary(); + IFilter filter = new MacBinary(); Assert.AreEqual(true, filter.Identify(location)); } [Test] public void Test() { - Filter filter = new MacBinary(); + IFilter filter = new MacBinary(); filter.Open(location); Assert.AreEqual(true, filter.IsOpened()); Assert.AreEqual(737280, filter.GetDataForkLength()); @@ -79,7 +79,7 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckContents() { - Filter filter = new MacBinary(); + IFilter filter = new MacBinary(); filter.Open(location); Stream str = filter.GetDataForkStream(); byte[] data = new byte[737280]; @@ -96,7 +96,7 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckResource() { - Filter filter = new MacBinary(); + IFilter filter = new MacBinary(); filter.Open(location); Stream str = filter.GetResourceForkStream(); byte[] data = new byte[286]; diff --git a/DiscImageChef.Tests/Filters/PCExchange.cs b/DiscImageChef.Tests/Filters/PCExchange.cs index efa270ec..a2c9d060 100644 --- a/DiscImageChef.Tests/Filters/PCExchange.cs +++ b/DiscImageChef.Tests/Filters/PCExchange.cs @@ -58,14 +58,14 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckFilterId() { - Filter filter = new PCExchange(); + IFilter filter = new PCExchange(); Assert.AreEqual(true, filter.Identify(location)); } [Test] public void Test() { - Filter filter = new PCExchange(); + IFilter filter = new PCExchange(); filter.Open(location); Assert.AreEqual(true, filter.IsOpened()); Assert.AreEqual(737280, filter.GetDataForkLength()); @@ -79,7 +79,7 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckContents() { - Filter filter = new PCExchange(); + IFilter filter = new PCExchange(); filter.Open(location); Stream str = filter.GetDataForkStream(); byte[] data = new byte[737280]; @@ -96,7 +96,7 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckResource() { - Filter filter = new PCExchange(); + IFilter filter = new PCExchange(); filter.Open(location); Stream str = filter.GetResourceForkStream(); byte[] data = new byte[546]; diff --git a/DiscImageChef.Tests/Filters/XZ.cs b/DiscImageChef.Tests/Filters/XZ.cs index 7cc3b113..25eea69c 100644 --- a/DiscImageChef.Tests/Filters/XZ.cs +++ b/DiscImageChef.Tests/Filters/XZ.cs @@ -59,14 +59,14 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckFilterId() { - Filter filter = new XZ(); + IFilter filter = new XZ(); Assert.AreEqual(true, filter.Identify(location)); } [Test] public void Test() { - Filter filter = new XZ(); + IFilter filter = new XZ(); filter.Open(location); Assert.AreEqual(true, filter.IsOpened()); Assert.AreEqual(1048576, filter.GetDataForkLength()); @@ -80,7 +80,7 @@ namespace DiscImageChef.Tests.Filters [Test] public void CheckContents() { - Filter filter = new XZ(); + IFilter filter = new XZ(); filter.Open(location); Stream str = filter.GetDataForkStream(); byte[] data = new byte[1048576]; diff --git a/DiscImageChef.Tests/Images/2MG.cs b/DiscImageChef.Tests/Images/2MG.cs index 70b634ea..a697da1c 100644 --- a/DiscImageChef.Tests/Images/2MG.cs +++ b/DiscImageChef.Tests/Images/2MG.cs @@ -66,13 +66,13 @@ namespace DiscImageChef.Tests.Images for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "images", "2mg", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new DiscImages.Apple2Mg(); + IMediaImage image = new DiscImages.Apple2Mg(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); // How many sectors to read at once const uint SECTORS_TO_READ = 256; @@ -81,19 +81,19 @@ namespace DiscImageChef.Tests.Images Md5Context ctx = new Md5Context(); ctx.Init(); - while(doneSectors < image.ImageInfo.Sectors) + while(doneSectors < image.Info.Sectors) { byte[] sector; - if(image.ImageInfo.Sectors - doneSectors >= SECTORS_TO_READ) + if(image.Info.Sectors - doneSectors >= SECTORS_TO_READ) { sector = image.ReadSectors(doneSectors, SECTORS_TO_READ); doneSectors += SECTORS_TO_READ; } else { - sector = image.ReadSectors(doneSectors, (uint)(image.ImageInfo.Sectors - doneSectors)); - doneSectors += image.ImageInfo.Sectors - doneSectors; + sector = image.ReadSectors(doneSectors, (uint)(image.Info.Sectors - doneSectors)); + doneSectors += image.Info.Sectors - doneSectors; } ctx.Update(sector); diff --git a/DiscImageChef.Tests/Images/Anex86.cs b/DiscImageChef.Tests/Images/Anex86.cs index cf9050bd..e0b388ad 100644 --- a/DiscImageChef.Tests/Images/Anex86.cs +++ b/DiscImageChef.Tests/Images/Anex86.cs @@ -70,13 +70,13 @@ namespace DiscImageChef.Tests.Images for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "images", "anex86", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new DiscImages.Anex86(); + IMediaImage image = new DiscImages.Anex86(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); // How many sectors to read at once const uint SECTORS_TO_READ = 256; @@ -85,19 +85,19 @@ namespace DiscImageChef.Tests.Images Md5Context ctx = new Md5Context(); ctx.Init(); - while(doneSectors < image.ImageInfo.Sectors) + while(doneSectors < image.Info.Sectors) { byte[] sector; - if(image.ImageInfo.Sectors - doneSectors >= SECTORS_TO_READ) + if(image.Info.Sectors - doneSectors >= SECTORS_TO_READ) { sector = image.ReadSectors(doneSectors, SECTORS_TO_READ); doneSectors += SECTORS_TO_READ; } else { - sector = image.ReadSectors(doneSectors, (uint)(image.ImageInfo.Sectors - doneSectors)); - doneSectors += image.ImageInfo.Sectors - doneSectors; + sector = image.ReadSectors(doneSectors, (uint)(image.Info.Sectors - doneSectors)); + doneSectors += image.Info.Sectors - doneSectors; } ctx.Update(sector); diff --git a/DiscImageChef.Tests/Images/CisCopy.cs b/DiscImageChef.Tests/Images/CisCopy.cs index 2afd416b..f9ee58b5 100644 --- a/DiscImageChef.Tests/Images/CisCopy.cs +++ b/DiscImageChef.Tests/Images/CisCopy.cs @@ -84,13 +84,13 @@ namespace DiscImageChef.Tests.Images for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "images", "ciscopy", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new DiscImages.CisCopy(); + IMediaImage image = new DiscImages.CisCopy(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); // How many sectors to read at once const uint SECTORS_TO_READ = 256; @@ -99,19 +99,19 @@ namespace DiscImageChef.Tests.Images Md5Context ctx = new Md5Context(); ctx.Init(); - while(doneSectors < image.ImageInfo.Sectors) + while(doneSectors < image.Info.Sectors) { byte[] sector; - if(image.ImageInfo.Sectors - doneSectors >= SECTORS_TO_READ) + if(image.Info.Sectors - doneSectors >= SECTORS_TO_READ) { sector = image.ReadSectors(doneSectors, SECTORS_TO_READ); doneSectors += SECTORS_TO_READ; } else { - sector = image.ReadSectors(doneSectors, (uint)(image.ImageInfo.Sectors - doneSectors)); - doneSectors += image.ImageInfo.Sectors - doneSectors; + sector = image.ReadSectors(doneSectors, (uint)(image.Info.Sectors - doneSectors)); + doneSectors += image.Info.Sectors - doneSectors; } ctx.Update(sector); diff --git a/DiscImageChef.Tests/Images/CopyQM.cs b/DiscImageChef.Tests/Images/CopyQM.cs index bbda61d5..2aae199f 100644 --- a/DiscImageChef.Tests/Images/CopyQM.cs +++ b/DiscImageChef.Tests/Images/CopyQM.cs @@ -68,13 +68,13 @@ namespace DiscImageChef.Tests.Images for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "images", "copyqm", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new DiscImages.CopyQm(); + IMediaImage image = new DiscImages.CopyQm(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); // How many sectors to read at once const uint SECTORS_TO_READ = 256; @@ -83,19 +83,19 @@ namespace DiscImageChef.Tests.Images Md5Context ctx = new Md5Context(); ctx.Init(); - while(doneSectors < image.ImageInfo.Sectors) + while(doneSectors < image.Info.Sectors) { byte[] sector; - if(image.ImageInfo.Sectors - doneSectors >= SECTORS_TO_READ) + if(image.Info.Sectors - doneSectors >= SECTORS_TO_READ) { sector = image.ReadSectors(doneSectors, SECTORS_TO_READ); doneSectors += SECTORS_TO_READ; } else { - sector = image.ReadSectors(doneSectors, (uint)(image.ImageInfo.Sectors - doneSectors)); - doneSectors += image.ImageInfo.Sectors - doneSectors; + sector = image.ReadSectors(doneSectors, (uint)(image.Info.Sectors - doneSectors)); + doneSectors += image.Info.Sectors - doneSectors; } ctx.Update(sector); diff --git a/DiscImageChef.Tests/Images/D88.cs b/DiscImageChef.Tests/Images/D88.cs index 62d110ac..b1799355 100644 --- a/DiscImageChef.Tests/Images/D88.cs +++ b/DiscImageChef.Tests/Images/D88.cs @@ -86,13 +86,13 @@ namespace DiscImageChef.Tests.Images for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "images", "d88", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new DiscImages.D88(); + IMediaImage image = new DiscImages.D88(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); // How many sectors to read at once const uint SECTORS_TO_READ = 256; @@ -101,19 +101,19 @@ namespace DiscImageChef.Tests.Images Md5Context ctx = new Md5Context(); ctx.Init(); - while(doneSectors < image.ImageInfo.Sectors) + while(doneSectors < image.Info.Sectors) { byte[] sector; - if(image.ImageInfo.Sectors - doneSectors >= SECTORS_TO_READ) + if(image.Info.Sectors - doneSectors >= SECTORS_TO_READ) { sector = image.ReadSectors(doneSectors, SECTORS_TO_READ); doneSectors += SECTORS_TO_READ; } else { - sector = image.ReadSectors(doneSectors, (uint)(image.ImageInfo.Sectors - doneSectors)); - doneSectors += image.ImageInfo.Sectors - doneSectors; + sector = image.ReadSectors(doneSectors, (uint)(image.Info.Sectors - doneSectors)); + doneSectors += image.Info.Sectors - doneSectors; } ctx.Update(sector); diff --git a/DiscImageChef.Tests/Images/DART.cs b/DiscImageChef.Tests/Images/DART.cs index ae2e43dc..d35a5eb4 100644 --- a/DiscImageChef.Tests/Images/DART.cs +++ b/DiscImageChef.Tests/Images/DART.cs @@ -67,13 +67,13 @@ namespace DiscImageChef.Tests.Images for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "images", "dart", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new DiscImages.D88(); + IMediaImage image = new DiscImages.D88(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); // How many sectors to read at once const uint SECTORS_TO_READ = 256; @@ -82,19 +82,19 @@ namespace DiscImageChef.Tests.Images Md5Context ctx = new Md5Context(); ctx.Init(); - while(doneSectors < image.ImageInfo.Sectors) + while(doneSectors < image.Info.Sectors) { byte[] sector; - if(image.ImageInfo.Sectors - doneSectors >= SECTORS_TO_READ) + if(image.Info.Sectors - doneSectors >= SECTORS_TO_READ) { sector = image.ReadSectors(doneSectors, SECTORS_TO_READ); doneSectors += SECTORS_TO_READ; } else { - sector = image.ReadSectors(doneSectors, (uint)(image.ImageInfo.Sectors - doneSectors)); - doneSectors += image.ImageInfo.Sectors - doneSectors; + sector = image.ReadSectors(doneSectors, (uint)(image.Info.Sectors - doneSectors)); + doneSectors += image.Info.Sectors - doneSectors; } ctx.Update(sector); diff --git a/DiscImageChef.Tests/Images/DiskCopy42.cs b/DiscImageChef.Tests/Images/DiskCopy42.cs index 476d7457..1fe1c131 100644 --- a/DiscImageChef.Tests/Images/DiskCopy42.cs +++ b/DiscImageChef.Tests/Images/DiskCopy42.cs @@ -87,13 +87,13 @@ namespace DiscImageChef.Tests.Images for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "images", "", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new DiscImages.DiskCopy42(); + IMediaImage image = new DiscImages.DiskCopy42(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); - Assert.AreEqual(sectors[i], image.ImageInfo.Sectors, testfiles[i]); - Assert.AreEqual(sectorsize[i], image.ImageInfo.SectorSize, testfiles[i]); - Assert.AreEqual(mediatypes[i], image.ImageInfo.MediaType, testfiles[i]); + Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]); + Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]); + Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]); // How many sectors to read at once const uint SECTORS_TO_READ = 256; @@ -102,19 +102,19 @@ namespace DiscImageChef.Tests.Images Md5Context ctx = new Md5Context(); ctx.Init(); - while(doneSectors < image.ImageInfo.Sectors) + while(doneSectors < image.Info.Sectors) { byte[] sector; - if(image.ImageInfo.Sectors - doneSectors >= SECTORS_TO_READ) + if(image.Info.Sectors - doneSectors >= SECTORS_TO_READ) { sector = image.ReadSectors(doneSectors, SECTORS_TO_READ); doneSectors += SECTORS_TO_READ; } else { - sector = image.ReadSectors(doneSectors, (uint)(image.ImageInfo.Sectors - doneSectors)); - doneSectors += image.ImageInfo.Sectors - doneSectors; + sector = image.ReadSectors(doneSectors, (uint)(image.Info.Sectors - doneSectors)); + doneSectors += image.Info.Sectors - doneSectors; } ctx.Update(sector); diff --git a/DiscImageChef.Tests/Partitions/Acorn.cs b/DiscImageChef.Tests/Partitions/Acorn.cs index a3a49180..22aec952 100644 --- a/DiscImageChef.Tests/Partitions/Acorn.cs +++ b/DiscImageChef.Tests/Partitions/Acorn.cs @@ -99,9 +99,9 @@ namespace DiscImageChef.Tests.Partitions for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "partitions", "acorn", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); List partitions = Core.Partitions.GetAll(image); Assert.AreEqual(wanted[i].Length, partitions.Count, testfiles[i]); diff --git a/DiscImageChef.Tests/Partitions/AppleMap.cs b/DiscImageChef.Tests/Partitions/AppleMap.cs index 858b2e23..92fcdfbb 100644 --- a/DiscImageChef.Tests/Partitions/AppleMap.cs +++ b/DiscImageChef.Tests/Partitions/AppleMap.cs @@ -2003,9 +2003,9 @@ namespace DiscImageChef.Tests.Partitions for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "partitions", "apm", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); List partitions = Core.Partitions.GetAll(image); Assert.AreEqual(wanted[i].Length, partitions.Count, testfiles[i]); diff --git a/DiscImageChef.Tests/Partitions/Atari.cs b/DiscImageChef.Tests/Partitions/Atari.cs index bbca3413..6e79a273 100644 --- a/DiscImageChef.Tests/Partitions/Atari.cs +++ b/DiscImageChef.Tests/Partitions/Atari.cs @@ -315,9 +315,9 @@ namespace DiscImageChef.Tests.Partitions for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "partitions", "atari", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); List partitions = Core.Partitions.GetAll(image); Assert.AreEqual(wanted[i].Length, partitions.Count, testfiles[i]); diff --git a/DiscImageChef.Tests/Partitions/BSD.cs b/DiscImageChef.Tests/Partitions/BSD.cs index 0845b7ec..dd301fad 100644 --- a/DiscImageChef.Tests/Partitions/BSD.cs +++ b/DiscImageChef.Tests/Partitions/BSD.cs @@ -390,9 +390,9 @@ namespace DiscImageChef.Tests.Partitions for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "partitions", "bsd", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); List partitions = Core.Partitions.GetAll(image); Assert.AreEqual(wanted[i].Length, partitions.Count, testfiles[i]); diff --git a/DiscImageChef.Tests/Partitions/GPT.cs b/DiscImageChef.Tests/Partitions/GPT.cs index 51a5f41c..987a087f 100644 --- a/DiscImageChef.Tests/Partitions/GPT.cs +++ b/DiscImageChef.Tests/Partitions/GPT.cs @@ -157,9 +157,9 @@ namespace DiscImageChef.Tests.Partitions for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "partitions", "gpt", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); List partitions = Core.Partitions.GetAll(image); Assert.AreEqual(wanted[i].Length, partitions.Count, testfiles[i]); diff --git a/DiscImageChef.Tests/Partitions/MBR.cs b/DiscImageChef.Tests/Partitions/MBR.cs index fda74dd3..e5d8531d 100644 --- a/DiscImageChef.Tests/Partitions/MBR.cs +++ b/DiscImageChef.Tests/Partitions/MBR.cs @@ -1943,9 +1943,9 @@ namespace DiscImageChef.Tests.Partitions for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "partitions", "mbr", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); List partitions = Core.Partitions.GetAll(image); Assert.AreEqual(wanted[i].Length, partitions.Count, testfiles[i]); diff --git a/DiscImageChef.Tests/Partitions/MINIX.cs b/DiscImageChef.Tests/Partitions/MINIX.cs index 0e562288..6d3bff60 100644 --- a/DiscImageChef.Tests/Partitions/MINIX.cs +++ b/DiscImageChef.Tests/Partitions/MINIX.cs @@ -98,9 +98,9 @@ namespace DiscImageChef.Tests.Partitions for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "partitions", "minix", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); List partitions = Core.Partitions.GetAll(image); Assert.AreEqual(wanted[i].Length, partitions.Count, testfiles[i]); diff --git a/DiscImageChef.Tests/Partitions/PC98.cs b/DiscImageChef.Tests/Partitions/PC98.cs index 20ec0eaf..f4e0f210 100644 --- a/DiscImageChef.Tests/Partitions/PC98.cs +++ b/DiscImageChef.Tests/Partitions/PC98.cs @@ -377,9 +377,9 @@ namespace DiscImageChef.Tests.Partitions for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "partitions", "pc98", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new T98(); + IMediaImage image = new T98(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); List partitions = Core.Partitions.GetAll(image); Assert.AreEqual(wanted[i].Length, partitions.Count, testfiles[i]); diff --git a/DiscImageChef.Tests/Partitions/RDB.cs b/DiscImageChef.Tests/Partitions/RDB.cs index 69ff8713..f875d798 100644 --- a/DiscImageChef.Tests/Partitions/RDB.cs +++ b/DiscImageChef.Tests/Partitions/RDB.cs @@ -227,9 +227,9 @@ namespace DiscImageChef.Tests.Partitions for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "partitions", "rdb", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); List partitions = Core.Partitions.GetAll(image); Assert.AreEqual(wanted[i].Length, partitions.Count, testfiles[i]); diff --git a/DiscImageChef.Tests/Partitions/SGI.cs b/DiscImageChef.Tests/Partitions/SGI.cs index 9c4d6acc..f9e641d3 100644 --- a/DiscImageChef.Tests/Partitions/SGI.cs +++ b/DiscImageChef.Tests/Partitions/SGI.cs @@ -220,9 +220,9 @@ namespace DiscImageChef.Tests.Partitions for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "partitions", "sgi", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); List partitions = Core.Partitions.GetAll(image); Assert.AreEqual(wanted[i].Length, partitions.Count, testfiles[i]); diff --git a/DiscImageChef.Tests/Partitions/Sun.cs b/DiscImageChef.Tests/Partitions/Sun.cs index 0d0467b8..6df7d511 100644 --- a/DiscImageChef.Tests/Partitions/Sun.cs +++ b/DiscImageChef.Tests/Partitions/Sun.cs @@ -149,9 +149,9 @@ namespace DiscImageChef.Tests.Partitions for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "partitions", "sun", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); List partitions = Core.Partitions.GetAll(image); Assert.AreEqual(wanted[i].Length, partitions.Count, testfiles[i]); diff --git a/DiscImageChef.Tests/Partitions/VTOC.cs b/DiscImageChef.Tests/Partitions/VTOC.cs index af41389d..1ba531f1 100644 --- a/DiscImageChef.Tests/Partitions/VTOC.cs +++ b/DiscImageChef.Tests/Partitions/VTOC.cs @@ -198,9 +198,9 @@ namespace DiscImageChef.Tests.Partitions for(int i = 0; i < testfiles.Length; i++) { string location = Path.Combine(Consts.TestFilesRoot, "partitions", "vtoc", testfiles[i]); - Filter filter = new LZip(); + IFilter filter = new LZip(); filter.Open(location); - ImagePlugin image = new Vdi(); + IMediaImage image = new Vdi(); Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]); List partitions = Core.Partitions.GetAll(image); Assert.AreEqual(wanted[i].Length, partitions.Count, testfiles[i]); diff --git a/DiscImageChef/Commands/Analyze.cs b/DiscImageChef/Commands/Analyze.cs index d04eb861..2cb816e1 100644 --- a/DiscImageChef/Commands/Analyze.cs +++ b/DiscImageChef/Commands/Analyze.cs @@ -53,7 +53,7 @@ namespace DiscImageChef.Commands DicConsole.DebugWriteLine("Analyze command", "--partitions={0}", options.SearchForPartitions); FiltersList filtersList = new FiltersList(); - Filter inputFilter = filtersList.GetFilter(options.InputFile); + IFilter inputFilter = filtersList.GetFilter(options.InputFile); if(inputFilter == null) { @@ -76,13 +76,12 @@ namespace DiscImageChef.Commands } PluginBase plugins = new PluginBase(); - plugins.RegisterAllPlugins(encoding); bool checkraw = false; try { - ImagePlugin imageFormat = ImageFormat.Detect(inputFilter); + IMediaImage imageFormat = ImageFormat.Detect(inputFilter); if(imageFormat == null) { @@ -92,7 +91,7 @@ namespace DiscImageChef.Commands if(options.Verbose) DicConsole.VerboseWriteLine("Image format identified by {0} ({1}).", imageFormat.Name, - imageFormat.PluginUuid); + imageFormat.Id); else DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name); try @@ -106,13 +105,13 @@ namespace DiscImageChef.Commands DicConsole.DebugWriteLine("Analyze command", "Correctly opened image file."); DicConsole.DebugWriteLine("Analyze command", "Image without headers is {0} bytes.", - imageFormat.ImageInfo.ImageSize); - DicConsole.DebugWriteLine("Analyze command", "Image has {0} sectors.", imageFormat.ImageInfo.Sectors); + imageFormat.Info.ImageSize); + DicConsole.DebugWriteLine("Analyze command", "Image has {0} sectors.", imageFormat.Info.Sectors); DicConsole.DebugWriteLine("Analyze command", "Image identifies disk type as {0}.", - imageFormat.ImageInfo.MediaType); + imageFormat.Info.MediaType); Core.Statistics.AddMediaFormat(imageFormat.ImageFormat); - Core.Statistics.AddMedia(imageFormat.ImageInfo.MediaType, false); + Core.Statistics.AddMedia(imageFormat.Info.MediaType, false); Core.Statistics.AddFilter(inputFilter.Name); } catch(Exception ex) @@ -124,7 +123,7 @@ namespace DiscImageChef.Commands } List idPlugins; - Filesystem plugin; + IFilesystem plugin; string information; if(options.SearchForPartitions) { @@ -174,9 +173,9 @@ namespace DiscImageChef.Commands if(plugins.PluginsList.TryGetValue(pluginName, out plugin)) { DicConsole.WriteLine($"As identified by {plugin.Name}."); - plugin.GetInformation(imageFormat, partitions[i], out information); + plugin.GetInformation(imageFormat, partitions[i], out information, encoding); DicConsole.Write(information); - Core.Statistics.AddFilesystem(plugin.XmlFSType.Type); + Core.Statistics.AddFilesystem(plugin.XmlFsType.Type); } } else @@ -185,9 +184,9 @@ namespace DiscImageChef.Commands if(plugin == null) continue; DicConsole.WriteLine($"Identified by {plugin.Name}."); - plugin.GetInformation(imageFormat, partitions[i], out information); + plugin.GetInformation(imageFormat, partitions[i], out information, encoding); DicConsole.Write(information); - Core.Statistics.AddFilesystem(plugin.XmlFSType.Type); + Core.Statistics.AddFilesystem(plugin.XmlFsType.Type); } } } @@ -198,8 +197,8 @@ namespace DiscImageChef.Commands Partition wholePart = new Partition { Name = "Whole device", - Length = imageFormat.ImageInfo.Sectors, - Size = imageFormat.ImageInfo.Sectors * imageFormat.ImageInfo.SectorSize + Length = imageFormat.Info.Sectors, + Size = imageFormat.Info.Sectors * imageFormat.Info.SectorSize }; Core.Filesystems.Identify(imageFormat, out idPlugins, wholePart); @@ -212,9 +211,9 @@ namespace DiscImageChef.Commands if(plugins.PluginsList.TryGetValue(pluginName, out plugin)) { DicConsole.WriteLine($"As identified by {plugin.Name}."); - plugin.GetInformation(imageFormat, wholePart, out information); + plugin.GetInformation(imageFormat, wholePart, out information, encoding); DicConsole.Write(information); - Core.Statistics.AddFilesystem(plugin.XmlFSType.Type); + Core.Statistics.AddFilesystem(plugin.XmlFsType.Type); } } else @@ -223,9 +222,9 @@ namespace DiscImageChef.Commands if(plugin != null) { DicConsole.WriteLine($"Identified by {plugin.Name}."); - plugin.GetInformation(imageFormat, wholePart, out information); + plugin.GetInformation(imageFormat, wholePart, out information, encoding); DicConsole.Write(information); - Core.Statistics.AddFilesystem(plugin.XmlFSType.Type); + Core.Statistics.AddFilesystem(plugin.XmlFsType.Type); } } } diff --git a/DiscImageChef/Commands/Checksum.cs b/DiscImageChef/Commands/Checksum.cs index 9f1b0e63..141ed978 100644 --- a/DiscImageChef/Commands/Checksum.cs +++ b/DiscImageChef/Commands/Checksum.cs @@ -65,7 +65,7 @@ namespace DiscImageChef.Commands DicConsole.DebugWriteLine("Checksum command", "--spamsum={0}", options.DoSpamSum); FiltersList filtersList = new FiltersList(); - Filter inputFilter = filtersList.GetFilter(options.InputFile); + IFilter inputFilter = filtersList.GetFilter(options.InputFile); if(inputFilter == null) { @@ -73,7 +73,7 @@ namespace DiscImageChef.Commands return; } - ImagePlugin inputFormat = ImageFormat.Detect(inputFilter); + IMediaImage inputFormat = ImageFormat.Detect(inputFilter); if(inputFormat == null) { @@ -83,7 +83,7 @@ namespace DiscImageChef.Commands inputFormat.OpenImage(inputFilter); Core.Statistics.AddMediaFormat(inputFormat.ImageFormat); - Core.Statistics.AddMedia(inputFormat.ImageInfo.MediaType, false); + Core.Statistics.AddMedia(inputFormat.Info.MediaType, false); Core.Statistics.AddFilter(inputFilter.Name); EnableChecksum enabledChecksums = new EnableChecksum(); @@ -101,7 +101,7 @@ namespace DiscImageChef.Commands Core.Checksum mediaChecksum = null; - if(inputFormat.ImageInfo.HasPartitions) + if(inputFormat.Info.HasPartitions) try { Core.Checksum trackChecksum = null; @@ -171,8 +171,8 @@ namespace DiscImageChef.Commands previousTrackEnd = currentTrack.TrackEndSector; } - if(inputFormat.ImageInfo.Sectors - previousTrackEnd != 0 && options.WholeDisc) - for(ulong i = previousTrackEnd + 1; i < inputFormat.ImageInfo.Sectors; i++) + if(inputFormat.Info.Sectors - previousTrackEnd != 0 && options.WholeDisc) + for(ulong i = previousTrackEnd + 1; i < inputFormat.Info.Sectors; i++) { DicConsole.Write("\rHashing track-less sector {0}", i); @@ -194,7 +194,7 @@ namespace DiscImageChef.Commands { mediaChecksum = new Core.Checksum(enabledChecksums); - ulong sectors = inputFormat.ImageInfo.Sectors; + ulong sectors = inputFormat.Info.Sectors; DicConsole.WriteLine("Sectors {0}", sectors); ulong doneSectors = 0; diff --git a/DiscImageChef/Commands/Compare.cs b/DiscImageChef/Commands/Compare.cs index d8a652a5..192c3004 100644 --- a/DiscImageChef/Commands/Compare.cs +++ b/DiscImageChef/Commands/Compare.cs @@ -50,9 +50,9 @@ namespace DiscImageChef.Commands DicConsole.DebugWriteLine("Compare command", "--input2={0}", options.InputFile2); FiltersList filtersList = new FiltersList(); - Filter inputFilter1 = filtersList.GetFilter(options.InputFile1); + IFilter inputFilter1 = filtersList.GetFilter(options.InputFile1); filtersList = new FiltersList(); - Filter inputFilter2 = filtersList.GetFilter(options.InputFile2); + IFilter inputFilter2 = filtersList.GetFilter(options.InputFile2); if(inputFilter1 == null) { @@ -66,8 +66,8 @@ namespace DiscImageChef.Commands return; } - ImagePlugin input1Format = ImageFormat.Detect(inputFilter1); - ImagePlugin input2Format = ImageFormat.Detect(inputFilter2); + IMediaImage input1Format = ImageFormat.Detect(inputFilter1); + IMediaImage input2Format = ImageFormat.Detect(inputFilter2); if(input1Format == null) { @@ -77,7 +77,7 @@ namespace DiscImageChef.Commands if(options.Verbose) DicConsole.VerboseWriteLine("Input file 1 format identified by {0} ({1}).", input1Format.Name, - input1Format.PluginUuid); + input1Format.Id); else DicConsole.WriteLine("Input file 1 format identified by {0}.", input1Format.Name); if(input2Format == null) @@ -88,7 +88,7 @@ namespace DiscImageChef.Commands if(options.Verbose) DicConsole.VerboseWriteLine("Input file 2 format identified by {0} ({1}).", input2Format.Name, - input2Format.PluginUuid); + input2Format.Id); else DicConsole.WriteLine("Input file 2 format identified by {0}.", input2Format.Name); input1Format.OpenImage(inputFilter1); @@ -96,8 +96,8 @@ namespace DiscImageChef.Commands Core.Statistics.AddMediaFormat(input1Format.ImageFormat); Core.Statistics.AddMediaFormat(input2Format.ImageFormat); - Core.Statistics.AddMedia(input1Format.ImageInfo.MediaType, false); - Core.Statistics.AddMedia(input2Format.ImageInfo.MediaType, false); + Core.Statistics.AddMedia(input1Format.Info.MediaType, false); + Core.Statistics.AddMedia(input2Format.Info.MediaType, false); Core.Statistics.AddFilter(inputFilter1.Name); Core.Statistics.AddFilter(inputFilter2.Name); @@ -125,7 +125,7 @@ namespace DiscImageChef.Commands Dictionary image1DiskTags = new Dictionary(); Dictionary image2DiskTags = new Dictionary(); - image1Info.HasPartitions = input1Format.ImageInfo.HasPartitions; + image1Info.HasPartitions = input1Format.Info.HasPartitions; #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body try { image1Sessions = input1Format.Sessions; } catch @@ -134,29 +134,29 @@ namespace DiscImageChef.Commands } #pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body image1Info.HasSessions |= image1Sessions.Count > 0; - image1Info.ImageSize = input1Format.ImageInfo.ImageSize; - image1Info.Sectors = input1Format.ImageInfo.Sectors; - image1Info.SectorSize = input1Format.ImageInfo.SectorSize; - image1Info.CreationTime = input1Format.ImageInfo.CreationTime; - image1Info.LastModificationTime = input1Format.ImageInfo.LastModificationTime; - image1Info.MediaType = input1Format.ImageInfo.MediaType; - image1Info.Version = input1Format.ImageInfo.Version; - image1Info.Application = input1Format.ImageInfo.Application; - image1Info.ApplicationVersion = input1Format.ImageInfo.ApplicationVersion; - image1Info.Creator = input1Format.ImageInfo.Creator; - image1Info.MediaTitle = input1Format.ImageInfo.MediaTitle; - image1Info.Comments = input1Format.ImageInfo.Comments; - image1Info.MediaManufacturer = input1Format.ImageInfo.MediaManufacturer; - image1Info.MediaModel = input1Format.ImageInfo.MediaModel; - image1Info.MediaSerialNumber = input1Format.ImageInfo.MediaSerialNumber; - image1Info.MediaBarcode = input1Format.ImageInfo.MediaBarcode; - image1Info.MediaPartNumber = input1Format.ImageInfo.MediaPartNumber; - image1Info.MediaSequence = input1Format.ImageInfo.MediaSequence; - image1Info.LastMediaSequence = input1Format.ImageInfo.LastMediaSequence; - image1Info.DriveManufacturer = input1Format.ImageInfo.DriveManufacturer; - image1Info.DriveModel = input1Format.ImageInfo.DriveModel; - image1Info.DriveSerialNumber = input1Format.ImageInfo.DriveSerialNumber; - image1Info.DriveFirmwareRevision = input1Format.ImageInfo.DriveFirmwareRevision; + image1Info.ImageSize = input1Format.Info.ImageSize; + image1Info.Sectors = input1Format.Info.Sectors; + image1Info.SectorSize = input1Format.Info.SectorSize; + image1Info.CreationTime = input1Format.Info.CreationTime; + image1Info.LastModificationTime = input1Format.Info.LastModificationTime; + image1Info.MediaType = input1Format.Info.MediaType; + image1Info.Version = input1Format.Info.Version; + image1Info.Application = input1Format.Info.Application; + image1Info.ApplicationVersion = input1Format.Info.ApplicationVersion; + image1Info.Creator = input1Format.Info.Creator; + image1Info.MediaTitle = input1Format.Info.MediaTitle; + image1Info.Comments = input1Format.Info.Comments; + image1Info.MediaManufacturer = input1Format.Info.MediaManufacturer; + image1Info.MediaModel = input1Format.Info.MediaModel; + image1Info.MediaSerialNumber = input1Format.Info.MediaSerialNumber; + image1Info.MediaBarcode = input1Format.Info.MediaBarcode; + image1Info.MediaPartNumber = input1Format.Info.MediaPartNumber; + image1Info.MediaSequence = input1Format.Info.MediaSequence; + image1Info.LastMediaSequence = input1Format.Info.LastMediaSequence; + image1Info.DriveManufacturer = input1Format.Info.DriveManufacturer; + image1Info.DriveModel = input1Format.Info.DriveModel; + image1Info.DriveSerialNumber = input1Format.Info.DriveSerialNumber; + image1Info.DriveFirmwareRevision = input1Format.Info.DriveFirmwareRevision; foreach(MediaTagType disktag in Enum.GetValues(typeof(MediaTagType))) { try @@ -172,7 +172,7 @@ namespace DiscImageChef.Commands #pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body } - image2Info.HasPartitions = input2Format.ImageInfo.HasPartitions; + image2Info.HasPartitions = input2Format.Info.HasPartitions; #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body try { image2Sessions = input2Format.Sessions; } catch @@ -181,29 +181,29 @@ namespace DiscImageChef.Commands } #pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body image2Info.HasSessions |= image2Sessions.Count > 0; - image2Info.ImageSize = input2Format.ImageInfo.ImageSize; - image2Info.Sectors = input2Format.ImageInfo.Sectors; - image2Info.SectorSize = input2Format.ImageInfo.SectorSize; - image2Info.CreationTime = input2Format.ImageInfo.CreationTime; - image2Info.LastModificationTime = input2Format.ImageInfo.LastModificationTime; - image2Info.MediaType = input2Format.ImageInfo.MediaType; - image2Info.Version = input2Format.ImageInfo.Version; - image2Info.Application = input2Format.ImageInfo.Application; - image2Info.ApplicationVersion = input2Format.ImageInfo.ApplicationVersion; - image2Info.Creator = input2Format.ImageInfo.Creator; - image2Info.MediaTitle = input2Format.ImageInfo.MediaTitle; - image2Info.Comments = input2Format.ImageInfo.Comments; - image2Info.MediaManufacturer = input2Format.ImageInfo.MediaManufacturer; - image2Info.MediaModel = input2Format.ImageInfo.MediaModel; - image2Info.MediaSerialNumber = input2Format.ImageInfo.MediaSerialNumber; - image2Info.MediaBarcode = input2Format.ImageInfo.MediaBarcode; - image2Info.MediaPartNumber = input2Format.ImageInfo.MediaPartNumber; - image2Info.MediaSequence = input2Format.ImageInfo.MediaSequence; - image2Info.LastMediaSequence = input2Format.ImageInfo.LastMediaSequence; - image2Info.DriveManufacturer = input2Format.ImageInfo.DriveManufacturer; - image2Info.DriveModel = input2Format.ImageInfo.DriveModel; - image2Info.DriveSerialNumber = input2Format.ImageInfo.DriveSerialNumber; - image2Info.DriveFirmwareRevision = input2Format.ImageInfo.DriveFirmwareRevision; + image2Info.ImageSize = input2Format.Info.ImageSize; + image2Info.Sectors = input2Format.Info.Sectors; + image2Info.SectorSize = input2Format.Info.SectorSize; + image2Info.CreationTime = input2Format.Info.CreationTime; + image2Info.LastModificationTime = input2Format.Info.LastModificationTime; + image2Info.MediaType = input2Format.Info.MediaType; + image2Info.Version = input2Format.Info.Version; + image2Info.Application = input2Format.Info.Application; + image2Info.ApplicationVersion = input2Format.Info.ApplicationVersion; + image2Info.Creator = input2Format.Info.Creator; + image2Info.MediaTitle = input2Format.Info.MediaTitle; + image2Info.Comments = input2Format.Info.Comments; + image2Info.MediaManufacturer = input2Format.Info.MediaManufacturer; + image2Info.MediaModel = input2Format.Info.MediaModel; + image2Info.MediaSerialNumber = input2Format.Info.MediaSerialNumber; + image2Info.MediaBarcode = input2Format.Info.MediaBarcode; + image2Info.MediaPartNumber = input2Format.Info.MediaPartNumber; + image2Info.MediaSequence = input2Format.Info.MediaSequence; + image2Info.LastMediaSequence = input2Format.Info.LastMediaSequence; + image2Info.DriveManufacturer = input2Format.Info.DriveManufacturer; + image2Info.DriveModel = input2Format.Info.DriveModel; + image2Info.DriveSerialNumber = input2Format.Info.DriveSerialNumber; + image2Info.DriveFirmwareRevision = input2Format.Info.DriveFirmwareRevision; foreach(MediaTagType disktag in Enum.GetValues(typeof(MediaTagType))) { try diff --git a/DiscImageChef/Commands/CreateSidecar.cs b/DiscImageChef/Commands/CreateSidecar.cs index 152b1044..0eca236c 100644 --- a/DiscImageChef/Commands/CreateSidecar.cs +++ b/DiscImageChef/Commands/CreateSidecar.cs @@ -79,7 +79,7 @@ namespace DiscImageChef.Commands } FiltersList filtersList = new FiltersList(); - Filter inputFilter = filtersList.GetFilter(options.InputFile); + IFilter inputFilter = filtersList.GetFilter(options.InputFile); if(inputFilter == null) { @@ -89,7 +89,7 @@ namespace DiscImageChef.Commands try { - ImagePlugin imageFormat = ImageFormat.Detect(inputFilter); + IMediaImage imageFormat = ImageFormat.Detect(inputFilter); if(imageFormat == null) { @@ -99,7 +99,7 @@ namespace DiscImageChef.Commands if(options.Verbose) DicConsole.VerboseWriteLine("Image format identified by {0} ({1}).", imageFormat.Name, - imageFormat.PluginUuid); + imageFormat.Id); else DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name); try @@ -124,7 +124,7 @@ namespace DiscImageChef.Commands Core.Statistics.AddFilter(inputFilter.Name); CICMMetadataType sidecar = - Sidecar.Create(imageFormat, options.InputFile, inputFilter.UUID, encoding); + Sidecar.Create(imageFormat, options.InputFile, inputFilter.Id, encoding); DicConsole.WriteLine("Writing metadata sidecar"); diff --git a/DiscImageChef/Commands/Decode.cs b/DiscImageChef/Commands/Decode.cs index bd5e926c..73a47d68 100644 --- a/DiscImageChef/Commands/Decode.cs +++ b/DiscImageChef/Commands/Decode.cs @@ -54,7 +54,7 @@ namespace DiscImageChef.Commands DicConsole.DebugWriteLine("Decode command", "--sector-tags={0}", options.SectorTags); FiltersList filtersList = new FiltersList(); - Filter inputFilter = filtersList.GetFilter(options.InputFile); + IFilter inputFilter = filtersList.GetFilter(options.InputFile); if(inputFilter == null) { @@ -62,7 +62,7 @@ namespace DiscImageChef.Commands return; } - ImagePlugin inputFormat = ImageFormat.Detect(inputFilter); + IMediaImage inputFormat = ImageFormat.Detect(inputFilter); if(inputFormat == null) { @@ -72,14 +72,14 @@ namespace DiscImageChef.Commands inputFormat.OpenImage(inputFilter); Core.Statistics.AddMediaFormat(inputFormat.ImageFormat); - Core.Statistics.AddMedia(inputFormat.ImageInfo.MediaType, false); + Core.Statistics.AddMedia(inputFormat.Info.MediaType, false); Core.Statistics.AddFilter(inputFilter.Name); if(options.DiskTags) - if(inputFormat.ImageInfo.ReadableMediaTags.Count == 0) + if(inputFormat.Info.ReadableMediaTags.Count == 0) DicConsole.WriteLine("There are no disk tags in chosen disc image."); else - foreach(MediaTagType tag in inputFormat.ImageInfo.ReadableMediaTags) + foreach(MediaTagType tag in inputFormat.Info.ReadableMediaTags) switch(tag) { case MediaTagType.SCSI_INQUIRY: @@ -232,7 +232,7 @@ namespace DiscImageChef.Commands { ulong length; - if(options.Length.ToLowerInvariant() == "all") length = inputFormat.ImageInfo.Sectors - 1; + if(options.Length.ToLowerInvariant() == "all") length = inputFormat.Info.Sectors - 1; else { if(!ulong.TryParse(options.Length, out length)) @@ -243,10 +243,10 @@ namespace DiscImageChef.Commands } } - if(inputFormat.ImageInfo.ReadableSectorTags.Count == 0) + if(inputFormat.Info.ReadableSectorTags.Count == 0) DicConsole.WriteLine("There are no sector tags in chosen disc image."); else - foreach(SectorTagType tag in inputFormat.ImageInfo.ReadableSectorTags) + foreach(SectorTagType tag in inputFormat.Info.ReadableSectorTags) switch(tag) { default: diff --git a/DiscImageChef/Commands/Entropy.cs b/DiscImageChef/Commands/Entropy.cs index e50ee627..10435c0d 100644 --- a/DiscImageChef/Commands/Entropy.cs +++ b/DiscImageChef/Commands/Entropy.cs @@ -53,7 +53,7 @@ namespace DiscImageChef.Commands DicConsole.DebugWriteLine("Entropy command", "--duplicated-sectors={0}", options.DuplicatedSectors); FiltersList filtersList = new FiltersList(); - Filter inputFilter = filtersList.GetFilter(options.InputFile); + IFilter inputFilter = filtersList.GetFilter(options.InputFile); if(inputFilter == null) { @@ -61,7 +61,7 @@ namespace DiscImageChef.Commands return; } - ImagePlugin inputFormat = ImageFormat.Detect(inputFilter); + IMediaImage inputFormat = ImageFormat.Detect(inputFilter); if(inputFormat == null) { @@ -71,7 +71,7 @@ namespace DiscImageChef.Commands inputFormat.OpenImage(inputFilter); Core.Statistics.AddMediaFormat(inputFormat.ImageFormat); - Core.Statistics.AddMedia(inputFormat.ImageInfo.MediaType, false); + Core.Statistics.AddMedia(inputFormat.Info.MediaType, false); Core.Statistics.AddFilter(inputFilter.Name); double entropy = 0; ulong[] entTable; @@ -134,7 +134,7 @@ namespace DiscImageChef.Commands ulong diskSize = 0; List uniqueSectors = new List(); - sectors = inputFormat.ImageInfo.Sectors; + sectors = inputFormat.Info.Sectors; DicConsole.WriteLine("Sectors {0}", sectors); sha1Ctx.Init(); diff --git a/DiscImageChef/Commands/ExtractFiles.cs b/DiscImageChef/Commands/ExtractFiles.cs index 0b191baf..22105501 100644 --- a/DiscImageChef/Commands/ExtractFiles.cs +++ b/DiscImageChef/Commands/ExtractFiles.cs @@ -55,7 +55,7 @@ namespace DiscImageChef.Commands DicConsole.DebugWriteLine("Extract-Files command", "--output={0}", options.OutputDir); FiltersList filtersList = new FiltersList(); - Filter inputFilter = filtersList.GetFilter(options.InputFile); + IFilter inputFilter = filtersList.GetFilter(options.InputFile); if(inputFilter == null) { @@ -78,11 +78,11 @@ namespace DiscImageChef.Commands } PluginBase plugins = new PluginBase(); - plugins.RegisterAllPlugins(encoding); + plugins.RegisterAllPlugins(); try { - ImagePlugin imageFormat = ImageFormat.Detect(inputFilter); + IMediaImage imageFormat = ImageFormat.Detect(inputFilter); if(imageFormat == null) { @@ -92,7 +92,7 @@ namespace DiscImageChef.Commands if(options.Verbose) DicConsole.VerboseWriteLine("Image format identified by {0} ({1}).", imageFormat.Name, - imageFormat.PluginUuid); + imageFormat.Id); else DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name); if(Directory.Exists(options.OutputDir) || File.Exists(options.OutputDir)) @@ -114,14 +114,14 @@ namespace DiscImageChef.Commands DicConsole.DebugWriteLine("Extract-Files command", "Correctly opened image file."); DicConsole.DebugWriteLine("Extract-Files command", "Image without headers is {0} bytes.", - imageFormat.ImageInfo.ImageSize); + imageFormat.Info.ImageSize); DicConsole.DebugWriteLine("Extract-Files command", "Image has {0} sectors.", - imageFormat.ImageInfo.Sectors); + imageFormat.Info.Sectors); DicConsole.DebugWriteLine("Extract-Files command", "Image identifies disk type as {0}.", - imageFormat.ImageInfo.MediaType); + imageFormat.Info.MediaType); Core.Statistics.AddMediaFormat(imageFormat.ImageFormat); - Core.Statistics.AddMedia(imageFormat.ImageInfo.MediaType, false); + Core.Statistics.AddMedia(imageFormat.Info.MediaType, false); Core.Statistics.AddFilter(inputFilter.Name); } catch(Exception ex) @@ -135,7 +135,7 @@ namespace DiscImageChef.Commands Core.Partitions.AddSchemesToStats(partitions); List idPlugins; - Filesystem plugin; + IFilesystem plugin; Errno error; if(partitions.Count == 0) DicConsole.DebugWriteLine("Extract-Files command", "No partitions found"); else @@ -159,13 +159,10 @@ namespace DiscImageChef.Commands if(plugins.PluginsList.TryGetValue(pluginName, out plugin)) { DicConsole.WriteLine($"As identified by {plugin.Name}."); - Filesystem fs = (Filesystem)plugin - .GetType().GetConstructor(new[] - { - typeof(ImagePlugin), typeof(Partition), typeof(Encoding) - }).Invoke(new object[] {imageFormat, partitions[i], null}); + IFilesystem fs = (IFilesystem)plugin + .GetType().GetConstructor(Type.EmptyTypes)?.Invoke(new object[] { }); - error = fs.Mount(options.Debug); + error = fs.Mount(imageFormat, partitions[i], encoding, options.Debug); if(error == Errno.NoError) { List rootDir = new List(); @@ -176,9 +173,9 @@ namespace DiscImageChef.Commands FileEntryInfo stat = new FileEntryInfo(); string volumeName = - string.IsNullOrEmpty(fs.XmlFSType.VolumeName) + string.IsNullOrEmpty(fs.XmlFsType.VolumeName) ? "NO NAME" - : fs.XmlFSType.VolumeName; + : fs.XmlFsType.VolumeName; error = fs.Stat(entry, ref stat); if(error == Errno.NoError) @@ -199,12 +196,12 @@ namespace DiscImageChef.Commands Directory .CreateDirectory(Path.Combine(options.OutputDir, - fs.XmlFSType.Type, + fs.XmlFsType.Type, volumeName, ".xattrs", xattr)); outputPath = - Path.Combine(options.OutputDir, fs.XmlFSType.Type, + Path.Combine(options.OutputDir, fs.XmlFsType.Type, volumeName, ".xattrs", xattr, entry); if(!File.Exists(outputPath)) @@ -246,11 +243,11 @@ namespace DiscImageChef.Commands } Directory.CreateDirectory(Path.Combine(options.OutputDir, - fs.XmlFSType.Type, + fs.XmlFsType.Type, volumeName)); outputPath = - Path.Combine(options.OutputDir, fs.XmlFSType.Type, volumeName, + Path.Combine(options.OutputDir, fs.XmlFsType.Type, volumeName, entry); if(!File.Exists(outputPath)) @@ -302,7 +299,7 @@ namespace DiscImageChef.Commands DicConsole.ErrorWriteLine("Error {0} reading root directory {0}", error.ToString()); - Core.Statistics.AddFilesystem(fs.XmlFSType.Type); + Core.Statistics.AddFilesystem(fs.XmlFsType.Type); } else DicConsole.ErrorWriteLine("Unable to mount device, error {0}", @@ -313,12 +310,9 @@ namespace DiscImageChef.Commands { plugins.PluginsList.TryGetValue(idPlugins[0], out plugin); DicConsole.WriteLine($"Identified by {plugin.Name}."); - Filesystem fs = (Filesystem)plugin - .GetType().GetConstructor(new[] - { - typeof(ImagePlugin), typeof(Partition), typeof(Encoding) - }).Invoke(new object[] {imageFormat, partitions[i], null}); - error = fs.Mount(options.Debug); + IFilesystem fs = (IFilesystem)plugin + .GetType().GetConstructor(Type.EmptyTypes)?.Invoke(new object[] { }); + error = fs.Mount(imageFormat, partitions[i], encoding, options.Debug); if(error == Errno.NoError) { List rootDir = new List(); @@ -329,9 +323,9 @@ namespace DiscImageChef.Commands FileEntryInfo stat = new FileEntryInfo(); string volumeName = - string.IsNullOrEmpty(fs.XmlFSType.VolumeName) + string.IsNullOrEmpty(fs.XmlFsType.VolumeName) ? "NO NAME" - : fs.XmlFSType.VolumeName; + : fs.XmlFsType.VolumeName; error = fs.Stat(entry, ref stat); if(error == Errno.NoError) @@ -351,12 +345,12 @@ namespace DiscImageChef.Commands if(error != Errno.NoError) continue; Directory.CreateDirectory(Path.Combine(options.OutputDir, - fs.XmlFSType.Type, + fs.XmlFsType.Type, volumeName, ".xattrs", xattr)); outputPath = - Path.Combine(options.OutputDir, fs.XmlFSType.Type, + Path.Combine(options.OutputDir, fs.XmlFsType.Type, volumeName, ".xattrs", xattr, entry); if(!File.Exists(outputPath)) @@ -395,11 +389,11 @@ namespace DiscImageChef.Commands } } - Directory.CreateDirectory(Path.Combine(options.OutputDir, fs.XmlFSType.Type, + Directory.CreateDirectory(Path.Combine(options.OutputDir, fs.XmlFsType.Type, volumeName)); outputPath = - Path.Combine(options.OutputDir, fs.XmlFSType.Type, volumeName, entry); + Path.Combine(options.OutputDir, fs.XmlFsType.Type, volumeName, entry); if(!File.Exists(outputPath)) { @@ -448,7 +442,7 @@ namespace DiscImageChef.Commands else DicConsole.ErrorWriteLine("Error {0} reading root directory {0}", error.ToString()); - Core.Statistics.AddFilesystem(fs.XmlFSType.Type); + Core.Statistics.AddFilesystem(fs.XmlFsType.Type); } else DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString()); } @@ -458,8 +452,8 @@ namespace DiscImageChef.Commands Partition wholePart = new Partition { Name = "Whole device", - Length = imageFormat.ImageInfo.Sectors, - Size = imageFormat.ImageInfo.Sectors * imageFormat.ImageInfo.SectorSize + Length = imageFormat.Info.Sectors, + Size = imageFormat.Info.Sectors * imageFormat.Info.SectorSize }; Core.Filesystems.Identify(imageFormat, out idPlugins, wholePart); @@ -472,12 +466,9 @@ namespace DiscImageChef.Commands if(plugins.PluginsList.TryGetValue(pluginName, out plugin)) { DicConsole.WriteLine($"As identified by {plugin.Name}."); - Filesystem fs = (Filesystem)plugin - .GetType().GetConstructor(new[] - { - typeof(ImagePlugin), typeof(Partition), typeof(Encoding) - }).Invoke(new object[] {imageFormat, wholePart, null}); - error = fs.Mount(options.Debug); + IFilesystem fs = (IFilesystem)plugin + .GetType().GetConstructor(Type.EmptyTypes)?.Invoke(new object[] { }); + error = fs.Mount(imageFormat, wholePart, encoding, options.Debug); if(error == Errno.NoError) { List rootDir = new List(); @@ -488,9 +479,9 @@ namespace DiscImageChef.Commands FileEntryInfo stat = new FileEntryInfo(); string volumeName = - string.IsNullOrEmpty(fs.XmlFSType.VolumeName) + string.IsNullOrEmpty(fs.XmlFsType.VolumeName) ? "NO NAME" - : fs.XmlFSType.VolumeName; + : fs.XmlFsType.VolumeName; error = fs.Stat(entry, ref stat); if(error == Errno.NoError) @@ -510,12 +501,12 @@ namespace DiscImageChef.Commands if(error != Errno.NoError) continue; Directory.CreateDirectory(Path.Combine(options.OutputDir, - fs.XmlFSType.Type, + fs.XmlFsType.Type, volumeName, ".xattrs", xattr)); outputPath = - Path.Combine(options.OutputDir, fs.XmlFSType.Type, + Path.Combine(options.OutputDir, fs.XmlFsType.Type, volumeName, ".xattrs", xattr, entry); if(!File.Exists(outputPath)) @@ -554,11 +545,11 @@ namespace DiscImageChef.Commands } } - Directory.CreateDirectory(Path.Combine(options.OutputDir, fs.XmlFSType.Type, + Directory.CreateDirectory(Path.Combine(options.OutputDir, fs.XmlFsType.Type, volumeName)); outputPath = - Path.Combine(options.OutputDir, fs.XmlFSType.Type, volumeName, entry); + Path.Combine(options.OutputDir, fs.XmlFsType.Type, volumeName, entry); if(!File.Exists(outputPath)) { @@ -607,7 +598,7 @@ namespace DiscImageChef.Commands else DicConsole.ErrorWriteLine("Error {0} reading root directory {0}", error.ToString()); - Core.Statistics.AddFilesystem(fs.XmlFSType.Type); + Core.Statistics.AddFilesystem(fs.XmlFsType.Type); } else DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString()); } @@ -616,10 +607,9 @@ namespace DiscImageChef.Commands { plugins.PluginsList.TryGetValue(idPlugins[0], out plugin); DicConsole.WriteLine($"Identified by {plugin.Name}."); - Filesystem fs = (Filesystem)plugin - .GetType().GetConstructor(new[] {typeof(ImagePlugin), typeof(Partition), typeof(Encoding)}) - .Invoke(new object[] {imageFormat, wholePart, null}); - error = fs.Mount(options.Debug); + IFilesystem fs = (IFilesystem)plugin + .GetType().GetConstructor(Type.EmptyTypes)?.Invoke(new object[] { }); + error = fs.Mount(imageFormat, wholePart, encoding, options.Debug); if(error == Errno.NoError) { List rootDir = new List(); @@ -629,9 +619,9 @@ namespace DiscImageChef.Commands { FileEntryInfo stat = new FileEntryInfo(); - string volumeName = string.IsNullOrEmpty(fs.XmlFSType.VolumeName) + string volumeName = string.IsNullOrEmpty(fs.XmlFsType.VolumeName) ? "NO NAME" - : fs.XmlFSType.VolumeName; + : fs.XmlFsType.VolumeName; error = fs.Stat(entry, ref stat); if(error == Errno.NoError) @@ -651,11 +641,11 @@ namespace DiscImageChef.Commands if(error != Errno.NoError) continue; Directory.CreateDirectory(Path.Combine(options.OutputDir, - fs.XmlFSType.Type, volumeName, + fs.XmlFsType.Type, volumeName, ".xattrs", xattr)); outputPath = - Path.Combine(options.OutputDir, fs.XmlFSType.Type, volumeName, + Path.Combine(options.OutputDir, fs.XmlFsType.Type, volumeName, ".xattrs", xattr, entry); if(!File.Exists(outputPath)) @@ -694,10 +684,10 @@ namespace DiscImageChef.Commands } } - Directory.CreateDirectory(Path.Combine(options.OutputDir, fs.XmlFSType.Type, + Directory.CreateDirectory(Path.Combine(options.OutputDir, fs.XmlFsType.Type, volumeName)); - outputPath = Path.Combine(options.OutputDir, fs.XmlFSType.Type, volumeName, entry); + outputPath = Path.Combine(options.OutputDir, fs.XmlFsType.Type, volumeName, entry); if(!File.Exists(outputPath)) { @@ -740,7 +730,7 @@ namespace DiscImageChef.Commands } else DicConsole.ErrorWriteLine("Error {0} reading root directory {0}", error.ToString()); - Core.Statistics.AddFilesystem(fs.XmlFSType.Type); + Core.Statistics.AddFilesystem(fs.XmlFsType.Type); } else DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString()); } diff --git a/DiscImageChef/Commands/Formats.cs b/DiscImageChef/Commands/Formats.cs index 7df4e04d..ed3220ae 100644 --- a/DiscImageChef/Commands/Formats.cs +++ b/DiscImageChef/Commands/Formats.cs @@ -50,32 +50,32 @@ namespace DiscImageChef.Commands DicConsole.WriteLine("Supported filters:"); if(formatsOptions.Verbose) DicConsole.VerboseWriteLine("GUID\t\t\t\t\tFilter"); - foreach(KeyValuePair kvp in filtersList.Filters) - if(formatsOptions.Verbose) DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.UUID, kvp.Value.Name); + foreach(KeyValuePair kvp in filtersList.Filters) + if(formatsOptions.Verbose) DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name); else DicConsole.WriteLine(kvp.Value.Name); DicConsole.WriteLine(); DicConsole.WriteLine("Supported disc image formats:"); if(formatsOptions.Verbose) DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin"); - foreach(KeyValuePair kvp in plugins.ImagePluginsList) + foreach(KeyValuePair kvp in plugins.ImagePluginsList) if(formatsOptions.Verbose) - DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.PluginUuid, kvp.Value.Name); + DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name); else DicConsole.WriteLine(kvp.Value.Name); DicConsole.WriteLine(); DicConsole.WriteLine("Supported filesystems:"); if(formatsOptions.Verbose) DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin"); - foreach(KeyValuePair kvp in plugins.PluginsList) + foreach(KeyValuePair kvp in plugins.PluginsList) if(formatsOptions.Verbose) - DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.PluginUuid, kvp.Value.Name); + DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name); else DicConsole.WriteLine(kvp.Value.Name); DicConsole.WriteLine(); DicConsole.WriteLine("Supported partitioning schemes:"); if(formatsOptions.Verbose) DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin"); - foreach(KeyValuePair kvp in plugins.PartPluginsList) + foreach(KeyValuePair kvp in plugins.PartPluginsList) if(formatsOptions.Verbose) - DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.PluginUuid, kvp.Value.Name); + DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name); else DicConsole.WriteLine(kvp.Value.Name); Core.Statistics.AddCommand("formats"); diff --git a/DiscImageChef/Commands/Ls.cs b/DiscImageChef/Commands/Ls.cs index 91d86b94..ee63b095 100644 --- a/DiscImageChef/Commands/Ls.cs +++ b/DiscImageChef/Commands/Ls.cs @@ -51,7 +51,7 @@ namespace DiscImageChef.Commands DicConsole.DebugWriteLine("Ls command", "--input={0}", options.InputFile); FiltersList filtersList = new FiltersList(); - Filter inputFilter = filtersList.GetFilter(options.InputFile); + IFilter inputFilter = filtersList.GetFilter(options.InputFile); if(inputFilter == null) { @@ -74,11 +74,11 @@ namespace DiscImageChef.Commands } PluginBase plugins = new PluginBase(); - plugins.RegisterAllPlugins(encoding); + plugins.RegisterAllPlugins(); try { - ImagePlugin imageFormat = ImageFormat.Detect(inputFilter); + IMediaImage imageFormat = ImageFormat.Detect(inputFilter); if(imageFormat == null) { @@ -88,7 +88,7 @@ namespace DiscImageChef.Commands if(options.Verbose) DicConsole.VerboseWriteLine("Image format identified by {0} ({1}).", imageFormat.Name, - imageFormat.PluginUuid); + imageFormat.Id); else DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name); try @@ -102,13 +102,13 @@ namespace DiscImageChef.Commands DicConsole.DebugWriteLine("Ls command", "Correctly opened image file."); DicConsole.DebugWriteLine("Ls command", "Image without headers is {0} bytes.", - imageFormat.ImageInfo.ImageSize); - DicConsole.DebugWriteLine("Ls command", "Image has {0} sectors.", imageFormat.ImageInfo.Sectors); + imageFormat.Info.ImageSize); + DicConsole.DebugWriteLine("Ls command", "Image has {0} sectors.", imageFormat.Info.Sectors); DicConsole.DebugWriteLine("Ls command", "Image identifies disk type as {0}.", - imageFormat.ImageInfo.MediaType); + imageFormat.Info.MediaType); Core.Statistics.AddMediaFormat(imageFormat.ImageFormat); - Core.Statistics.AddMedia(imageFormat.ImageInfo.MediaType, false); + Core.Statistics.AddMedia(imageFormat.Info.MediaType, false); Core.Statistics.AddFilter(inputFilter.Name); } catch(Exception ex) @@ -122,7 +122,7 @@ namespace DiscImageChef.Commands Core.Partitions.AddSchemesToStats(partitions); List idPlugins; - Filesystem plugin; + IFilesystem plugin; Errno error; if(partitions.Count == 0) DicConsole.DebugWriteLine("Ls command", "No partitions found"); else @@ -146,15 +146,12 @@ namespace DiscImageChef.Commands if(plugins.PluginsList.TryGetValue(pluginName, out plugin)) { DicConsole.WriteLine($"As identified by {plugin.Name}."); - Filesystem fs = (Filesystem)plugin - .GetType().GetConstructor(new[] - { - typeof(ImagePlugin), typeof(Partition), typeof(Encoding) - })?.Invoke(new object[] {imageFormat, partitions[i], null}); + IFilesystem fs = (IFilesystem)plugin + .GetType().GetConstructor(Type.EmptyTypes)?.Invoke(new object[] { }); if(fs == null) continue; - error = fs.Mount(options.Debug); + error = fs.Mount(imageFormat, partitions[i], encoding, options.Debug); if(error == Errno.NoError) { List rootDir = new List(); @@ -165,7 +162,7 @@ namespace DiscImageChef.Commands DicConsole.ErrorWriteLine("Error {0} reading root directory {0}", error.ToString()); - Core.Statistics.AddFilesystem(fs.XmlFSType.Type); + Core.Statistics.AddFilesystem(fs.XmlFsType.Type); } else DicConsole.ErrorWriteLine("Unable to mount device, error {0}", @@ -178,14 +175,11 @@ namespace DiscImageChef.Commands if(plugin == null) continue; DicConsole.WriteLine($"Identified by {plugin.Name}."); - Filesystem fs = (Filesystem)plugin - .GetType().GetConstructor(new[] - { - typeof(ImagePlugin), typeof(Partition), typeof(Encoding) - })?.Invoke(new object[] {imageFormat, partitions[i], null}); + IFilesystem fs = (IFilesystem)plugin + .GetType().GetConstructor(Type.EmptyTypes)?.Invoke(new object[] { }); if(fs == null) continue; - error = fs.Mount(options.Debug); + error = fs.Mount(imageFormat, partitions[i], encoding, options.Debug); if(error == Errno.NoError) { List rootDir = new List(); @@ -195,7 +189,7 @@ namespace DiscImageChef.Commands else DicConsole.ErrorWriteLine("Error {0} reading root directory {0}", error.ToString()); - Core.Statistics.AddFilesystem(fs.XmlFSType.Type); + Core.Statistics.AddFilesystem(fs.XmlFsType.Type); } else DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString()); } @@ -205,8 +199,8 @@ namespace DiscImageChef.Commands Partition wholePart = new Partition { Name = "Whole device", - Length = imageFormat.ImageInfo.Sectors, - Size = imageFormat.ImageInfo.Sectors * imageFormat.ImageInfo.SectorSize + Length = imageFormat.Info.Sectors, + Size = imageFormat.Info.Sectors * imageFormat.Info.SectorSize }; Core.Filesystems.Identify(imageFormat, out idPlugins, wholePart); @@ -219,14 +213,11 @@ namespace DiscImageChef.Commands if(plugins.PluginsList.TryGetValue(pluginName, out plugin)) { DicConsole.WriteLine($"As identified by {plugin.Name}."); - Filesystem fs = (Filesystem)plugin - .GetType().GetConstructor(new[] - { - typeof(ImagePlugin), typeof(Partition), typeof(Encoding) - })?.Invoke(new object[] {imageFormat, wholePart, null}); + IFilesystem fs = (IFilesystem)plugin + .GetType().GetConstructor(Type.EmptyTypes)?.Invoke(new object[] { }); if(fs == null) continue; - error = fs.Mount(options.Debug); + error = fs.Mount(imageFormat, wholePart, encoding, options.Debug); if(error == Errno.NoError) { List rootDir = new List(); @@ -236,7 +227,7 @@ namespace DiscImageChef.Commands else DicConsole.ErrorWriteLine("Error {0} reading root directory {0}", error.ToString()); - Core.Statistics.AddFilesystem(fs.XmlFSType.Type); + Core.Statistics.AddFilesystem(fs.XmlFsType.Type); } else DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString()); } @@ -247,12 +238,11 @@ namespace DiscImageChef.Commands if(plugin != null) { DicConsole.WriteLine($"Identified by {plugin.Name}."); - Filesystem fs = (Filesystem)plugin - .GetType().GetConstructor(new[] {typeof(ImagePlugin), typeof(Partition), typeof(Encoding)}) - ?.Invoke(new object[] {imageFormat, wholePart, null}); + IFilesystem fs = (IFilesystem)plugin + .GetType().GetConstructor(Type.EmptyTypes)?.Invoke(new object[] { }); if(fs != null) { - error = fs.Mount(options.Debug); + error = fs.Mount(imageFormat, wholePart, encoding, options.Debug); if(error == Errno.NoError) { List rootDir = new List(); @@ -288,7 +278,7 @@ namespace DiscImageChef.Commands else DicConsole.ErrorWriteLine("Error {0} reading root directory {0}", error.ToString()); - Core.Statistics.AddFilesystem(fs.XmlFSType.Type); + Core.Statistics.AddFilesystem(fs.XmlFsType.Type); } else DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString()); } diff --git a/DiscImageChef/Commands/PrintHex.cs b/DiscImageChef/Commands/PrintHex.cs index f1edf4e8..ccc6817e 100644 --- a/DiscImageChef/Commands/PrintHex.cs +++ b/DiscImageChef/Commands/PrintHex.cs @@ -50,7 +50,7 @@ namespace DiscImageChef.Commands DicConsole.DebugWriteLine("PrintHex command", "--WidthBytes={0}", options.WidthBytes); FiltersList filtersList = new FiltersList(); - Filter inputFilter = filtersList.GetFilter(options.InputFile); + IFilter inputFilter = filtersList.GetFilter(options.InputFile); if(inputFilter == null) { @@ -58,7 +58,7 @@ namespace DiscImageChef.Commands return; } - ImagePlugin inputFormat = ImageFormat.Detect(inputFilter); + IMediaImage inputFormat = ImageFormat.Detect(inputFilter); if(inputFormat == null) { @@ -72,7 +72,7 @@ namespace DiscImageChef.Commands { DicConsole.WriteLine("Sector {0}", options.StartSector + i); - if(inputFormat.ImageInfo.ReadableSectorTags == null) + if(inputFormat.Info.ReadableSectorTags == null) { DicConsole .WriteLine("Requested sectors with tags, unsupported by underlying image format, printing only user data."); @@ -80,7 +80,7 @@ namespace DiscImageChef.Commands } else { - if(inputFormat.ImageInfo.ReadableSectorTags.Count == 0) + if(inputFormat.Info.ReadableSectorTags.Count == 0) { DicConsole .WriteLine("Requested sectors with tags, unsupported by underlying image format, printing only user data."); diff --git a/DiscImageChef/Commands/Verify.cs b/DiscImageChef/Commands/Verify.cs index 46d9baa0..4a9e4ddc 100644 --- a/DiscImageChef/Commands/Verify.cs +++ b/DiscImageChef/Commands/Verify.cs @@ -50,7 +50,7 @@ namespace DiscImageChef.Commands DicConsole.DebugWriteLine("Verify command", "--verify-sectors={0}", options.VerifySectors); FiltersList filtersList = new FiltersList(); - Filter inputFilter = filtersList.GetFilter(options.InputFile); + IFilter inputFilter = filtersList.GetFilter(options.InputFile); if(inputFilter == null) { @@ -58,7 +58,7 @@ namespace DiscImageChef.Commands return; } - ImagePlugin inputFormat = ImageFormat.Detect(inputFilter); + IMediaImage inputFormat = ImageFormat.Detect(inputFilter); if(inputFormat == null) { @@ -68,7 +68,7 @@ namespace DiscImageChef.Commands inputFormat.OpenImage(inputFilter); Core.Statistics.AddMediaFormat(inputFormat.ImageFormat); - Core.Statistics.AddMedia(inputFormat.ImageInfo.MediaType, false); + Core.Statistics.AddMedia(inputFormat.Info.MediaType, false); Core.Statistics.AddFilter(inputFilter.Name); bool? correctDisc = null; @@ -132,7 +132,7 @@ namespace DiscImageChef.Commands while(remainingSectors > 0) { DicConsole.Write("\rChecking sector {0} of {1}, on track {2}", currentSectorAll, - inputFormat.ImageInfo.Sectors, currentTrack.TrackSequence); + inputFormat.Info.Sectors, currentTrack.TrackSequence); List tempfailingLbas; List tempunknownLbas; @@ -174,13 +174,13 @@ namespace DiscImageChef.Commands } else { - ulong remainingSectors = inputFormat.ImageInfo.Sectors; + ulong remainingSectors = inputFormat.Info.Sectors; ulong currentSector = 0; startCheck = DateTime.UtcNow; while(remainingSectors > 0) { - DicConsole.Write("\rChecking sector {0} of {1}", currentSector, inputFormat.ImageInfo.Sectors); + DicConsole.Write("\rChecking sector {0} of {1}", currentSector, inputFormat.Info.Sectors); List tempfailingLbas; List tempunknownLbas; @@ -239,22 +239,22 @@ namespace DiscImageChef.Commands if(options.Verbose) { DicConsole.VerboseWriteLine("LBAs with error:"); - if(failingLbas.Count == (int)inputFormat.ImageInfo.Sectors) + if(failingLbas.Count == (int)inputFormat.Info.Sectors) DicConsole.VerboseWriteLine("\tall sectors."); else foreach(ulong t in failingLbas) DicConsole.VerboseWriteLine("\t{0}", t); DicConsole.WriteLine("LBAs without checksum:"); - if(unknownLbas.Count == (int)inputFormat.ImageInfo.Sectors) + if(unknownLbas.Count == (int)inputFormat.Info.Sectors) DicConsole.VerboseWriteLine("\tall sectors."); else foreach(ulong t in unknownLbas) DicConsole.VerboseWriteLine("\t{0}", t); } - DicConsole.WriteLine("Total sectors........... {0}", inputFormat.ImageInfo.Sectors); + DicConsole.WriteLine("Total sectors........... {0}", inputFormat.Info.Sectors); DicConsole.WriteLine("Total errors............ {0}", failingLbas.Count); DicConsole.WriteLine("Total unknowns.......... {0}", unknownLbas.Count); DicConsole.WriteLine("Total errors+unknowns... {0}", failingLbas.Count + unknownLbas.Count); - totalSectors = (long)inputFormat.ImageInfo.Sectors; + totalSectors = (long)inputFormat.Info.Sectors; errorSectors = failingLbas.Count; unknownSectors = unknownLbas.Count; correctSectors = totalSectors - errorSectors - unknownSectors;