public override int Invoke(IEnumerable <string> arguments) { List <string> extra = Options.Parse(arguments); if (showHelp) { Options.WriteOptionDescriptions(CommandSet.Out); return((int)ErrorNumber.HelpRequested); } MainClass.PrintCopyright(); if (MainClass.Debug) { DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; } if (MainClass.Verbose) { DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; } Statistics.AddCommand("checksum"); if (extra.Count > 1) { DicConsole.ErrorWriteLine("Too many arguments."); return((int)ErrorNumber.UnexpectedArgumentCount); } if (extra.Count == 0) { DicConsole.ErrorWriteLine("Missing input image."); return((int)ErrorNumber.MissingArgument); } inputFile = extra[0]; DicConsole.DebugWriteLine("Checksum command", "--adler32={0}", doAdler32); DicConsole.DebugWriteLine("Checksum command", "--crc16={0}", doCrc16); DicConsole.DebugWriteLine("Checksum command", "--crc32={0}", doCrc32); DicConsole.DebugWriteLine("Checksum command", "--crc64={0}", doCrc64); DicConsole.DebugWriteLine("Checksum command", "--debug={0}", MainClass.Debug); DicConsole.DebugWriteLine("Checksum command", "--fletcher16={0}", doFletcher16); DicConsole.DebugWriteLine("Checksum command", "--fletcher32={0}", doFletcher32); DicConsole.DebugWriteLine("Checksum command", "--input={0}", inputFile); DicConsole.DebugWriteLine("Checksum command", "--md5={0}", doMd5); DicConsole.DebugWriteLine("Checksum command", "--ripemd160={0}", doRipemd160); DicConsole.DebugWriteLine("Checksum command", "--separated-tracks={0}", separatedTracks); DicConsole.DebugWriteLine("Checksum command", "--sha1={0}", doSha1); DicConsole.DebugWriteLine("Checksum command", "--sha256={0}", doSha256); DicConsole.DebugWriteLine("Checksum command", "--sha384={0}", doSha384); DicConsole.DebugWriteLine("Checksum command", "--sha512={0}", doSha512); DicConsole.DebugWriteLine("Checksum command", "--spamsum={0}", doSpamSum); DicConsole.DebugWriteLine("Checksum command", "--verbose={0}", MainClass.Verbose); DicConsole.DebugWriteLine("Checksum command", "--whole-disc={0}", wholeDisc); FiltersList filtersList = new FiltersList(); IFilter inputFilter = filtersList.GetFilter(inputFile); if (inputFilter == null) { DicConsole.ErrorWriteLine("Cannot open specified file."); return((int)ErrorNumber.CannotOpenFile); } IMediaImage inputFormat = ImageFormat.Detect(inputFilter); if (inputFormat == null) { DicConsole.ErrorWriteLine("Unable to recognize image format, not checksumming"); return((int)ErrorNumber.UnrecognizedFormat); } inputFormat.Open(inputFilter); Statistics.AddMediaFormat(inputFormat.Format); Statistics.AddMedia(inputFormat.Info.MediaType, false); Statistics.AddFilter(inputFilter.Name); EnableChecksum enabledChecksums = new EnableChecksum(); if (doAdler32) { enabledChecksums |= EnableChecksum.Adler32; } if (doCrc16) { enabledChecksums |= EnableChecksum.Crc16; } if (doCrc32) { enabledChecksums |= EnableChecksum.Crc32; } if (doCrc64) { enabledChecksums |= EnableChecksum.Crc64; } if (doMd5) { enabledChecksums |= EnableChecksum.Md5; } if (doRipemd160) { enabledChecksums |= EnableChecksum.Ripemd160; } if (doSha1) { enabledChecksums |= EnableChecksum.Sha1; } if (doSha256) { enabledChecksums |= EnableChecksum.Sha256; } if (doSha384) { enabledChecksums |= EnableChecksum.Sha384; } if (doSha512) { enabledChecksums |= EnableChecksum.Sha512; } if (doSpamSum) { enabledChecksums |= EnableChecksum.SpamSum; } if (doFletcher16) { enabledChecksums |= EnableChecksum.Fletcher16; } if (doFletcher32) { enabledChecksums |= EnableChecksum.Fletcher32; } Checksum mediaChecksum = null; switch (inputFormat) { case IOpticalMediaImage opticalInput when opticalInput.Tracks != null: try { Checksum trackChecksum = null; if (wholeDisc) { mediaChecksum = new Checksum(enabledChecksums); } ulong previousTrackEnd = 0; List <Track> inputTracks = opticalInput.Tracks; foreach (Track currentTrack in inputTracks) { if (currentTrack.TrackStartSector - previousTrackEnd != 0 && wholeDisc) { for (ulong i = previousTrackEnd + 1; i < currentTrack.TrackStartSector; i++) { DicConsole.Write("\rHashing track-less sector {0}", i); byte[] hiddenSector = inputFormat.ReadSector(i); mediaChecksum?.Update(hiddenSector); } } DicConsole.DebugWriteLine("Checksum command", "Track {0} starts at sector {1} and ends at sector {2}", currentTrack.TrackSequence, currentTrack.TrackStartSector, currentTrack.TrackEndSector); if (separatedTracks) { trackChecksum = new Checksum(enabledChecksums); } ulong sectors = currentTrack.TrackEndSector - currentTrack.TrackStartSector + 1; ulong doneSectors = 0; DicConsole.WriteLine("Track {0} has {1} sectors", currentTrack.TrackSequence, sectors); while (doneSectors < sectors) { byte[] sector; if (sectors - doneSectors >= SECTORS_TO_READ) { sector = opticalInput.ReadSectors(doneSectors, SECTORS_TO_READ, currentTrack.TrackSequence); DicConsole.Write("\rHashings sectors {0} to {2} of track {1}", doneSectors, currentTrack.TrackSequence, doneSectors + SECTORS_TO_READ); doneSectors += SECTORS_TO_READ; } else { sector = opticalInput.ReadSectors(doneSectors, (uint)(sectors - doneSectors), currentTrack.TrackSequence); DicConsole.Write("\rHashings sectors {0} to {2} of track {1}", doneSectors, currentTrack.TrackSequence, doneSectors + (sectors - doneSectors)); doneSectors += sectors - doneSectors; } if (wholeDisc) { mediaChecksum?.Update(sector); } if (separatedTracks) { trackChecksum?.Update(sector); } } DicConsole.WriteLine(); if (separatedTracks) { if (trackChecksum != null) { foreach (ChecksumType chk in trackChecksum.End()) { DicConsole.WriteLine("Track {0}'s {1}: {2}", currentTrack.TrackSequence, chk.type, chk.Value); } } } previousTrackEnd = currentTrack.TrackEndSector; } if (opticalInput.Info.Sectors - previousTrackEnd != 0 && wholeDisc) { for (ulong i = previousTrackEnd + 1; i < opticalInput.Info.Sectors; i++) { DicConsole.Write("\rHashing track-less sector {0}", i); byte[] hiddenSector = inputFormat.ReadSector(i); mediaChecksum?.Update(hiddenSector); } } if (wholeDisc) { if (mediaChecksum != null) { foreach (ChecksumType chk in mediaChecksum.End()) { DicConsole.WriteLine("Disk's {0}: {1}", chk.type, chk.Value); } } } } catch (Exception ex) { if (MainClass.Debug) { DicConsole.DebugWriteLine("Could not get tracks because {0}", ex.Message); } else { DicConsole.WriteLine("Unable to get separate tracks, not checksumming them"); } } break; case ITapeImage tapeImage when tapeImage.IsTape && tapeImage.Files?.Count > 0: { Checksum trackChecksum = null; if (wholeDisc) { mediaChecksum = new Checksum(enabledChecksums); } ulong previousTrackEnd = 0; foreach (TapeFile currentFile in tapeImage.Files) { if (currentFile.FirstBlock - previousTrackEnd != 0 && wholeDisc) { for (ulong i = previousTrackEnd + 1; i < currentFile.FirstBlock; i++) { DicConsole.Write("\rHashing file-less block {0}", i); byte[] hiddenSector = inputFormat.ReadSector(i); mediaChecksum?.Update(hiddenSector); } } DicConsole.DebugWriteLine("Checksum command", "Track {0} starts at sector {1} and ends at block {2}", currentFile.File, currentFile.FirstBlock, currentFile.LastBlock); if (separatedTracks) { trackChecksum = new Checksum(enabledChecksums); } ulong sectors = currentFile.LastBlock - currentFile.FirstBlock + 1; ulong doneSectors = 0; DicConsole.WriteLine("File {0} has {1} sectors", currentFile.File, sectors); while (doneSectors < sectors) { byte[] sector; if (sectors - doneSectors >= SECTORS_TO_READ) { sector = tapeImage.ReadSectors(doneSectors + currentFile.FirstBlock, SECTORS_TO_READ); DicConsole.Write("\rHashings blocks {0} to {2} of file {1}", doneSectors, currentFile.File, doneSectors + SECTORS_TO_READ); doneSectors += SECTORS_TO_READ; } else { sector = tapeImage.ReadSectors(doneSectors + currentFile.FirstBlock, (uint)(sectors - doneSectors)); DicConsole.Write("\rHashings blocks {0} to {2} of file {1}", doneSectors, currentFile.File, doneSectors + (sectors - doneSectors)); doneSectors += sectors - doneSectors; } if (wholeDisc) { mediaChecksum?.Update(sector); } if (separatedTracks) { trackChecksum?.Update(sector); } } DicConsole.WriteLine(); if (separatedTracks) { if (trackChecksum != null) { foreach (ChecksumType chk in trackChecksum.End()) { DicConsole.WriteLine("File {0}'s {1}: {2}", currentFile.File, chk.type, chk.Value); } } } previousTrackEnd = currentFile.LastBlock; } if (tapeImage.Info.Sectors - previousTrackEnd != 0 && wholeDisc) { for (ulong i = previousTrackEnd + 1; i < tapeImage.Info.Sectors; i++) { DicConsole.Write("\rHashing file-less sector {0}", i); byte[] hiddenSector = inputFormat.ReadSector(i); mediaChecksum?.Update(hiddenSector); } } if (wholeDisc) { if (mediaChecksum != null) { foreach (ChecksumType chk in mediaChecksum.End()) { DicConsole.WriteLine("Tape's {0}: {1}", chk.type, chk.Value); } } } break; } default: { mediaChecksum = new Checksum(enabledChecksums); ulong sectors = inputFormat.Info.Sectors; DicConsole.WriteLine("Sectors {0}", sectors); ulong doneSectors = 0; while (doneSectors < sectors) { byte[] sector; if (sectors - doneSectors >= SECTORS_TO_READ) { sector = inputFormat.ReadSectors(doneSectors, SECTORS_TO_READ); DicConsole.Write("\rHashings sectors {0} to {1}", doneSectors, doneSectors + SECTORS_TO_READ); doneSectors += SECTORS_TO_READ; } else { sector = inputFormat.ReadSectors(doneSectors, (uint)(sectors - doneSectors)); DicConsole.Write("\rHashings sectors {0} to {1}", doneSectors, doneSectors + (sectors - doneSectors)); doneSectors += sectors - doneSectors; } mediaChecksum.Update(sector); } DicConsole.WriteLine(); foreach (ChecksumType chk in mediaChecksum.End()) { DicConsole.WriteLine("Disk's {0}: {1}", chk.type, chk.Value); } break; } } return((int)ErrorNumber.NoError); }
public override int Invoke(IEnumerable <string> arguments) { List <string> extra = Options.Parse(arguments); if (showHelp) { Options.WriteOptionDescriptions(CommandSet.Out); return((int)ErrorNumber.HelpRequested); } MainClass.PrintCopyright(); if (MainClass.Debug) { DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; } if (MainClass.Verbose) { DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; } Statistics.AddCommand("compare"); if (extra.Count > 2) { DicConsole.ErrorWriteLine("Too many arguments."); return((int)ErrorNumber.UnexpectedArgumentCount); } if (extra.Count <= 1) { DicConsole.ErrorWriteLine("Missing input image."); return((int)ErrorNumber.MissingArgument); } inputFile1 = extra[0]; inputFile2 = extra[1]; DicConsole.DebugWriteLine("Compare command", "--debug={0}", MainClass.Debug); DicConsole.DebugWriteLine("Compare command", "--input1={0}", inputFile1); DicConsole.DebugWriteLine("Compare command", "--input2={0}", inputFile2); DicConsole.DebugWriteLine("Compare command", "--verbose={0}", MainClass.Verbose); FiltersList filtersList = new FiltersList(); IFilter inputFilter1 = filtersList.GetFilter(inputFile1); filtersList = new FiltersList(); IFilter inputFilter2 = filtersList.GetFilter(inputFile2); if (inputFilter1 == null) { DicConsole.ErrorWriteLine("Cannot open input file 1"); return((int)ErrorNumber.CannotOpenFile); } if (inputFilter2 == null) { DicConsole.ErrorWriteLine("Cannot open input file 2"); return((int)ErrorNumber.CannotOpenFile); } IMediaImage input1Format = ImageFormat.Detect(inputFilter1); IMediaImage input2Format = ImageFormat.Detect(inputFilter2); if (input1Format == null) { DicConsole.ErrorWriteLine("Input file 1 format not identified, not proceeding with comparison."); return((int)ErrorNumber.UnrecognizedFormat); } if (MainClass.Verbose) { DicConsole.VerboseWriteLine("Input file 1 format identified by {0} ({1}).", input1Format.Name, input1Format.Id); } else { DicConsole.WriteLine("Input file 1 format identified by {0}.", input1Format.Name); } if (input2Format == null) { DicConsole.ErrorWriteLine("Input file 2 format not identified, not proceeding with comparison."); return((int)ErrorNumber.UnrecognizedFormat); } if (MainClass.Verbose) { DicConsole.VerboseWriteLine("Input file 2 format identified by {0} ({1}).", input2Format.Name, input2Format.Id); } else { DicConsole.WriteLine("Input file 2 format identified by {0}.", input2Format.Name); } input1Format.Open(inputFilter1); input2Format.Open(inputFilter2); Statistics.AddMediaFormat(input1Format.Format); Statistics.AddMediaFormat(input2Format.Format); Statistics.AddMedia(input1Format.Info.MediaType, false); Statistics.AddMedia(input2Format.Info.MediaType, false); Statistics.AddFilter(inputFilter1.Name); Statistics.AddFilter(inputFilter2.Name); StringBuilder sb = new StringBuilder(); if (MainClass.Verbose) { sb.AppendLine("\tDisc image 1\tDisc image 2"); sb.AppendLine("================================"); sb.AppendFormat("File\t{0}\t{1}", inputFile1, inputFile2).AppendLine(); sb.AppendFormat("Disc image format\t{0}\t{1}", input1Format.Name, input2Format.Name).AppendLine(); } else { sb.AppendFormat("Disc image 1: {0}", inputFile1).AppendLine(); sb.AppendFormat("Disc image 2: {0}", inputFile2).AppendLine(); } bool imagesDiffer = false; ImageInfo image1Info = input1Format.Info; ImageInfo image2Info = input2Format.Info; List <Session> image1Sessions = new List <Session>(); List <Session> image2Sessions = new List <Session>(); Dictionary <MediaTagType, byte[]> image1DiskTags = new Dictionary <MediaTagType, byte[]>(); Dictionary <MediaTagType, byte[]> image2DiskTags = new Dictionary <MediaTagType, byte[]>(); foreach (MediaTagType disktag in Enum.GetValues(typeof(MediaTagType))) { try { byte[] temparray = input1Format.ReadDiskTag(disktag); image1DiskTags.Add(disktag, temparray); } #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body catch { // ignored } #pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body } foreach (MediaTagType disktag in Enum.GetValues(typeof(MediaTagType))) { try { byte[] temparray = input2Format.ReadDiskTag(disktag); image2DiskTags.Add(disktag, temparray); } #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body catch { // ignored } #pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body } if (MainClass.Verbose) { sb.AppendFormat("Has partitions?\t{0}\t{1}", image1Info.HasPartitions, image2Info.HasPartitions) .AppendLine(); sb.AppendFormat("Has sessions?\t{0}\t{1}", image1Info.HasSessions, image2Info.HasSessions).AppendLine(); sb.AppendFormat("Image size\t{0}\t{1}", image1Info.ImageSize, image2Info.ImageSize).AppendLine(); sb.AppendFormat("Sectors\t{0}\t{1}", image1Info.Sectors, image2Info.Sectors).AppendLine(); sb.AppendFormat("Sector size\t{0}\t{1}", image1Info.SectorSize, image2Info.SectorSize).AppendLine(); sb.AppendFormat("Creation time\t{0}\t{1}", image1Info.CreationTime, image2Info.CreationTime) .AppendLine(); sb.AppendFormat("Last modification time\t{0}\t{1}", image1Info.LastModificationTime, image2Info.LastModificationTime).AppendLine(); sb.AppendFormat("Disk type\t{0}\t{1}", image1Info.MediaType, image2Info.MediaType).AppendLine(); sb.AppendFormat("Image version\t{0}\t{1}", image1Info.Version, image2Info.Version).AppendLine(); sb.AppendFormat("Image application\t{0}\t{1}", image1Info.Application, image2Info.Application) .AppendLine(); sb.AppendFormat("Image application version\t{0}\t{1}", image1Info.ApplicationVersion, image2Info.ApplicationVersion).AppendLine(); sb.AppendFormat("Image creator\t{0}\t{1}", image1Info.Creator, image2Info.Creator).AppendLine(); sb.AppendFormat("Image name\t{0}\t{1}", image1Info.MediaTitle, image2Info.MediaTitle).AppendLine(); sb.AppendFormat("Image comments\t{0}\t{1}", image1Info.Comments, image2Info.Comments).AppendLine(); sb.AppendFormat("Disk manufacturer\t{0}\t{1}", image1Info.MediaManufacturer, image2Info.MediaManufacturer).AppendLine(); sb.AppendFormat("Disk model\t{0}\t{1}", image1Info.MediaModel, image2Info.MediaModel).AppendLine(); sb.AppendFormat("Disk serial number\t{0}\t{1}", image1Info.MediaSerialNumber, image2Info.MediaSerialNumber).AppendLine(); sb.AppendFormat("Disk barcode\t{0}\t{1}", image1Info.MediaBarcode, image2Info.MediaBarcode) .AppendLine(); sb.AppendFormat("Disk part no.\t{0}\t{1}", image1Info.MediaPartNumber, image2Info.MediaPartNumber) .AppendLine(); sb.AppendFormat("Disk sequence\t{0}\t{1}", image1Info.MediaSequence, image2Info.MediaSequence) .AppendLine(); sb.AppendFormat("Last disk on sequence\t{0}\t{1}", image1Info.LastMediaSequence, image2Info.LastMediaSequence).AppendLine(); sb.AppendFormat("Drive manufacturer\t{0}\t{1}", image1Info.DriveManufacturer, image2Info.DriveManufacturer).AppendLine(); sb.AppendFormat("Drive firmware revision\t{0}\t{1}", image1Info.DriveFirmwareRevision, image2Info.DriveFirmwareRevision).AppendLine(); sb.AppendFormat("Drive model\t{0}\t{1}", image1Info.DriveModel, image2Info.DriveModel).AppendLine(); sb.AppendFormat("Drive serial number\t{0}\t{1}", image1Info.DriveSerialNumber, image2Info.DriveSerialNumber).AppendLine(); foreach (MediaTagType disktag in Enum.GetValues(typeof(MediaTagType))) { sb.AppendFormat("Has {0}?\t{1}\t{2}", disktag, image1DiskTags.ContainsKey(disktag), image2DiskTags.ContainsKey(disktag)).AppendLine(); } } DicConsole.WriteLine("Comparing disk image characteristics"); if (image1Info.HasPartitions != image2Info.HasPartitions) { imagesDiffer = true; if (!MainClass.Verbose) { sb.AppendLine("Image partitioned status differ"); } } if (image1Info.HasSessions != image2Info.HasSessions) { imagesDiffer = true; if (!MainClass.Verbose) { sb.AppendLine("Image session status differ"); } } if (image1Info.Sectors != image2Info.Sectors) { imagesDiffer = true; if (!MainClass.Verbose) { sb.AppendLine("Image sectors differ"); } } if (image1Info.SectorSize != image2Info.SectorSize) { imagesDiffer = true; if (!MainClass.Verbose) { sb.AppendLine("Image sector size differ"); } } if (image1Info.MediaType != image2Info.MediaType) { imagesDiffer = true; if (!MainClass.Verbose) { sb.AppendLine("Disk type differ"); } } ulong leastSectors; if (image1Info.Sectors < image2Info.Sectors) { imagesDiffer = true; leastSectors = image1Info.Sectors; if (!MainClass.Verbose) { sb.AppendLine("Image 2 has more sectors"); } } else if (image1Info.Sectors > image2Info.Sectors) { imagesDiffer = true; leastSectors = image2Info.Sectors; if (!MainClass.Verbose) { sb.AppendLine("Image 1 has more sectors"); } } else { leastSectors = image1Info.Sectors; } DicConsole.WriteLine("Comparing sectors..."); for (ulong sector = 0; sector < leastSectors; sector++) { DicConsole.Write("\rComparing sector {0} of {1}...", sector + 1, leastSectors); try { byte[] image1Sector = input1Format.ReadSector(sector); byte[] image2Sector = input2Format.ReadSector(sector); ArrayHelpers.CompareBytes(out bool different, out bool sameSize, image1Sector, image2Sector); if (different) { imagesDiffer = true; sb.AppendFormat("Sector {0} is different", sector).AppendLine(); } else if (!sameSize) { imagesDiffer = true; sb .AppendFormat("Sector {0} has different sizes ({1} bytes in image 1, {2} in image 2) but are otherwise identical", sector, image1Sector.LongLength, image2Sector.LongLength).AppendLine(); } } #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body catch { // ignored } #pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body } DicConsole.WriteLine(); sb.AppendLine(imagesDiffer ? "Images differ" : "Images do not differ"); DicConsole.WriteLine(sb.ToString()); return((int)ErrorNumber.NoError); }