internal Dictionary <ChecksumType, string> End() => new Dictionary <ChecksumType, string> { [ChecksumType.Crc32] = _crc32Ctx.End(), [ChecksumType.Md5] = _md5Ctx.End(), [ChecksumType.Sha1] = _sha1Ctx.End(), [ChecksumType.Sha256] = _sha256Ctx.End(), [ChecksumType.Sha384] = _sha384Ctx.End(), [ChecksumType.Sha512] = _sha512Ctx.End() };
public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { Encoding = encoding ?? Encoding.GetEncoding("iso-8859-1"); StringBuilder sbInformation = new StringBuilder(); XmlFsType = new FileSystemType(); information = null; BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; byte[] bootBlockSectors = imagePlugin.ReadSectors(0 + partition.Start, 2); BootBlock bootBlk = Marshal.ByteArrayToStructureBigEndian <BootBlock>(bootBlockSectors); bootBlk.bootCode = new byte[bootBlockSectors.Length - 12]; Array.Copy(bootBlockSectors, 12, bootBlk.bootCode, 0, bootBlk.bootCode.Length); bootBlockSectors[4] = bootBlockSectors[5] = bootBlockSectors[6] = bootBlockSectors[7] = 0; uint bsum = AmigaBootChecksum(bootBlockSectors); ulong bRootPtr = 0; // If bootblock is correct, let's take its rootblock pointer if (bsum == bootBlk.checksum) { bRootPtr = bootBlk.root_ptr + partition.Start; DicConsole.DebugWriteLine("AmigaDOS plugin", "Bootblock points to {0} as Rootblock", bRootPtr); } ulong[] rootPtrs = { bRootPtr + partition.Start, (partition.End - partition.Start + 1) / 2 + partition.Start - 2, (partition.End - partition.Start + 1) / 2 + partition.Start - 1, (partition.End - partition.Start + 1) / 2 + partition.Start, (partition.End - partition.Start + 1) / 2 + partition.Start + 4 }; RootBlock rootBlk = new RootBlock(); byte[] rootBlockSector = null; bool rootFound = false; uint blockSize = 0; // So to handle even number of sectors foreach (ulong rootPtr in rootPtrs.Where(rootPtr => rootPtr < partition.End && rootPtr >= partition.Start)) { DicConsole.DebugWriteLine("AmigaDOS plugin", "Searching for Rootblock in sector {0}", rootPtr); rootBlockSector = imagePlugin.ReadSector(rootPtr); rootBlk.type = BigEndianBitConverter.ToUInt32(rootBlockSector, 0x00); DicConsole.DebugWriteLine("AmigaDOS plugin", "rootBlk.type = {0}", rootBlk.type); if (rootBlk.type != TYPE_HEADER) { continue; } rootBlk.hashTableSize = BigEndianBitConverter.ToUInt32(rootBlockSector, 0x0C); DicConsole.DebugWriteLine("AmigaDOS plugin", "rootBlk.hashTableSize = {0}", rootBlk.hashTableSize); blockSize = (rootBlk.hashTableSize + 56) * 4; uint sectorsPerBlock = (uint)(blockSize / rootBlockSector.Length); DicConsole.DebugWriteLine("AmigaDOS plugin", "blockSize = {0}", blockSize); DicConsole.DebugWriteLine("AmigaDOS plugin", "sectorsPerBlock = {0}", sectorsPerBlock); if (blockSize % rootBlockSector.Length > 0) { sectorsPerBlock++; } if (rootPtr + sectorsPerBlock >= partition.End) { continue; } rootBlockSector = imagePlugin.ReadSectors(rootPtr, sectorsPerBlock); // Clear checksum on sector rootBlk.checksum = BigEndianBitConverter.ToUInt32(rootBlockSector, 20); rootBlockSector[20] = rootBlockSector[21] = rootBlockSector[22] = rootBlockSector[23] = 0; uint rsum = AmigaChecksum(rootBlockSector); DicConsole.DebugWriteLine("AmigaDOS plugin", "rootBlk.checksum = 0x{0:X8}", rootBlk.checksum); DicConsole.DebugWriteLine("AmigaDOS plugin", "rsum = 0x{0:X8}", rsum); rootBlk.sec_type = BigEndianBitConverter.ToUInt32(rootBlockSector, rootBlockSector.Length - 4); DicConsole.DebugWriteLine("AmigaDOS plugin", "rootBlk.sec_type = {0}", rootBlk.sec_type); if (rootBlk.sec_type != SUBTYPE_ROOT || rootBlk.checksum != rsum) { continue; } rootBlockSector = imagePlugin.ReadSectors(rootPtr, sectorsPerBlock); rootFound = true; break; } if (!rootFound) { return; } rootBlk = MarshalRootBlock(rootBlockSector); string diskName = StringHandlers.PascalToString(rootBlk.diskName, Encoding); switch (bootBlk.diskType & 0xFF) { case 0: sbInformation.Append("Amiga Original File System"); XmlFsType.Type = "Amiga OFS"; break; case 1: sbInformation.Append("Amiga Fast File System"); XmlFsType.Type = "Amiga FFS"; break; case 2: sbInformation.Append("Amiga Original File System with international characters"); XmlFsType.Type = "Amiga OFS"; break; case 3: sbInformation.Append("Amiga Fast File System with international characters"); XmlFsType.Type = "Amiga FFS"; break; case 4: sbInformation.Append("Amiga Original File System with directory cache"); XmlFsType.Type = "Amiga OFS"; break; case 5: sbInformation.Append("Amiga Fast File System with directory cache"); XmlFsType.Type = "Amiga FFS"; break; case 6: sbInformation.Append("Amiga Original File System with long filenames"); XmlFsType.Type = "Amiga OFS2"; break; case 7: sbInformation.Append("Amiga Fast File System with long filenames"); XmlFsType.Type = "Amiga FFS2"; break; } if ((bootBlk.diskType & 0x6D754600) == 0x6D754600) { sbInformation.Append(", with multi-user patches"); } sbInformation.AppendLine(); sbInformation.AppendFormat("Volume name: {0}", diskName).AppendLine(); if (bootBlk.checksum == bsum) { Sha1Context sha1Ctx = new Sha1Context(); sha1Ctx.Update(bootBlk.bootCode); sbInformation.AppendLine("Volume is bootable"); sbInformation.AppendFormat("Boot code SHA1 is {0}", sha1Ctx.End()).AppendLine(); } if (rootBlk.bitmapFlag == 0xFFFFFFFF) { sbInformation.AppendLine("Volume bitmap is valid"); } if (rootBlk.bitmapExtensionBlock != 0x00000000 && rootBlk.bitmapExtensionBlock != 0xFFFFFFFF) { sbInformation.AppendFormat("Bitmap extension at block {0}", rootBlk.bitmapExtensionBlock).AppendLine(); } if ((bootBlk.diskType & 0xFF) == 4 || (bootBlk.diskType & 0xFF) == 5) { sbInformation.AppendFormat("Directory cache starts at block {0}", rootBlk.extension).AppendLine(); } ulong blocks = (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(); sbInformation.AppendFormat("Volume created on {0}", DateHandlers.AmigaToDateTime(rootBlk.cDays, rootBlk.cMins, rootBlk.cTicks)) .AppendLine(); sbInformation.AppendFormat("Volume last modified on {0}", DateHandlers.AmigaToDateTime(rootBlk.vDays, rootBlk.vMins, rootBlk.vTicks)) .AppendLine(); sbInformation.AppendFormat("Volume root directory last modified on on {0}", DateHandlers.AmigaToDateTime(rootBlk.rDays, rootBlk.rMins, rootBlk.rTicks)) .AppendLine(); 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 = blockSize; XmlFsType.VolumeName = diskName; XmlFsType.Bootable = bsum == bootBlk.checksum; // Useful as a serial XmlFsType.VolumeSerial = $"{rootBlk.checksum:X8}"; }
public bool Open(IFilter imageFilter) { Stream imageStream = imageFilter.GetDataForkStream(); byte[] header = new byte[512]; byte[] footer; imageStream.Seek(0, SeekOrigin.Begin); imageStream.Read(header, 0, 512); if (imageStream.Length % 2 == 0) { footer = new byte[512]; imageStream.Seek(-512, SeekOrigin.End); imageStream.Read(footer, 0, 512); } else { footer = new byte[511]; imageStream.Seek(-511, SeekOrigin.End); imageStream.Read(footer, 0, 511); } BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; uint headerChecksum = BigEndianBitConverter.ToUInt32(header, 0x40); uint footerChecksum = BigEndianBitConverter.ToUInt32(footer, 0x40); ulong headerCookie = BigEndianBitConverter.ToUInt64(header, 0); ulong footerCookie = BigEndianBitConverter.ToUInt64(footer, 0); header[0x40] = 0; header[0x41] = 0; header[0x42] = 0; header[0x43] = 0; footer[0x40] = 0; footer[0x41] = 0; footer[0x42] = 0; footer[0x43] = 0; uint headerCalculatedChecksum = VhdChecksum(header); uint footerCalculatedChecksum = VhdChecksum(footer); DicConsole.DebugWriteLine("VirtualPC plugin", "Header checksum = 0x{0:X8}, calculated = 0x{1:X8}", headerChecksum, headerCalculatedChecksum); DicConsole.DebugWriteLine("VirtualPC plugin", "Header checksum = 0x{0:X8}, calculated = 0x{1:X8}", footerChecksum, footerCalculatedChecksum); byte[] usableHeader; uint usableChecksum; if (headerCookie == IMAGE_COOKIE && headerChecksum == headerCalculatedChecksum) { usableHeader = header; usableChecksum = headerChecksum; } else if (footerCookie == IMAGE_COOKIE && footerChecksum == footerCalculatedChecksum) { usableHeader = footer; usableChecksum = footerChecksum; } else { throw new ImageNotSupportedException("(VirtualPC plugin): Both header and footer are corrupt, image cannot be opened."); } thisFooter = new HardDiskFooter { Cookie = BigEndianBitConverter.ToUInt64(usableHeader, 0x00), Features = BigEndianBitConverter.ToUInt32(usableHeader, 0x08), Version = BigEndianBitConverter.ToUInt32(usableHeader, 0x0C), Offset = BigEndianBitConverter.ToUInt64(usableHeader, 0x10), Timestamp = BigEndianBitConverter.ToUInt32(usableHeader, 0x18), CreatorApplication = BigEndianBitConverter.ToUInt32(usableHeader, 0x1C), CreatorVersion = BigEndianBitConverter.ToUInt32(usableHeader, 0x20), CreatorHostOs = BigEndianBitConverter.ToUInt32(usableHeader, 0x24), OriginalSize = BigEndianBitConverter.ToUInt64(usableHeader, 0x28), CurrentSize = BigEndianBitConverter.ToUInt64(usableHeader, 0x30), DiskGeometry = BigEndianBitConverter.ToUInt32(usableHeader, 0x38), DiskType = BigEndianBitConverter.ToUInt32(usableHeader, 0x3C), Checksum = usableChecksum, UniqueId = BigEndianBitConverter.ToGuid(usableHeader, 0x44), SavedState = usableHeader[0x54], Reserved = new byte[usableHeader.Length - 0x55] }; Array.Copy(usableHeader, 0x55, thisFooter.Reserved, 0, usableHeader.Length - 0x55); thisDateTime = new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc); thisDateTime = thisDateTime.AddSeconds(thisFooter.Timestamp); Sha1Context sha1Ctx = new Sha1Context(); sha1Ctx.Update(thisFooter.Reserved); DicConsole.DebugWriteLine("VirtualPC plugin", "footer.cookie = 0x{0:X8}", thisFooter.Cookie); DicConsole.DebugWriteLine("VirtualPC plugin", "footer.features = 0x{0:X8}", thisFooter.Features); DicConsole.DebugWriteLine("VirtualPC plugin", "footer.version = 0x{0:X8}", thisFooter.Version); DicConsole.DebugWriteLine("VirtualPC plugin", "footer.offset = {0}", thisFooter.Offset); DicConsole.DebugWriteLine("VirtualPC plugin", "footer.timestamp = 0x{0:X8} ({1})", thisFooter.Timestamp, thisDateTime); DicConsole.DebugWriteLine("VirtualPC plugin", "footer.creatorApplication = 0x{0:X8} (\"{1}\")", thisFooter.CreatorApplication, Encoding.ASCII.GetString(BigEndianBitConverter.GetBytes(thisFooter .CreatorApplication))); DicConsole.DebugWriteLine("VirtualPC plugin", "footer.creatorVersion = 0x{0:X8}", thisFooter.CreatorVersion); DicConsole.DebugWriteLine("VirtualPC plugin", "footer.creatorHostOS = 0x{0:X8} (\"{1}\")", thisFooter.CreatorHostOs, Encoding.ASCII.GetString(BigEndianBitConverter .GetBytes(thisFooter.CreatorHostOs))); DicConsole.DebugWriteLine("VirtualPC plugin", "footer.originalSize = {0}", thisFooter.OriginalSize); DicConsole.DebugWriteLine("VirtualPC plugin", "footer.currentSize = {0}", thisFooter.CurrentSize); DicConsole.DebugWriteLine("VirtualPC plugin", "footer.diskGeometry = 0x{0:X8} (C/H/S: {1}/{2}/{3})", thisFooter.DiskGeometry, (thisFooter.DiskGeometry & 0xFFFF0000) >> 16, (thisFooter.DiskGeometry & 0xFF00) >> 8, thisFooter.DiskGeometry & 0xFF); DicConsole.DebugWriteLine("VirtualPC plugin", "footer.diskType = 0x{0:X8}", thisFooter.DiskType); DicConsole.DebugWriteLine("VirtualPC plugin", "footer.checksum = 0x{0:X8}", thisFooter.Checksum); DicConsole.DebugWriteLine("VirtualPC plugin", "footer.uniqueId = {0}", thisFooter.UniqueId); 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"; } else { throw new ImageNotSupportedException($"(VirtualPC plugin): Unknown image type {thisFooter.DiskType} found. Please submit a bug with an example image."); } switch (thisFooter.CreatorApplication) { case CREATOR_QEMU: { imageInfo.Application = "QEMU"; // QEMU always set same version imageInfo.ApplicationVersion = "Unknown"; break; } case CREATOR_VIRTUAL_BOX: { 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"; break; case CREATOR_WINDOWS: // VirtualBox uses Windows creator for any other OS imageInfo.Application = "VirtualBox"; break; default: imageInfo.Application = $"VirtualBox for unknown OS \"{Encoding.ASCII.GetString(BigEndianBitConverter.GetBytes(thisFooter.CreatorHostOs))}\""; break; } break; } case CREATOR_VIRTUAL_SERVER: { imageInfo.Application = "Microsoft Virtual Server"; switch (thisFooter.CreatorVersion) { case VERSION_VIRTUAL_SERVER2004: imageInfo.ApplicationVersion = "2004"; break; default: imageInfo.ApplicationVersion = $"Unknown version 0x{thisFooter.CreatorVersion:X8}"; break; } break; } case CREATOR_VIRTUAL_PC: { switch (thisFooter.CreatorHostOs) { case CREATOR_MACINTOSH: case CREATOR_MACINTOSH_OLD: switch (thisFooter.CreatorVersion) { case VERSION_VIRTUAL_PC_MAC: imageInfo.Application = "Connectix Virtual PC"; imageInfo.ApplicationVersion = "5, 6 or 7"; break; default: imageInfo.ApplicationVersion = $"Unknown version 0x{thisFooter.CreatorVersion:X8}"; break; } break; case CREATOR_WINDOWS: switch (thisFooter.CreatorVersion) { case VERSION_VIRTUAL_PC_MAC: imageInfo.Application = "Connectix Virtual PC"; imageInfo.ApplicationVersion = "5, 6 or 7"; break; case VERSION_VIRTUAL_PC2004: imageInfo.Application = "Microsoft Virtual PC"; imageInfo.ApplicationVersion = "2004"; break; case VERSION_VIRTUAL_PC2007: imageInfo.Application = "Microsoft Virtual PC"; imageInfo.ApplicationVersion = "2007"; break; default: imageInfo.ApplicationVersion = $"Unknown version 0x{thisFooter.CreatorVersion:X8}"; break; } break; default: imageInfo.Application = $"Virtual PC for unknown OS \"{Encoding.ASCII.GetString(BigEndianBitConverter.GetBytes(thisFooter.CreatorHostOs))}\""; imageInfo.ApplicationVersion = $"Unknown version 0x{thisFooter.CreatorVersion:X8}"; break; } break; } case CREATOR_DISCIMAGECHEF: { imageInfo.Application = "DiscImageChef"; imageInfo.ApplicationVersion = $"{(thisFooter.CreatorVersion & 0xFF000000) >> 24}.{(thisFooter.CreatorVersion & 0xFF0000) >> 16}.{(thisFooter.CreatorVersion & 0xFF00) >> 8}.{thisFooter.CreatorVersion & 0xFF}"; } break; default: { imageInfo.Application = $"Unknown application \"{Encoding.ASCII.GetString(BigEndianBitConverter.GetBytes(thisFooter.CreatorHostOs))}\""; imageInfo.ApplicationVersion = $"Unknown version 0x{thisFooter.CreatorVersion:X8}"; break; } } thisFilter = imageFilter; 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.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) { imageStream.Seek((long)thisFooter.Offset, SeekOrigin.Begin); byte[] dynamicBytes = new byte[1024]; imageStream.Read(dynamicBytes, 0, 1024); uint dynamicChecksum = BigEndianBitConverter.ToUInt32(dynamicBytes, 0x24); dynamicBytes[0x24] = 0; dynamicBytes[0x25] = 0; dynamicBytes[0x26] = 0; dynamicBytes[0x27] = 0; uint dynamicChecksumCalculated = VhdChecksum(dynamicBytes); DicConsole.DebugWriteLine("VirtualPC plugin", "Dynamic header checksum = 0x{0:X8}, calculated = 0x{1:X8}", dynamicChecksum, dynamicChecksumCalculated); if (dynamicChecksum != dynamicChecksumCalculated) { throw new ImageNotSupportedException("(VirtualPC plugin): Both header and footer are corrupt, image cannot be opened."); } thisDynamic = new DynamicDiskHeader { LocatorEntries = new ParentLocatorEntry[8], Reserved2 = new byte[256] }; for (int i = 0; i < 8; i++) { thisDynamic.LocatorEntries[i] = new ParentLocatorEntry(); } thisDynamic.Cookie = BigEndianBitConverter.ToUInt64(dynamicBytes, 0x00); thisDynamic.DataOffset = BigEndianBitConverter.ToUInt64(dynamicBytes, 0x08); thisDynamic.TableOffset = BigEndianBitConverter.ToUInt64(dynamicBytes, 0x10); thisDynamic.HeaderVersion = BigEndianBitConverter.ToUInt32(dynamicBytes, 0x18); thisDynamic.MaxTableEntries = BigEndianBitConverter.ToUInt32(dynamicBytes, 0x1C); thisDynamic.BlockSize = BigEndianBitConverter.ToUInt32(dynamicBytes, 0x20); thisDynamic.Checksum = dynamicChecksum; thisDynamic.ParentId = BigEndianBitConverter.ToGuid(dynamicBytes, 0x28); thisDynamic.ParentTimestamp = BigEndianBitConverter.ToUInt32(dynamicBytes, 0x38); thisDynamic.Reserved = BigEndianBitConverter.ToUInt32(dynamicBytes, 0x3C); thisDynamic.ParentName = Encoding.BigEndianUnicode.GetString(dynamicBytes, 0x40, 512); for (int i = 0; i < 8; i++) { thisDynamic.LocatorEntries[i].PlatformCode = BigEndianBitConverter.ToUInt32(dynamicBytes, 0x240 + 0x00 + 24 * i); thisDynamic.LocatorEntries[i].PlatformDataSpace = BigEndianBitConverter.ToUInt32(dynamicBytes, 0x240 + 0x04 + 24 * i); thisDynamic.LocatorEntries[i].PlatformDataLength = BigEndianBitConverter.ToUInt32(dynamicBytes, 0x240 + 0x08 + 24 * i); thisDynamic.LocatorEntries[i].Reserved = BigEndianBitConverter.ToUInt32(dynamicBytes, 0x240 + 0x0C + 24 * i); thisDynamic.LocatorEntries[i].PlatformDataOffset = BigEndianBitConverter.ToUInt64(dynamicBytes, 0x240 + 0x10 + 24 * i); } Array.Copy(dynamicBytes, 0x300, thisDynamic.Reserved2, 0, 256); parentDateTime = new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc); parentDateTime = parentDateTime.AddSeconds(thisDynamic.ParentTimestamp); sha1Ctx = new Sha1Context(); sha1Ctx.Update(thisDynamic.Reserved2); DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.cookie = 0x{0:X8}", thisDynamic.Cookie); DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.dataOffset = {0}", thisDynamic.DataOffset); DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.tableOffset = {0}", thisDynamic.TableOffset); DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.headerVersion = 0x{0:X8}", thisDynamic.HeaderVersion); DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.maxTableEntries = {0}", thisDynamic.MaxTableEntries); DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.blockSize = {0}", thisDynamic.BlockSize); DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.checksum = 0x{0:X8}", thisDynamic.Checksum); DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.parentID = {0}", thisDynamic.ParentId); DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.parentTimestamp = 0x{0:X8} ({1})", thisDynamic.ParentTimestamp, parentDateTime); DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.reserved = 0x{0:X8}", thisDynamic.Reserved); for (int i = 0; i < 8; i++) { DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.locatorEntries[{0}].platformCode = 0x{1:X8} (\"{2}\")", i, thisDynamic.LocatorEntries[i].PlatformCode, Encoding.ASCII.GetString(BigEndianBitConverter.GetBytes(thisDynamic .LocatorEntries[i] .PlatformCode))); DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.locatorEntries[{0}].platformDataSpace = {1}", i, thisDynamic.LocatorEntries[i].PlatformDataSpace); DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.locatorEntries[{0}].platformDataLength = {1}", i, thisDynamic.LocatorEntries[i].PlatformDataLength); DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.locatorEntries[{0}].reserved = 0x{1:X8}", i, thisDynamic.LocatorEntries[i].Reserved); DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.locatorEntries[{0}].platformDataOffset = {1}", i, thisDynamic.LocatorEntries[i].PlatformDataOffset); } DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.parentName = \"{0}\"", thisDynamic.ParentName); DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.reserved2's SHA1 = 0x{0}", sha1Ctx.End()); if (thisDynamic.HeaderVersion != VERSION1) { throw new ImageNotSupportedException($"(VirtualPC plugin): Unknown image type {thisFooter.DiskType} found. Please submit a bug with an example image."); } DateTime startTime = DateTime.UtcNow; blockAllocationTable = new uint[thisDynamic.MaxTableEntries]; // Safe and slow code. It takes 76,572 ms to fill a 30720 entries BAT /* * byte[] bat = new byte[thisDynamic.maxTableEntries * 4]; * imageStream.Seek((long)thisDynamic.tableOffset, SeekOrigin.Begin); * imageStream.Read(bat, 0, (int)(thisDynamic.maxTableEntries * 4)); * for (int i = 0; i < thisDynamic.maxTableEntries; i++) * blockAllocationTable[i] = BigEndianBitConverter.ToUInt32(bat, 4 * i); * * DateTime endTime = DateTime.UtcNow; * DicConsole.DebugWriteLine("VirtualPC plugin", "Filling the BAT took {0} seconds", (endTime-startTime).TotalSeconds); */ // How many sectors uses the BAT uint batSectorCount = (uint)Math.Ceiling((double)thisDynamic.MaxTableEntries * 4 / 512); byte[] batSectorBytes = new byte[512]; // Unsafe and fast code. It takes 4 ms to fill a 30720 entries BAT for (int i = 0; i < batSectorCount; i++) { imageStream.Seek((long)thisDynamic.TableOffset + i * 512, SeekOrigin.Begin); imageStream.Read(batSectorBytes, 0, 512); // This does the big-endian trick but reverses the order of elements also Array.Reverse(batSectorBytes); GCHandle handle = GCHandle.Alloc(batSectorBytes, GCHandleType.Pinned); BatSector batSector = (BatSector)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(BatSector)); handle.Free(); // This restores the order of elements Array.Reverse(batSector.blockPointer); if (blockAllocationTable.Length >= i * 512 / 4 + 512 / 4) { Array.Copy(batSector.blockPointer, 0, blockAllocationTable, i * 512 / 4, 512 / 4); } else { Array.Copy(batSector.blockPointer, 0, blockAllocationTable, i * 512 / 4, blockAllocationTable.Length - i * 512 / 4); } } DateTime endTime = DateTime.UtcNow; DicConsole.DebugWriteLine("VirtualPC plugin", "Filling the BAT took {0} seconds", (endTime - startTime).TotalSeconds); // Too noisy /* * for (int i = 0; i < thisDynamic.maxTableEntries; i++) * DicConsole.DebugWriteLine("VirtualPC plugin", "blockAllocationTable[{0}] = {1}", i, blockAllocationTable[i]); */ // Get the roundest number of sectors needed to store the block bitmap bitmapSize = (uint)Math.Ceiling((double)thisDynamic.BlockSize / 512 // 1 bit per sector on the bitmap / 8 // and aligned to 512 byte boundary / 512); DicConsole.DebugWriteLine("VirtualPC plugin", "Bitmap is {0} sectors", bitmapSize); } imageInfo.XmlMediaType = XmlMediaType.BlockMedia; switch (thisFooter.DiskType) { case TYPE_FIXED: case TYPE_DYNAMIC: { // Nothing to do here, really. return(true); } case TYPE_DIFFERENCING: { locatorEntriesData = new byte[8][]; for (int i = 0; i < 8; i++) { if (thisDynamic.LocatorEntries[i].PlatformCode != 0x00000000) { locatorEntriesData[i] = new byte[thisDynamic.LocatorEntries[i].PlatformDataLength]; imageStream.Seek((long)thisDynamic.LocatorEntries[i].PlatformDataOffset, SeekOrigin.Begin); imageStream.Read(locatorEntriesData[i], 0, (int)thisDynamic.LocatorEntries[i].PlatformDataLength); switch (thisDynamic.LocatorEntries[i].PlatformCode) { case PLATFORM_CODE_WINDOWS_ABSOLUTE: case PLATFORM_CODE_WINDOWS_RELATIVE: DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.locatorEntries[{0}] = \"{1}\"", i, Encoding.ASCII.GetString(locatorEntriesData[i])); break; case PLATFORM_CODE_WINDOWS_ABSOLUTE_U: case PLATFORM_CODE_WINDOWS_RELATIVE_U: DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.locatorEntries[{0}] = \"{1}\"", i, Encoding.BigEndianUnicode .GetString(locatorEntriesData[i])); break; case PLATFORM_CODE_MACINTOSH_URI: DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.locatorEntries[{0}] = \"{1}\"", i, Encoding.UTF8.GetString(locatorEntriesData[i])); break; default: DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.locatorEntries[{0}] =", i); PrintHex.PrintHexArray(locatorEntriesData[i], 64); break; } } } int currentLocator = 0; bool locatorFound = false; string parentPath = null; while (!locatorFound && currentLocator < 8) { switch (thisDynamic.LocatorEntries[currentLocator].PlatformCode) { case PLATFORM_CODE_WINDOWS_ABSOLUTE: case PLATFORM_CODE_WINDOWS_RELATIVE: parentPath = Encoding.ASCII.GetString(locatorEntriesData[currentLocator]); break; case PLATFORM_CODE_WINDOWS_ABSOLUTE_U: case PLATFORM_CODE_WINDOWS_RELATIVE_U: parentPath = Encoding.BigEndianUnicode.GetString(locatorEntriesData[currentLocator]); break; case PLATFORM_CODE_MACINTOSH_URI: parentPath = Uri.UnescapeDataString(Encoding.UTF8.GetString(locatorEntriesData[currentLocator])); if (parentPath.StartsWith("file://localhost", StringComparison.InvariantCulture)) { parentPath = parentPath.Remove(0, 16); } else { DicConsole.DebugWriteLine("VirtualPC plugin", "Unsupported protocol classified found in URI parent path: \"{0}\"", parentPath); parentPath = null; } break; } if (parentPath != null) { DicConsole.DebugWriteLine("VirtualPC plugin", "Possible parent path: \"{0}\"", parentPath); IFilter parentFilter = new FiltersList().GetFilter(Path.Combine(imageFilter.GetParentFolder(), parentPath)); if (parentFilter != null) { locatorFound = true; } if (!locatorFound) { parentPath = null; } } currentLocator++; } if (!locatorFound) { throw new FileNotFoundException("(VirtualPC plugin): Cannot find parent file for differencing disk image"); } { parentImage = new Vhd(); IFilter parentFilter = new FiltersList().GetFilter(Path.Combine(imageFilter.GetParentFolder(), parentPath)); if (parentFilter == null) { throw new ImageNotSupportedException("(VirtualPC plugin): Cannot find parent image filter"); } /* PluginBase plugins = new PluginBase(); * plugins.RegisterAllPlugins(); * if (!plugins.ImagePluginsList.TryGetValue(Name.ToLower(), out parentImage)) * throw new SystemException("(VirtualPC plugin): Unable to open myself");*/ if (!parentImage.Identify(parentFilter)) { throw new ImageNotSupportedException("(VirtualPC plugin): Parent image is not a Virtual PC disk image"); } if (!parentImage.Open(parentFilter)) { throw new ImageNotSupportedException("(VirtualPC plugin): Cannot open parent disk image"); } // While specification says that parent and child disk images should contain UUID relationship // in reality it seems that old differencing disk images stored a parent UUID that, nonetheless // 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.Info.Sectors != imageInfo.Sectors) { throw new ImageNotSupportedException("(VirtualPC plugin): Parent image is of different size"); } } return(true); } case TYPE_DEPRECATED1: case TYPE_DEPRECATED2: case TYPE_DEPRECATED3: { throw new ImageNotSupportedException("(VirtualPC plugin): Deprecated image type found. Please submit a bug with an example image."); } default: { throw new ImageNotSupportedException($"(VirtualPC plugin): Unknown image type {thisFooter.DiskType} found. Please submit a bug with an example image."); } } }
public bool?VerifyMediaImage() { if (_discImage.DiscHashes.Count == 0) { return(null); } // Read up to 1 MiB at a time for verification const int verifySize = 1024 * 1024; long readBytes; byte[] verifyBytes; IFilter[] filters = _discImage.Tracks.OrderBy(t => t.Sequence).Select(t => t.TrackFile.DataFilter). Distinct().ToArray(); if (_discImage.DiscHashes.TryGetValue("sha1", out string sha1)) { var ctx = new Sha1Context(); foreach (IFilter filter in filters) { Stream stream = filter.GetDataForkStream(); readBytes = 0; verifyBytes = new byte[verifySize]; while (readBytes + verifySize < stream.Length) { stream.Read(verifyBytes, 0, verifyBytes.Length); ctx.Update(verifyBytes); readBytes += verifyBytes.LongLength; } verifyBytes = new byte[stream.Length - readBytes]; stream.Read(verifyBytes, 0, verifyBytes.Length); ctx.Update(verifyBytes); } string verifySha1 = ctx.End(); AaruConsole.DebugWriteLine("CDRWin plugin", "Calculated SHA1: {0}", verifySha1); AaruConsole.DebugWriteLine("CDRWin plugin", "Expected SHA1: {0}", sha1); return(verifySha1 == sha1); } if (_discImage.DiscHashes.TryGetValue("md5", out string md5)) { var ctx = new Md5Context(); foreach (IFilter filter in filters) { Stream stream = filter.GetDataForkStream(); readBytes = 0; verifyBytes = new byte[verifySize]; while (readBytes + verifySize < stream.Length) { stream.Read(verifyBytes, 0, verifyBytes.Length); ctx.Update(verifyBytes); readBytes += verifyBytes.LongLength; } verifyBytes = new byte[stream.Length - readBytes]; stream.Read(verifyBytes, 0, verifyBytes.Length); ctx.Update(verifyBytes); } string verifyMd5 = ctx.End(); AaruConsole.DebugWriteLine("CDRWin plugin", "Calculated MD5: {0}", verifyMd5); AaruConsole.DebugWriteLine("CDRWin plugin", "Expected MD5: {0}", md5); return(verifyMd5 == md5); } if (_discImage.DiscHashes.TryGetValue("crc32", out string crc32)) { var ctx = new Crc32Context(); foreach (IFilter filter in filters) { Stream stream = filter.GetDataForkStream(); readBytes = 0; verifyBytes = new byte[verifySize]; while (readBytes + verifySize < stream.Length) { stream.Read(verifyBytes, 0, verifyBytes.Length); ctx.Update(verifyBytes); readBytes += verifyBytes.LongLength; } verifyBytes = new byte[stream.Length - readBytes]; stream.Read(verifyBytes, 0, verifyBytes.Length); ctx.Update(verifyBytes); } string verifyCrc = ctx.End(); AaruConsole.DebugWriteLine("CDRWin plugin", "Calculated CRC32: {0}", verifyCrc); AaruConsole.DebugWriteLine("CDRWin plugin", "Expected CRC32: {0}", crc32); return(verifyCrc == crc32); } foreach (string hash in _discImage.DiscHashes.Keys) { AaruConsole.DebugWriteLine("CDRWin plugin", "Found unsupported hash {0}", hash); } return(null); }
public static BenchmarkResults Do(int bufferSize, int blockSize) { BenchmarkResults results = new BenchmarkResults { Entries = new Dictionary <string, BenchmarkEntry>(), MinMemory = long.MaxValue, MaxMemory = 0, SeparateTime = 0 }; MemoryStream ms = new MemoryStream(bufferSize); Random rnd = new Random(); DateTime start; DateTime end; start = DateTime.Now; InitProgress(); for (int i = 0; i < bufferSize / blockSize; i++) { UpdateProgress("Writing block {0} of {1} with random data.", i + 1, bufferSize / blockSize); byte[] tmp = new byte[blockSize]; rnd.NextBytes(tmp); ms.Write(tmp, 0, blockSize); } EndProgress(); end = DateTime.Now; results.FillTime = (end - start).TotalSeconds; results.FillSpeed = bufferSize / 1048576.0 / (end - start).TotalSeconds; ms.Seek(0, SeekOrigin.Begin); long mem = GC.GetTotalMemory(false); if (mem > results.MaxMemory) { results.MaxMemory = mem; } if (mem < results.MinMemory) { results.MinMemory = mem; } start = DateTime.Now; InitProgress(); for (int i = 0; i < bufferSize / blockSize; i++) { UpdateProgress("Reading block {0} of {1}.", i + 1, bufferSize / blockSize); byte[] tmp = new byte[blockSize]; ms.Read(tmp, 0, blockSize); } EndProgress(); end = DateTime.Now; mem = GC.GetTotalMemory(false); if (mem > results.MaxMemory) { results.MaxMemory = mem; } if (mem < results.MinMemory) { results.MinMemory = mem; } results.ReadTime = (end - start).TotalSeconds; results.ReadSpeed = bufferSize / 1048576.0 / (end - start).TotalSeconds; #region Adler32 IChecksum ctx = new Adler32Context(); ms.Seek(0, SeekOrigin.Begin); mem = GC.GetTotalMemory(false); if (mem > results.MaxMemory) { results.MaxMemory = mem; } if (mem < results.MinMemory) { results.MinMemory = mem; } start = DateTime.Now; InitProgress(); for (int i = 0; i < bufferSize / blockSize; i++) { UpdateProgress("Checksumming block {0} of {1} with Adler32.", i + 1, bufferSize / blockSize); byte[] tmp = new byte[blockSize]; ms.Read(tmp, 0, blockSize); ctx.Update(tmp); } EndProgress(); ctx.End(); end = DateTime.Now; mem = GC.GetTotalMemory(false); if (mem > results.MaxMemory) { results.MaxMemory = mem; } if (mem < results.MinMemory) { results.MinMemory = mem; } results.Entries.Add("Adler32", new BenchmarkEntry { TimeSpan = (end - start).TotalSeconds, Speed = bufferSize / 1048576.0 / (end - start).TotalSeconds }); results.SeparateTime += (end - start).TotalSeconds; #endregion Adler32 #region Fletcher16 ctx = new Fletcher16Context(); ms.Seek(0, SeekOrigin.Begin); mem = GC.GetTotalMemory(false); if (mem > results.MaxMemory) { results.MaxMemory = mem; } if (mem < results.MinMemory) { results.MinMemory = mem; } start = DateTime.Now; InitProgress(); for (int i = 0; i < bufferSize / blockSize; i++) { UpdateProgress("Checksumming block {0} of {1} with Fletcher-16.", i + 1, bufferSize / blockSize); byte[] tmp = new byte[blockSize]; ms.Read(tmp, 0, blockSize); ctx.Update(tmp); } EndProgress(); ctx.End(); end = DateTime.Now; mem = GC.GetTotalMemory(false); if (mem > results.MaxMemory) { results.MaxMemory = mem; } if (mem < results.MinMemory) { results.MinMemory = mem; } results.Entries.Add("Fletcher16", new BenchmarkEntry { TimeSpan = (end - start).TotalSeconds, Speed = bufferSize / 1048576.0 / (end - start).TotalSeconds }); results.SeparateTime += (end - start).TotalSeconds; #endregion Fletcher16 #region Fletcher32 ctx = new Fletcher32Context(); ms.Seek(0, SeekOrigin.Begin); mem = GC.GetTotalMemory(false); if (mem > results.MaxMemory) { results.MaxMemory = mem; } if (mem < results.MinMemory) { results.MinMemory = mem; } start = DateTime.Now; InitProgress(); for (int i = 0; i < bufferSize / blockSize; i++) { UpdateProgress("Checksumming block {0} of {1} with Fletcher-32.", i + 1, bufferSize / blockSize); byte[] tmp = new byte[blockSize]; ms.Read(tmp, 0, blockSize); ctx.Update(tmp); } EndProgress(); ctx.End(); end = DateTime.Now; mem = GC.GetTotalMemory(false); if (mem > results.MaxMemory) { results.MaxMemory = mem; } if (mem < results.MinMemory) { results.MinMemory = mem; } results.Entries.Add("Fletcher32", new BenchmarkEntry { TimeSpan = (end - start).TotalSeconds, Speed = bufferSize / 1048576.0 / (end - start).TotalSeconds }); results.SeparateTime += (end - start).TotalSeconds; #endregion Fletcher32 #region CRC16 ctx = new Crc16Context(); ms.Seek(0, SeekOrigin.Begin); mem = GC.GetTotalMemory(false); if (mem > results.MaxMemory) { results.MaxMemory = mem; } if (mem < results.MinMemory) { results.MinMemory = mem; } start = DateTime.Now; InitProgress(); for (int i = 0; i < bufferSize / blockSize; i++) { UpdateProgress("Checksumming block {0} of {1} with CRC16.", i + 1, bufferSize / blockSize); byte[] tmp = new byte[blockSize]; ms.Read(tmp, 0, blockSize); ctx.Update(tmp); } EndProgress(); ctx.End(); end = DateTime.Now; mem = GC.GetTotalMemory(false); if (mem > results.MaxMemory) { results.MaxMemory = mem; } if (mem < results.MinMemory) { results.MinMemory = mem; } results.Entries.Add("CRC16", new BenchmarkEntry { TimeSpan = (end - start).TotalSeconds, Speed = bufferSize / 1048576.0 / (end - start).TotalSeconds }); results.SeparateTime += (end - start).TotalSeconds; #endregion CRC16 #region CRC32 ctx = new Crc32Context(); ms.Seek(0, SeekOrigin.Begin); mem = GC.GetTotalMemory(false); if (mem > results.MaxMemory) { results.MaxMemory = mem; } if (mem < results.MinMemory) { results.MinMemory = mem; } start = DateTime.Now; InitProgress(); for (int i = 0; i < bufferSize / blockSize; i++) { UpdateProgress("Checksumming block {0} of {1} with CRC32.", i + 1, bufferSize / blockSize); byte[] tmp = new byte[blockSize]; ms.Read(tmp, 0, blockSize); ctx.Update(tmp); } EndProgress(); ctx.End(); end = DateTime.Now; mem = GC.GetTotalMemory(false); if (mem > results.MaxMemory) { results.MaxMemory = mem; } if (mem < results.MinMemory) { results.MinMemory = mem; } results.Entries.Add("CRC32", new BenchmarkEntry { TimeSpan = (end - start).TotalSeconds, Speed = bufferSize / 1048576.0 / (end - start).TotalSeconds }); results.SeparateTime += (end - start).TotalSeconds; #endregion CRC32 #region CRC64 ctx = new Crc64Context(); ms.Seek(0, SeekOrigin.Begin); mem = GC.GetTotalMemory(false); if (mem > results.MaxMemory) { results.MaxMemory = mem; } if (mem < results.MinMemory) { results.MinMemory = mem; } start = DateTime.Now; InitProgress(); for (int i = 0; i < bufferSize / blockSize; i++) { UpdateProgress("Checksumming block {0} of {1} with CRC64.", i + 1, bufferSize / blockSize); byte[] tmp = new byte[blockSize]; ms.Read(tmp, 0, blockSize); ctx.Update(tmp); } EndProgress(); ctx.End(); end = DateTime.Now; mem = GC.GetTotalMemory(false); if (mem > results.MaxMemory) { results.MaxMemory = mem; } if (mem < results.MinMemory) { results.MinMemory = mem; } results.Entries.Add("CRC64", new BenchmarkEntry { TimeSpan = (end - start).TotalSeconds, Speed = bufferSize / 1048576.0 / (end - start).TotalSeconds }); results.SeparateTime += (end - start).TotalSeconds; #endregion CRC64 #region MD5 ctx = new Md5Context(); ms.Seek(0, SeekOrigin.Begin); mem = GC.GetTotalMemory(false); if (mem > results.MaxMemory) { results.MaxMemory = mem; } if (mem < results.MinMemory) { results.MinMemory = mem; } start = DateTime.Now; InitProgress(); for (int i = 0; i < bufferSize / blockSize; i++) { UpdateProgress("Checksumming block {0} of {1} with MD5.", i + 1, bufferSize / blockSize); byte[] tmp = new byte[blockSize]; ms.Read(tmp, 0, blockSize); ctx.Update(tmp); } EndProgress(); ctx.End(); end = DateTime.Now; mem = GC.GetTotalMemory(false); if (mem > results.MaxMemory) { results.MaxMemory = mem; } if (mem < results.MinMemory) { results.MinMemory = mem; } results.Entries.Add("MD5", new BenchmarkEntry { TimeSpan = (end - start).TotalSeconds, Speed = bufferSize / 1048576.0 / (end - start).TotalSeconds }); results.SeparateTime += (end - start).TotalSeconds; #endregion MD5 #if !NETSTANDARD2_0 #region RIPEMD160 ctx = new Ripemd160Context(); ms.Seek(0, SeekOrigin.Begin); mem = GC.GetTotalMemory(false); if (mem > results.MaxMemory) { results.MaxMemory = mem; } if (mem < results.MinMemory) { results.MinMemory = mem; } start = DateTime.Now; InitProgress(); for (int i = 0; i < bufferSize / blockSize; i++) { UpdateProgress("Checksumming block {0} of {1} with RIPEMD160.", i + 1, bufferSize / blockSize); byte[] tmp = new byte[blockSize]; ms.Read(tmp, 0, blockSize); ctx.Update(tmp); } EndProgress(); ctx.End(); end = DateTime.Now; mem = GC.GetTotalMemory(false); if (mem > results.MaxMemory) { results.MaxMemory = mem; } if (mem < results.MinMemory) { results.MinMemory = mem; } results.Entries.Add("RIPEMD160", new BenchmarkEntry { TimeSpan = (end - start).TotalSeconds, Speed = bufferSize / 1048576.0 / (end - start).TotalSeconds }); results.SeparateTime += (end - start).TotalSeconds; #endregion RIPEMD160 #endif #region SHA1 ctx = new Sha1Context(); ms.Seek(0, SeekOrigin.Begin); mem = GC.GetTotalMemory(false); if (mem > results.MaxMemory) { results.MaxMemory = mem; } if (mem < results.MinMemory) { results.MinMemory = mem; } start = DateTime.Now; InitProgress(); for (int i = 0; i < bufferSize / blockSize; i++) { UpdateProgress("Checksumming block {0} of {1} with SHA1.", i + 1, bufferSize / blockSize); byte[] tmp = new byte[blockSize]; ms.Read(tmp, 0, blockSize); ctx.Update(tmp); } EndProgress(); ctx.End(); end = DateTime.Now; mem = GC.GetTotalMemory(false); if (mem > results.MaxMemory) { results.MaxMemory = mem; } if (mem < results.MinMemory) { results.MinMemory = mem; } results.Entries.Add("SHA1", new BenchmarkEntry { TimeSpan = (end - start).TotalSeconds, Speed = bufferSize / 1048576.0 / (end - start).TotalSeconds }); results.SeparateTime += (end - start).TotalSeconds; #endregion SHA1 #region SHA256 ctx = new Sha256Context(); ms.Seek(0, SeekOrigin.Begin); mem = GC.GetTotalMemory(false); if (mem > results.MaxMemory) { results.MaxMemory = mem; } if (mem < results.MinMemory) { results.MinMemory = mem; } start = DateTime.Now; InitProgress(); for (int i = 0; i < bufferSize / blockSize; i++) { UpdateProgress("Checksumming block {0} of {1} with SHA256.", i + 1, bufferSize / blockSize); byte[] tmp = new byte[blockSize]; ms.Read(tmp, 0, blockSize); ctx.Update(tmp); } EndProgress(); ctx.End(); end = DateTime.Now; mem = GC.GetTotalMemory(false); if (mem > results.MaxMemory) { results.MaxMemory = mem; } if (mem < results.MinMemory) { results.MinMemory = mem; } results.Entries.Add("SHA256", new BenchmarkEntry { TimeSpan = (end - start).TotalSeconds, Speed = bufferSize / 1048576.0 / (end - start).TotalSeconds }); results.SeparateTime += (end - start).TotalSeconds; #endregion SHA256 #region SHA384 ctx = new Sha384Context(); ms.Seek(0, SeekOrigin.Begin); mem = GC.GetTotalMemory(false); if (mem > results.MaxMemory) { results.MaxMemory = mem; } if (mem < results.MinMemory) { results.MinMemory = mem; } start = DateTime.Now; InitProgress(); for (int i = 0; i < bufferSize / blockSize; i++) { UpdateProgress("Checksumming block {0} of {1} with SHA384.", i + 1, bufferSize / blockSize); byte[] tmp = new byte[blockSize]; ms.Read(tmp, 0, blockSize); ctx.Update(tmp); } EndProgress(); ctx.End(); end = DateTime.Now; mem = GC.GetTotalMemory(false); if (mem > results.MaxMemory) { results.MaxMemory = mem; } if (mem < results.MinMemory) { results.MinMemory = mem; } results.Entries.Add("SHA384", new BenchmarkEntry { TimeSpan = (end - start).TotalSeconds, Speed = bufferSize / 1048576.0 / (end - start).TotalSeconds }); results.SeparateTime += (end - start).TotalSeconds; #endregion SHA384 #region SHA512 ctx = new Sha512Context(); ms.Seek(0, SeekOrigin.Begin); mem = GC.GetTotalMemory(false); if (mem > results.MaxMemory) { results.MaxMemory = mem; } if (mem < results.MinMemory) { results.MinMemory = mem; } start = DateTime.Now; InitProgress(); for (int i = 0; i < bufferSize / blockSize; i++) { UpdateProgress("Checksumming block {0} of {1} with SHA512.", i + 1, bufferSize / blockSize); byte[] tmp = new byte[blockSize]; ms.Read(tmp, 0, blockSize); ctx.Update(tmp); } EndProgress(); ctx.End(); end = DateTime.Now; mem = GC.GetTotalMemory(false); if (mem > results.MaxMemory) { results.MaxMemory = mem; } if (mem < results.MinMemory) { results.MinMemory = mem; } results.Entries.Add("SHA512", new BenchmarkEntry { TimeSpan = (end - start).TotalSeconds, Speed = bufferSize / 1048576.0 / (end - start).TotalSeconds }); results.SeparateTime += (end - start).TotalSeconds; #endregion SHA512 #region SpamSum ctx = new SpamSumContext(); ms.Seek(0, SeekOrigin.Begin); mem = GC.GetTotalMemory(false); if (mem > results.MaxMemory) { results.MaxMemory = mem; } if (mem < results.MinMemory) { results.MinMemory = mem; } start = DateTime.Now; InitProgress(); for (int i = 0; i < bufferSize / blockSize; i++) { UpdateProgress("Checksumming block {0} of {1} with SpamSum.", i + 1, bufferSize / blockSize); byte[] tmp = new byte[blockSize]; ms.Read(tmp, 0, blockSize); ctx.Update(tmp); } EndProgress(); ctx.End(); end = DateTime.Now; mem = GC.GetTotalMemory(false); if (mem > results.MaxMemory) { results.MaxMemory = mem; } if (mem < results.MinMemory) { results.MinMemory = mem; } results.Entries.Add("SpamSum", new BenchmarkEntry { TimeSpan = (end - start).TotalSeconds, Speed = bufferSize / 1048576.0 / (end - start).TotalSeconds }); results.SeparateTime += (end - start).TotalSeconds; #endregion SpamSum #region Entropy ulong[] entTable = new ulong[256]; ms.Seek(0, SeekOrigin.Begin); mem = GC.GetTotalMemory(false); if (mem > results.MaxMemory) { results.MaxMemory = mem; } if (mem < results.MinMemory) { results.MinMemory = mem; } start = DateTime.Now; InitProgress(); for (int i = 0; i < bufferSize / blockSize; i++) { UpdateProgress("Entropying block {0} of {1}.", i + 1, bufferSize / blockSize); byte[] tmp = new byte[blockSize]; ms.Read(tmp, 0, blockSize); foreach (byte b in tmp) { entTable[b]++; } } EndProgress(); end = DateTime.Now; mem = GC.GetTotalMemory(false); if (mem > results.MaxMemory) { results.MaxMemory = mem; } if (mem < results.MinMemory) { results.MinMemory = mem; } results.EntropyTime = (end - start).TotalSeconds; results.EntropySpeed = bufferSize / 1048576.0 / (end - start).TotalSeconds; #endregion Entropy /* #region Multitasking * start = DateTime.Now; * Checksum allChecksums = new Checksum(); * InitProgress(); * for(int i = 0; i < bufferSize / blockSize; i++) * { * UpdateProgress("Checksumming block {0} of {1} with all algorithms at the same time.", i + 1, * bufferSize / blockSize); * byte[] tmp = new byte[blockSize]; * ms.Read(tmp, 0, blockSize); * * allChecksums.Update(tmp); * } * * EndProgress(); * * allChecksums.End(); * end = DateTime.Now; * mem = GC.GetTotalMemory(false); * if(mem > results.MaxMemory) results.MaxMemory = mem; * if(mem < results.MinMemory) results.MinMemory = mem; * * results.TotalTime = (end - start).TotalSeconds; * results.TotalSpeed = bufferSize / 1048576.0 / results.TotalTime; #endregion */ results.SeparateSpeed = bufferSize / 1048576.0 / results.SeparateTime; return(results); }
public bool GetInformation(IMediaImage imagePlugin, out List <Partition> partitions, ulong sectorOffset) { partitions = new List <Partition>(); byte[] sector = imagePlugin.ReadSector(sectorOffset); if (sector.Length < 512) { return(false); } var table = new AtariTable { boot = new byte[342], icdEntries = new AtariEntry[8], unused = new byte[12], entries = new AtariEntry[4] }; Array.Copy(sector, 0, table.boot, 0, 342); for (int i = 0; i < 8; i++) { table.icdEntries[i].type = BigEndianBitConverter.ToUInt32(sector, 342 + (i * 12) + 0); table.icdEntries[i].start = BigEndianBitConverter.ToUInt32(sector, 342 + (i * 12) + 4); table.icdEntries[i].length = BigEndianBitConverter.ToUInt32(sector, 342 + (i * 12) + 8); } Array.Copy(sector, 438, table.unused, 0, 12); table.size = BigEndianBitConverter.ToUInt32(sector, 450); for (int i = 0; i < 4; i++) { table.entries[i].type = BigEndianBitConverter.ToUInt32(sector, 454 + (i * 12) + 0); table.entries[i].start = BigEndianBitConverter.ToUInt32(sector, 454 + (i * 12) + 4); table.entries[i].length = BigEndianBitConverter.ToUInt32(sector, 454 + (i * 12) + 8); } table.badStart = BigEndianBitConverter.ToUInt32(sector, 502); table.badLength = BigEndianBitConverter.ToUInt32(sector, 506); table.checksum = BigEndianBitConverter.ToUInt16(sector, 510); var sha1Ctx = new Sha1Context(); sha1Ctx.Update(table.boot); AaruConsole.DebugWriteLine("Atari partition plugin", "Boot code SHA1: {0}", sha1Ctx.End()); for (int i = 0; i < 8; i++) { AaruConsole.DebugWriteLine("Atari partition plugin", "table.icdEntries[{0}].flag = 0x{1:X2}", i, (table.icdEntries[i].type & 0xFF000000) >> 24); AaruConsole.DebugWriteLine("Atari partition plugin", "table.icdEntries[{0}].type = 0x{1:X6}", i, table.icdEntries[i].type & 0x00FFFFFF); AaruConsole.DebugWriteLine("Atari partition plugin", "table.icdEntries[{0}].start = {1}", i, table.icdEntries[i].start); AaruConsole.DebugWriteLine("Atari partition plugin", "table.icdEntries[{0}].length = {1}", i, table.icdEntries[i].length); } AaruConsole.DebugWriteLine("Atari partition plugin", "table.size = {0}", table.size); for (int i = 0; i < 4; i++) { AaruConsole.DebugWriteLine("Atari partition plugin", "table.entries[{0}].flag = 0x{1:X2}", i, (table.entries[i].type & 0xFF000000) >> 24); AaruConsole.DebugWriteLine("Atari partition plugin", "table.entries[{0}].type = 0x{1:X6}", i, table.entries[i].type & 0x00FFFFFF); AaruConsole.DebugWriteLine("Atari partition plugin", "table.entries[{0}].start = {1}", i, table.entries[i].start); AaruConsole.DebugWriteLine("Atari partition plugin", "table.entries[{0}].length = {1}", i, table.entries[i].length); } AaruConsole.DebugWriteLine("Atari partition plugin", "table.badStart = {0}", table.badStart); AaruConsole.DebugWriteLine("Atari partition plugin", "table.badLength = {0}", table.badLength); AaruConsole.DebugWriteLine("Atari partition plugin", "table.checksum = 0x{0:X4}", table.checksum); bool validTable = false; ulong partitionSequence = 0; for (int i = 0; i < 4; i++) { uint type = table.entries[i].type & 0x00FFFFFF; switch (type) { case TypeGEMDOS: case TypeBigGEMDOS: case TypeLinux: case TypeSwap: case TypeRAW: case TypeNetBSD: case TypeNetBSDSwap: case TypeSysV: case TypeMac: case TypeMinix: case TypeMinix2: validTable = true; if (table.entries[i].start <= imagePlugin.Info.Sectors) { if (table.entries[i].start + table.entries[i].length > imagePlugin.Info.Sectors) { AaruConsole.DebugWriteLine("Atari partition plugin", "WARNING: End of partition goes beyond device size"); } ulong sectorSize = imagePlugin.Info.SectorSize; if (sectorSize == 2448 || sectorSize == 2352) { sectorSize = 2048; } byte[] partType = new byte[3]; partType[0] = (byte)((type & 0xFF0000) >> 16); partType[1] = (byte)((type & 0x00FF00) >> 8); partType[2] = (byte)(type & 0x0000FF); var part = new Partition { Size = table.entries[i].length * sectorSize, Length = table.entries[i].length, Sequence = partitionSequence, Name = "", Offset = table.entries[i].start * sectorSize, Start = table.entries[i].start, Type = Encoding.ASCII.GetString(partType), Scheme = Name }; switch (type) { case TypeGEMDOS: part.Description = "Atari GEMDOS partition"; break; case TypeBigGEMDOS: part.Description = "Atari GEMDOS partition bigger than 32 MiB"; break; case TypeLinux: part.Description = "Linux partition"; break; case TypeSwap: part.Description = "Swap partition"; break; case TypeRAW: part.Description = "RAW partition"; break; case TypeNetBSD: part.Description = "NetBSD partition"; break; case TypeNetBSDSwap: part.Description = "NetBSD swap partition"; break; case TypeSysV: part.Description = "Atari UNIX partition"; break; case TypeMac: part.Description = "Macintosh partition"; break; case TypeMinix: case TypeMinix2: part.Description = "MINIX partition"; break; default: part.Description = "Unknown partition type"; break; } partitions.Add(part); partitionSequence++; } break; case TypeExtended: byte[] extendedSector = imagePlugin.ReadSector(table.entries[i].start); var extendedTable = new AtariTable(); extendedTable.entries = new AtariEntry[4]; for (int j = 0; j < 4; j++) { extendedTable.entries[j].type = BigEndianBitConverter.ToUInt32(extendedSector, 454 + (j * 12) + 0); extendedTable.entries[j].start = BigEndianBitConverter.ToUInt32(extendedSector, 454 + (j * 12) + 4); extendedTable.entries[j].length = BigEndianBitConverter.ToUInt32(extendedSector, 454 + (j * 12) + 8); } for (int j = 0; j < 4; j++) { uint extendedType = extendedTable.entries[j].type & 0x00FFFFFF; if (extendedType != TypeGEMDOS && extendedType != TypeBigGEMDOS && extendedType != TypeLinux && extendedType != TypeSwap && extendedType != TypeRAW && extendedType != TypeNetBSD && extendedType != TypeNetBSDSwap && extendedType != TypeSysV && extendedType != TypeMac && extendedType != TypeMinix && extendedType != TypeMinix2) { continue; } validTable = true; if (extendedTable.entries[j].start > imagePlugin.Info.Sectors) { continue; } if (extendedTable.entries[j].start + extendedTable.entries[j].length > imagePlugin.Info.Sectors) { AaruConsole.DebugWriteLine("Atari partition plugin", "WARNING: End of partition goes beyond device size"); } ulong sectorSize = imagePlugin.Info.SectorSize; if (sectorSize == 2448 || sectorSize == 2352) { sectorSize = 2048; } byte[] partType = new byte[3]; partType[0] = (byte)((extendedType & 0xFF0000) >> 16); partType[1] = (byte)((extendedType & 0x00FF00) >> 8); partType[2] = (byte)(extendedType & 0x0000FF); var part = new Partition { Size = extendedTable.entries[j].length * sectorSize, Length = extendedTable.entries[j].length, Sequence = partitionSequence, Name = "", Offset = extendedTable.entries[j].start * sectorSize, Start = extendedTable.entries[j].start, Type = Encoding.ASCII.GetString(partType), Scheme = Name }; switch (extendedType) { case TypeGEMDOS: part.Description = "Atari GEMDOS partition"; break; case TypeBigGEMDOS: part.Description = "Atari GEMDOS partition bigger than 32 MiB"; break; case TypeLinux: part.Description = "Linux partition"; break; case TypeSwap: part.Description = "Swap partition"; break; case TypeRAW: part.Description = "RAW partition"; break; case TypeNetBSD: part.Description = "NetBSD partition"; break; case TypeNetBSDSwap: part.Description = "NetBSD swap partition"; break; case TypeSysV: part.Description = "Atari UNIX partition"; break; case TypeMac: part.Description = "Macintosh partition"; break; case TypeMinix: case TypeMinix2: part.Description = "MINIX partition"; break; default: part.Description = "Unknown partition type"; break; } partitions.Add(part); partitionSequence++; } break; } } if (!validTable) { return(partitions.Count > 0); } for (int i = 0; i < 8; i++) { uint type = table.icdEntries[i].type & 0x00FFFFFF; if (type != TypeGEMDOS && type != TypeBigGEMDOS && type != TypeLinux && type != TypeSwap && type != TypeRAW && type != TypeNetBSD && type != TypeNetBSDSwap && type != TypeSysV && type != TypeMac && type != TypeMinix && type != TypeMinix2) { continue; } if (table.icdEntries[i].start > imagePlugin.Info.Sectors) { continue; } if (table.icdEntries[i].start + table.icdEntries[i].length > imagePlugin.Info.Sectors) { AaruConsole.DebugWriteLine("Atari partition plugin", "WARNING: End of partition goes beyond device size"); } ulong sectorSize = imagePlugin.Info.SectorSize; if (sectorSize == 2448 || sectorSize == 2352) { sectorSize = 2048; } byte[] partType = new byte[3]; partType[0] = (byte)((type & 0xFF0000) >> 16); partType[1] = (byte)((type & 0x00FF00) >> 8); partType[2] = (byte)(type & 0x0000FF); var part = new Partition { Size = table.icdEntries[i].length * sectorSize, Length = table.icdEntries[i].length, Sequence = partitionSequence, Name = "", Offset = table.icdEntries[i].start * sectorSize, Start = table.icdEntries[i].start, Type = Encoding.ASCII.GetString(partType), Scheme = Name }; switch (type) { case TypeGEMDOS: part.Description = "Atari GEMDOS partition"; break; case TypeBigGEMDOS: part.Description = "Atari GEMDOS partition bigger than 32 MiB"; break; case TypeLinux: part.Description = "Linux partition"; break; case TypeSwap: part.Description = "Swap partition"; break; case TypeRAW: part.Description = "RAW partition"; break; case TypeNetBSD: part.Description = "NetBSD partition"; break; case TypeNetBSDSwap: part.Description = "NetBSD swap partition"; break; case TypeSysV: part.Description = "Atari UNIX partition"; break; case TypeMac: part.Description = "Macintosh partition"; break; case TypeMinix: case TypeMinix2: part.Description = "MINIX partition"; break; default: part.Description = "Unknown partition type"; break; } partitions.Add(part); partitionSequence++; } return(partitions.Count > 0); }
internal static List <ChecksumType> GetChecksums(byte[] data) { Adler32Context adler32ctxData = new Adler32Context(); Crc16Context crc16ctxData = new Crc16Context(); Crc32Context crc32ctxData = new Crc32Context(); Crc64Context crc64ctxData = new Crc64Context(); Md5Context md5ctxData = new Md5Context(); Ripemd160Context ripemd160ctxData = new Ripemd160Context(); Sha1Context sha1ctxData = new Sha1Context(); Sha256Context sha256ctxData = new Sha256Context(); Sha384Context sha384ctxData = new Sha384Context(); Sha512Context sha512ctxData = new Sha512Context(); SpamSumContext ssctxData = new SpamSumContext(); Thread adlerThreadData = new Thread(updateAdler); Thread crc16ThreadData = new Thread(updateCRC16); Thread crc32ThreadData = new Thread(updateCRC32); Thread crc64ThreadData = new Thread(updateCRC64); Thread md5ThreadData = new Thread(updateMD5); Thread ripemd160ThreadData = new Thread(updateRIPEMD160); Thread sha1ThreadData = new Thread(updateSHA1); Thread sha256ThreadData = new Thread(updateSHA256); Thread sha384ThreadData = new Thread(updateSHA384); Thread sha512ThreadData = new Thread(updateSHA512); Thread spamsumThreadData = new Thread(updateSpamSum); adlerPacket adlerPktData = new adlerPacket(); crc16Packet crc16PktData = new crc16Packet(); crc32Packet crc32PktData = new crc32Packet(); crc64Packet crc64PktData = new crc64Packet(); md5Packet md5PktData = new md5Packet(); ripemd160Packet ripemd160PktData = new ripemd160Packet(); sha1Packet sha1PktData = new sha1Packet(); sha256Packet sha256PktData = new sha256Packet(); sha384Packet sha384PktData = new sha384Packet(); sha512Packet sha512PktData = new sha512Packet(); spamsumPacket spamsumPktData = new spamsumPacket(); adler32ctxData.Init(); adlerPktData.context = adler32ctxData; crc16ctxData.Init(); crc16PktData.context = crc16ctxData; crc32ctxData.Init(); crc32PktData.context = crc32ctxData; crc64ctxData.Init(); crc64PktData.context = crc64ctxData; md5ctxData.Init(); md5PktData.context = md5ctxData; ripemd160ctxData.Init(); ripemd160PktData.context = ripemd160ctxData; sha1ctxData.Init(); sha1PktData.context = sha1ctxData; sha256ctxData.Init(); sha256PktData.context = sha256ctxData; sha384ctxData.Init(); sha384PktData.context = sha384ctxData; sha512ctxData.Init(); sha512PktData.context = sha512ctxData; ssctxData.Init(); spamsumPktData.context = ssctxData; adlerPktData.data = data; adlerThreadData.Start(adlerPktData); crc16PktData.data = data; crc16ThreadData.Start(crc16PktData); crc32PktData.data = data; crc32ThreadData.Start(crc32PktData); crc64PktData.data = data; crc64ThreadData.Start(crc64PktData); md5PktData.data = data; md5ThreadData.Start(md5PktData); ripemd160PktData.data = data; ripemd160ThreadData.Start(ripemd160PktData); sha1PktData.data = data; sha1ThreadData.Start(sha1PktData); sha256PktData.data = data; sha256ThreadData.Start(sha256PktData); sha384PktData.data = data; sha384ThreadData.Start(sha384PktData); sha512PktData.data = data; sha512ThreadData.Start(sha512PktData); spamsumPktData.data = data; spamsumThreadData.Start(spamsumPktData); while (adlerThreadData.IsAlive || crc16ThreadData.IsAlive || crc32ThreadData.IsAlive || crc64ThreadData.IsAlive || md5ThreadData.IsAlive || ripemd160ThreadData.IsAlive || sha1ThreadData.IsAlive || sha256ThreadData.IsAlive || sha384ThreadData.IsAlive || sha512ThreadData.IsAlive || spamsumThreadData.IsAlive) { } List <ChecksumType> dataChecksums = new List <ChecksumType>(); ChecksumType chk = new ChecksumType { type = ChecksumTypeType.adler32, Value = adler32ctxData.End() }; dataChecksums.Add(chk); chk = new ChecksumType { type = ChecksumTypeType.crc16, Value = crc16ctxData.End() }; dataChecksums.Add(chk); chk = new ChecksumType { type = ChecksumTypeType.crc32, Value = crc32ctxData.End() }; dataChecksums.Add(chk); chk = new ChecksumType { type = ChecksumTypeType.crc64, Value = crc64ctxData.End() }; dataChecksums.Add(chk); chk = new ChecksumType { type = ChecksumTypeType.md5, Value = md5ctxData.End() }; dataChecksums.Add(chk); chk = new ChecksumType { type = ChecksumTypeType.ripemd160, Value = ripemd160ctxData.End() }; dataChecksums.Add(chk); chk = new ChecksumType { type = ChecksumTypeType.sha1, Value = sha1ctxData.End() }; dataChecksums.Add(chk); chk = new ChecksumType { type = ChecksumTypeType.sha256, Value = sha256ctxData.End() }; dataChecksums.Add(chk); chk = new ChecksumType { type = ChecksumTypeType.sha384, Value = sha384ctxData.End() }; dataChecksums.Add(chk); chk = new ChecksumType { type = ChecksumTypeType.sha512, Value = sha512ctxData.End() }; dataChecksums.Add(chk); chk = new ChecksumType { type = ChecksumTypeType.spamsum, Value = ssctxData.End() }; dataChecksums.Add(chk); return(dataChecksums); }
internal List <ChecksumType> End() { List <ChecksumType> chks = new List <ChecksumType>(); ChecksumType chk = new ChecksumType { type = ChecksumTypeType.adler32, Value = adler32ctx.End() }; chks.Add(chk); chk = new ChecksumType { type = ChecksumTypeType.crc16, Value = crc16ctx.End() }; chks.Add(chk); chk = new ChecksumType { type = ChecksumTypeType.crc32, Value = crc32ctx.End() }; chks.Add(chk); chk = new ChecksumType { type = ChecksumTypeType.crc64, Value = crc64ctx.End() }; chks.Add(chk); chk = new ChecksumType { type = ChecksumTypeType.md5, Value = md5ctx.End() }; chks.Add(chk); chk = new ChecksumType { type = ChecksumTypeType.ripemd160, Value = ripemd160ctx.End() }; chks.Add(chk); chk = new ChecksumType { type = ChecksumTypeType.sha1, Value = sha1ctx.End() }; chks.Add(chk); chk = new ChecksumType { type = ChecksumTypeType.sha256, Value = sha256ctx.End() }; chks.Add(chk); chk = new ChecksumType { type = ChecksumTypeType.sha384, Value = sha384ctx.End() }; chks.Add(chk); chk = new ChecksumType { type = ChecksumTypeType.sha512, Value = sha512ctx.End() }; chks.Add(chk); chk = new ChecksumType { type = ChecksumTypeType.spamsum, Value = ssctx.End() }; chks.Add(chk); return(chks); }