// /*************************************************************************** // The Disc Image Chef // ---------------------------------------------------------------------------- // // Filename : BlockMedia.cs // Version : 1.0 // Author(s) : Natalia Portillo // // Component : Component // // Revision : $Revision$ // Last change by : $Author$ // Date : $Date$ // // --[ Description ] ---------------------------------------------------------- // // Description // // --[ License ] -------------------------------------------------------------- // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program 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 General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // // ---------------------------------------------------------------------------- // Copyright (C) 2011-2015 Claunia.com // ****************************************************************************/ // //$Id$ using System.Collections.Generic; using System.IO; using DiscImageChef.CommonTypes; using DiscImageChef.Decoders.PCMCIA; using DiscImageChef.Filesystems; using DiscImageChef.ImagePlugins; using Schemas; namespace DiscImageChef.Core { public static partial class Sidecar { static void BlockMedia(ImagePlugin image, System.Guid filterId, string imagePath, FileInfo fi, PluginBase plugins, List imgChecksums, ref CICMMetadataType sidecar) { sidecar.BlockMedia = new[] { new BlockMediaType { Checksums = imgChecksums.ToArray(), Image = new ImageType { format = image.GetImageFormat(), offset = 0, offsetSpecified = true, Value = Path.GetFileName(imagePath) }, Size = fi.Length, Sequence = new SequenceType { MediaTitle = image.GetImageName() } } }; if(image.GetMediaSequence() != 0 && image.GetLastDiskSequence() != 0) { sidecar.BlockMedia[0].Sequence.MediaSequence = image.GetMediaSequence(); sidecar.BlockMedia[0].Sequence.TotalMedia = image.GetMediaSequence(); } else { sidecar.BlockMedia[0].Sequence.MediaSequence = 1; sidecar.BlockMedia[0].Sequence.TotalMedia = 1; } foreach(MediaTagType tagType in image.ImageInfo.readableMediaTags) { switch(tagType) { case MediaTagType.ATAPI_IDENTIFY: sidecar.BlockMedia[0].ATA = new ATAType { Identify = new DumpType { Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.ATAPI_IDENTIFY)).ToArray(), Size = image.ReadDiskTag(MediaTagType.ATAPI_IDENTIFY).Length } }; break; case MediaTagType.ATA_IDENTIFY: sidecar.BlockMedia[0].ATA = new ATAType { Identify = new DumpType { Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.ATA_IDENTIFY)).ToArray(), Size = image.ReadDiskTag(MediaTagType.ATA_IDENTIFY).Length } }; break; case MediaTagType.PCMCIA_CIS: byte[] cis = image.ReadDiskTag(MediaTagType.PCMCIA_CIS); sidecar.BlockMedia[0].PCMCIA = new PCMCIAType { CIS = new DumpType { Checksums = Checksum.GetChecksums(cis).ToArray(), Size = cis.Length } }; Tuple[] tuples = CIS.GetTuples(cis); if(tuples != null) { foreach(Tuple tuple in tuples) { if(tuple.Code == TupleCodes.CISTPL_MANFID) { ManufacturerIdentificationTuple manfid = CIS.DecodeManufacturerIdentificationTuple(tuple); if(manfid != null) { sidecar.BlockMedia[0].PCMCIA.ManufacturerCode = manfid.ManufacturerID; sidecar.BlockMedia[0].PCMCIA.CardCode = manfid.CardID; sidecar.BlockMedia[0].PCMCIA.ManufacturerCodeSpecified = true; sidecar.BlockMedia[0].PCMCIA.CardCodeSpecified = true; } } else if(tuple.Code == TupleCodes.CISTPL_VERS_1) { Level1VersionTuple vers = CIS.DecodeLevel1VersionTuple(tuple); if(vers != null) { sidecar.BlockMedia[0].PCMCIA.Manufacturer = vers.Manufacturer; sidecar.BlockMedia[0].PCMCIA.ProductName = vers.Product; sidecar.BlockMedia[0].PCMCIA.Compliance = string.Format("{0}.{1}", vers.MajorVersion, vers.MinorVersion); sidecar.BlockMedia[0].PCMCIA.AdditionalInformation = vers.AdditionalInformation; } } } } break; case MediaTagType.SCSI_INQUIRY: sidecar.BlockMedia[0].SCSI = new SCSIType { Inquiry = new DumpType { Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.SCSI_INQUIRY)).ToArray(), Size = image.ReadDiskTag(MediaTagType.SCSI_INQUIRY).Length } }; break; case MediaTagType.SD_CID: if(sidecar.BlockMedia[0].SecureDigital == null) sidecar.BlockMedia[0].SecureDigital = new SecureDigitalType(); sidecar.BlockMedia[0].SecureDigital.CID = new DumpType { Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.SD_CID)).ToArray(), Size = image.ReadDiskTag(MediaTagType.SD_CID).Length }; break; case MediaTagType.SD_CSD: if(sidecar.BlockMedia[0].SecureDigital == null) sidecar.BlockMedia[0].SecureDigital = new SecureDigitalType(); sidecar.BlockMedia[0].SecureDigital.CSD = new DumpType { Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.SD_CSD)).ToArray(), Size = image.ReadDiskTag(MediaTagType.SD_CSD).Length }; break; case MediaTagType.SD_ExtendedCSD: if(sidecar.BlockMedia[0].SecureDigital == null) sidecar.BlockMedia[0].SecureDigital = new SecureDigitalType(); sidecar.BlockMedia[0].SecureDigital.ExtendedCSD = new DumpType { Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.SD_ExtendedCSD)).ToArray(), Size = image.ReadDiskTag(MediaTagType.SD_ExtendedCSD).Length }; break; } } // 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 System.Guid("12345678-AAAA-BBBB-CCCC-123456789000") && filterId == new System.Guid("12345678-AAAA-BBBB-CCCC-123456789000")) { sidecar.BlockMedia[0].ContentChecksums = sidecar.BlockMedia[0].Checksums; } else { Checksum contentChkWorker = new Checksum(); // For fast debugging, skip checksum //goto skipImageChecksum; uint sectorsToRead = 512; ulong sectors = image.GetSectors(); ulong doneSectors = 0; InitProgress2(); while(doneSectors < sectors) { byte[] sector; if((sectors - doneSectors) >= sectorsToRead) { sector = image.ReadSectors(doneSectors, sectorsToRead); UpdateProgress2("Hashings sector {0} of {1}", (long)doneSectors, (long)sectors); doneSectors += sectorsToRead; } else { sector = image.ReadSectors(doneSectors, (uint)(sectors - doneSectors)); UpdateProgress2("Hashings sector {0} of {1}", (long)doneSectors, (long)sectors); doneSectors += (sectors - doneSectors); } contentChkWorker.Update(sector); } // For fast debugging, skip checksum //skipImageChecksum: List cntChecksums = contentChkWorker.End(); sidecar.BlockMedia[0].ContentChecksums = cntChecksums.ToArray(); EndProgress2(); } Metadata.MediaType.MediaTypeToString(image.ImageInfo.mediaType, out string dskType, out string dskSubType); sidecar.BlockMedia[0].DiskType = dskType; sidecar.BlockMedia[0].DiskSubType = dskSubType; Statistics.AddMedia(image.ImageInfo.mediaType, false); sidecar.BlockMedia[0].Dimensions = Metadata.Dimensions.DimensionsFromMediaType(image.ImageInfo.mediaType); sidecar.BlockMedia[0].LogicalBlocks = (long)image.GetSectors(); sidecar.BlockMedia[0].LogicalBlockSize = (int)image.GetSectorSize(); // TODO: Detect it sidecar.BlockMedia[0].PhysicalBlockSize = (int)image.GetSectorSize(); UpdateStatus("Checking filesystems..."); List partitions = Partitions.GetAll(image); Partitions.AddSchemesToStats(partitions); sidecar.BlockMedia[0].FileSystemInformation = new PartitionType[1]; if(partitions.Count > 0) { sidecar.BlockMedia[0].FileSystemInformation = new PartitionType[partitions.Count]; for(int i = 0; i < partitions.Count; i++) { sidecar.BlockMedia[0].FileSystemInformation[i] = new PartitionType { Description = partitions[i].Description, EndSector = (int)(partitions[i].End), Name = partitions[i].Name, Sequence = (int)partitions[i].Sequence, StartSector = (int)partitions[i].Start, Type = partitions[i].Type }; List lstFs = new List(); foreach(Filesystem _plugin in plugins.PluginsList.Values) { try { if(_plugin.Identify(image, partitions[i])) { _plugin.GetInformation(image, partitions[i], out string foo); 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 #pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body { //DicConsole.DebugWriteLine("Create-sidecar command", "Plugin {0} crashed", _plugin.Name); } } if(lstFs.Count > 0) sidecar.BlockMedia[0].FileSystemInformation[i].FileSystems = lstFs.ToArray(); } } else { sidecar.BlockMedia[0].FileSystemInformation[0] = new PartitionType { StartSector = 0, EndSector = (int)(image.GetSectors() - 1) }; Partition wholePart = new Partition { Name = "Whole device", Length = image.GetSectors(), Size = image.GetSectors() * image.GetSectorSize() }; List lstFs = new List(); foreach(Filesystem _plugin in plugins.PluginsList.Values) { try { if(_plugin.Identify(image, wholePart)) { _plugin.GetInformation(image, wholePart, out string foo); 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 #pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body { //DicConsole.DebugWriteLine("Create-sidecar command", "Plugin {0} crashed", _plugin.Name); } } 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) { 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; } if(image.ImageInfo.readableMediaTags.Contains(MediaTagType.ATA_IDENTIFY)) { Decoders.ATA.Identify.IdentifyDevice? ataId = Decoders.ATA.Identify.Decode(image.ReadDiskTag(MediaTagType.ATA_IDENTIFY)); if(ataId.HasValue) { if(ataId.Value.CurrentCylinders > 0 && ataId.Value.CurrentHeads > 0 && ataId.Value.CurrentSectorsPerTrack > 0) { sidecar.BlockMedia[0].CylindersSpecified = true; sidecar.BlockMedia[0].HeadsSpecified = true; sidecar.BlockMedia[0].SectorsPerTrackSpecified = true; sidecar.BlockMedia[0].Cylinders = ataId.Value.CurrentCylinders; sidecar.BlockMedia[0].Heads = ataId.Value.CurrentHeads; sidecar.BlockMedia[0].SectorsPerTrack = ataId.Value.CurrentSectorsPerTrack; } else if(ataId.Value.Cylinders > 0 && ataId.Value.Heads > 0 && ataId.Value.SectorsPerTrack > 0) { sidecar.BlockMedia[0].CylindersSpecified = true; sidecar.BlockMedia[0].HeadsSpecified = true; sidecar.BlockMedia[0].SectorsPerTrackSpecified = true; sidecar.BlockMedia[0].Cylinders = ataId.Value.Cylinders; sidecar.BlockMedia[0].Heads = ataId.Value.Heads; sidecar.BlockMedia[0].SectorsPerTrack = ataId.Value.SectorsPerTrack; } } } // TODO: Implement support for getting CHS from SCSI mode pages } } }