예제 #1
0
        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("entropy");

            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("Entropy command", "--debug={0}", MainClass.Debug);
            DicConsole.DebugWriteLine("Entropy command", "--duplicated-sectors={0}", duplicatedSectors);
            DicConsole.DebugWriteLine("Entropy command", "--input={0}", inputFile);
            DicConsole.DebugWriteLine("Entropy command", "--separated-tracks={0}", separatedTracks);
            DicConsole.DebugWriteLine("Entropy command", "--verbose={0}", MainClass.Verbose);
            DicConsole.DebugWriteLine("Entropy 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);

            Entropy entropyCalculator = new Entropy(MainClass.Debug, MainClass.Verbose, inputFormat);

            entropyCalculator.InitProgressEvent    += Progress.InitProgress;
            entropyCalculator.InitProgress2Event   += Progress.InitProgress2;
            entropyCalculator.UpdateProgressEvent  += Progress.UpdateProgress;
            entropyCalculator.UpdateProgress2Event += Progress.UpdateProgress2;
            entropyCalculator.EndProgressEvent     += Progress.EndProgress;
            entropyCalculator.EndProgress2Event    += Progress.EndProgress2;

            if (separatedTracks)
            {
                EntropyResults[] tracksEntropy = entropyCalculator.CalculateTracksEntropy(duplicatedSectors);
                foreach (EntropyResults trackEntropy in tracksEntropy)
                {
                    DicConsole.WriteLine("Entropy for track {0} is {1:F4}.", trackEntropy.Track, trackEntropy.Entropy);
                    if (trackEntropy.UniqueSectors != null)
                    {
                        DicConsole.WriteLine("Track {0} has {1} unique sectors ({2:P3})", trackEntropy.Track,
                                             trackEntropy.UniqueSectors,
                                             (double)trackEntropy.UniqueSectors / (double)trackEntropy.Sectors);
                    }
                }
            }

            if (!wholeDisc)
            {
                return((int)ErrorNumber.NoError);
            }

            EntropyResults entropy = entropyCalculator.CalculateMediaEntropy(duplicatedSectors);

            DicConsole.WriteLine("Entropy for disk is {0:F4}.", entropy.Entropy);
            if (entropy.UniqueSectors != null)
            {
                DicConsole.WriteLine("Disk has {0} unique sectors ({1:P3})", entropy.UniqueSectors,
                                     (double)entropy.UniqueSectors / (double)entropy.Sectors);
            }

            return((int)ErrorNumber.NoError);
        }
예제 #2
0
        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("analyze");

            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("Analyze command", "--debug={0}", MainClass.Debug);
            DicConsole.DebugWriteLine("Analyze command", "--encoding={0}", encodingName);
            DicConsole.DebugWriteLine("Analyze command", "--filesystems={0}", searchForFilesystems);
            DicConsole.DebugWriteLine("Analyze command", "--input={0}", inputFile);
            DicConsole.DebugWriteLine("Analyze command", "--partitions={0}", searchForPartitions);
            DicConsole.DebugWriteLine("Analyze command", "--verbose={0}", MainClass.Verbose);

            FiltersList filtersList = new FiltersList();
            IFilter     inputFilter = filtersList.GetFilter(inputFile);

            if (inputFilter == null)
            {
                DicConsole.ErrorWriteLine("Cannot open specified file.");
                return((int)ErrorNumber.CannotOpenFile);
            }

            Encoding encoding = null;

            if (encodingName != null)
            {
                try
                {
                    encoding = Claunia.Encoding.Encoding.GetEncoding(encodingName);
                    if (MainClass.Verbose)
                    {
                        DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName);
                    }
                }
                catch (ArgumentException)
                {
                    DicConsole.ErrorWriteLine("Specified encoding is not supported.");
                    return((int)ErrorNumber.EncodingUnknown);
                }
            }

            PluginBase plugins = GetPluginBase.Instance;

            bool checkraw = false;

            try
            {
                IMediaImage imageFormat = ImageFormat.Detect(inputFilter);

                if (imageFormat == null)
                {
                    DicConsole.WriteLine("Image format not identified, not proceeding with analysis.");
                    return((int)ErrorNumber.UnrecognizedFormat);
                }

                if (MainClass.Verbose)
                {
                    DicConsole.VerboseWriteLine("Image format identified by {0} ({1}).", imageFormat.Name,
                                                imageFormat.Id);
                }
                else
                {
                    DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name);
                }
                DicConsole.WriteLine();

                try
                {
                    if (!imageFormat.Open(inputFilter))
                    {
                        DicConsole.WriteLine("Unable to open image format");
                        DicConsole.WriteLine("No error given");
                        return((int)ErrorNumber.CannotOpenFormat);
                    }

                    if (MainClass.Verbose)
                    {
                        ImageInfo.PrintImageInfo(imageFormat);
                        DicConsole.WriteLine();
                    }

                    Statistics.AddMediaFormat(imageFormat.Format);
                    Statistics.AddMedia(imageFormat.Info.MediaType, false);
                    Statistics.AddFilter(inputFilter.Name);
                }
                catch (Exception ex)
                {
                    DicConsole.ErrorWriteLine("Unable to open image format");
                    DicConsole.ErrorWriteLine("Error: {0}", ex.Message);
                    DicConsole.DebugWriteLine("Analyze command", "Stack trace: {0}", ex.StackTrace);
                    return((int)ErrorNumber.CannotOpenFormat);
                }

                List <string> idPlugins;
                IFilesystem   plugin;
                string        information;
                if (searchForPartitions)
                {
                    List <Partition> partitions = Core.Partitions.GetAll(imageFormat);
                    Core.Partitions.AddSchemesToStats(partitions);

                    if (partitions.Count == 0)
                    {
                        DicConsole.DebugWriteLine("Analyze command", "No partitions found");
                        if (!searchForFilesystems)
                        {
                            DicConsole.WriteLine("No partitions founds, not searching for filesystems");
                            return((int)ErrorNumber.NothingFound);
                        }

                        checkraw = true;
                    }
                    else
                    {
                        DicConsole.WriteLine("{0} partitions found.", partitions.Count);

                        for (int i = 0; i < partitions.Count; i++)
                        {
                            DicConsole.WriteLine();
                            DicConsole.WriteLine("Partition {0}:", partitions[i].Sequence);
                            DicConsole.WriteLine("Partition name: {0}", partitions[i].Name);
                            DicConsole.WriteLine("Partition type: {0}", partitions[i].Type);
                            DicConsole.WriteLine("Partition start: sector {0}, byte {1}", partitions[i].Start,
                                                 partitions[i].Offset);
                            DicConsole.WriteLine("Partition length: {0} sectors, {1} bytes", partitions[i].Length,
                                                 partitions[i].Size);
                            DicConsole.WriteLine("Partition scheme: {0}", partitions[i].Scheme);
                            DicConsole.WriteLine("Partition description:");
                            DicConsole.WriteLine(partitions[i].Description);

                            if (!searchForFilesystems)
                            {
                                continue;
                            }

                            DicConsole.WriteLine("Identifying filesystem on partition");

                            Core.Filesystems.Identify(imageFormat, out idPlugins, partitions[i]);
                            if (idPlugins.Count == 0)
                            {
                                DicConsole.WriteLine("Filesystem not identified");
                            }
                            else if (idPlugins.Count > 1)
                            {
                                DicConsole.WriteLine($"Identified by {idPlugins.Count} plugins");

                                foreach (string pluginName in idPlugins)
                                {
                                    if (plugins.PluginsList.TryGetValue(pluginName, out plugin))
                                    {
                                        DicConsole.WriteLine($"As identified by {plugin.Name}.");
                                        plugin.GetInformation(imageFormat, partitions[i], out information, encoding);
                                        DicConsole.Write(information);
                                        Statistics.AddFilesystem(plugin.XmlFsType.Type);
                                    }
                                }
                            }
                            else
                            {
                                plugins.PluginsList.TryGetValue(idPlugins[0], out plugin);
                                if (plugin == null)
                                {
                                    continue;
                                }

                                DicConsole.WriteLine($"Identified by {plugin.Name}.");
                                plugin.GetInformation(imageFormat, partitions[i], out information, encoding);
                                DicConsole.Write("{0}", information);
                                Statistics.AddFilesystem(plugin.XmlFsType.Type);
                            }
                        }
                    }
                }

                if (checkraw)
                {
                    Partition wholePart = new Partition
                    {
                        Name   = "Whole device",
                        Length = imageFormat.Info.Sectors,
                        Size   = imageFormat.Info.Sectors * imageFormat.Info.SectorSize
                    };

                    Core.Filesystems.Identify(imageFormat, out idPlugins, wholePart);
                    if (idPlugins.Count == 0)
                    {
                        DicConsole.WriteLine("Filesystem not identified");
                    }
                    else if (idPlugins.Count > 1)
                    {
                        DicConsole.WriteLine($"Identified by {idPlugins.Count} plugins");

                        foreach (string pluginName in idPlugins)
                        {
                            if (plugins.PluginsList.TryGetValue(pluginName, out plugin))
                            {
                                DicConsole.WriteLine($"As identified by {plugin.Name}.");
                                plugin.GetInformation(imageFormat, wholePart, out information, encoding);
                                DicConsole.Write(information);
                                Statistics.AddFilesystem(plugin.XmlFsType.Type);
                            }
                        }
                    }
                    else
                    {
                        plugins.PluginsList.TryGetValue(idPlugins[0], out plugin);
                        if (plugin != null)
                        {
                            DicConsole.WriteLine($"Identified by {plugin.Name}.");
                            plugin.GetInformation(imageFormat, wholePart, out information, encoding);
                            DicConsole.Write(information);
                            Statistics.AddFilesystem(plugin.XmlFsType.Type);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                DicConsole.ErrorWriteLine($"Error reading file: {ex.Message}");
                DicConsole.DebugWriteLine("Analyze command", ex.StackTrace);
                return((int)ErrorNumber.UnexpectedException);
            }

            return((int)ErrorNumber.NoError);
        }
예제 #3
0
        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("verify");

            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("Verify command", "--debug={0}", MainClass.Debug);
            DicConsole.DebugWriteLine("Verify command", "--input={0}", inputFile);
            DicConsole.DebugWriteLine("Verify command", "--verbose={0}", MainClass.Verbose);
            DicConsole.DebugWriteLine("Verify command", "--verify-disc={0}", verifyDisc);
            DicConsole.DebugWriteLine("Verify command", "--verify-sectors={0}", verifySectors);

            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 verifying");
                return((int)ErrorNumber.FormatNotFound);
            }

            inputFormat.Open(inputFilter);
            Statistics.AddMediaFormat(inputFormat.Format);
            Statistics.AddMedia(inputFormat.Info.MediaType, false);
            Statistics.AddFilter(inputFilter.Name);

            bool?correctImage   = null;
            long totalSectors   = 0;
            long errorSectors   = 0;
            bool?correctSectors = null;
            long unknownSectors = 0;

            IVerifiableImage        verifiableImage        = inputFormat as IVerifiableImage;
            IVerifiableSectorsImage verifiableSectorsImage = inputFormat as IVerifiableSectorsImage;

            if (verifiableImage is null && verifiableSectorsImage is null)
            {
                DicConsole.ErrorWriteLine("The specified image does not support any kind of verification");
                return((int)ErrorNumber.NotVerificable);
            }

            if (verifyDisc && verifiableImage != null)
            {
                DateTime startCheck      = DateTime.UtcNow;
                bool?    discCheckStatus = verifiableImage.VerifyMediaImage();
                DateTime endCheck        = DateTime.UtcNow;

                TimeSpan checkTime = endCheck - startCheck;

                switch (discCheckStatus)
                {
                case true:
                    DicConsole.WriteLine("Disc image checksums are correct");
                    break;

                case false:
                    DicConsole.WriteLine("Disc image checksums are incorrect");
                    break;

                case null:
                    DicConsole.WriteLine("Disc image does not contain checksums");
                    break;
                }

                correctImage = discCheckStatus;
                DicConsole.VerboseWriteLine("Checking disc image checksums took {0} seconds", checkTime.TotalSeconds);
            }

            if (verifySectors)
            {
                DateTime     startCheck  = DateTime.Now;
                DateTime     endCheck    = startCheck;
                List <ulong> failingLbas = new List <ulong>();
                List <ulong> unknownLbas = new List <ulong>();

                if (verifiableSectorsImage is IOpticalMediaImage opticalMediaImage)
                {
                    List <Track> inputTracks      = opticalMediaImage.Tracks;
                    ulong        currentSectorAll = 0;

                    startCheck = DateTime.UtcNow;
                    foreach (Track currentTrack in inputTracks)
                    {
                        ulong remainingSectors = currentTrack.TrackEndSector - currentTrack.TrackStartSector;
                        ulong currentSector    = 0;

                        while (remainingSectors > 0)
                        {
                            DicConsole.Write("\rChecking sector {0} of {1}, on track {2}", currentSectorAll,
                                             inputFormat.Info.Sectors, currentTrack.TrackSequence);

                            List <ulong> tempfailingLbas;
                            List <ulong> tempunknownLbas;

                            if (remainingSectors < 512)
                            {
                                opticalMediaImage.VerifySectors(currentSector, (uint)remainingSectors,
                                                                currentTrack.TrackSequence, out tempfailingLbas,
                                                                out tempunknownLbas);
                            }
                            else
                            {
                                opticalMediaImage.VerifySectors(currentSector, 512, currentTrack.TrackSequence,
                                                                out tempfailingLbas, out tempunknownLbas);
                            }

                            failingLbas.AddRange(tempfailingLbas);

                            unknownLbas.AddRange(tempunknownLbas);

                            if (remainingSectors < 512)
                            {
                                currentSector    += remainingSectors;
                                currentSectorAll += remainingSectors;
                                remainingSectors  = 0;
                            }
                            else
                            {
                                currentSector    += 512;
                                currentSectorAll += 512;
                                remainingSectors -= 512;
                            }
                        }
                    }

                    endCheck = DateTime.UtcNow;
                }
                else if (verifiableSectorsImage != null)
                {
                    ulong remainingSectors = inputFormat.Info.Sectors;
                    ulong currentSector    = 0;

                    startCheck = DateTime.UtcNow;
                    while (remainingSectors > 0)
                    {
                        DicConsole.Write("\rChecking sector {0} of {1}", currentSector, inputFormat.Info.Sectors);

                        List <ulong> tempfailingLbas;
                        List <ulong> tempunknownLbas;

                        if (remainingSectors < 512)
                        {
                            verifiableSectorsImage.VerifySectors(currentSector, (uint)remainingSectors,
                                                                 out tempfailingLbas, out tempunknownLbas);
                        }
                        else
                        {
                            verifiableSectorsImage.VerifySectors(currentSector, 512, out tempfailingLbas,
                                                                 out tempunknownLbas);
                        }

                        failingLbas.AddRange(tempfailingLbas);

                        unknownLbas.AddRange(tempunknownLbas);

                        if (remainingSectors < 512)
                        {
                            currentSector   += remainingSectors;
                            remainingSectors = 0;
                        }
                        else
                        {
                            currentSector    += 512;
                            remainingSectors -= 512;
                        }
                    }

                    endCheck = DateTime.UtcNow;
                }

                TimeSpan checkTime = endCheck - startCheck;

                DicConsole.Write("\r" + new string(' ', System.Console.WindowWidth - 1) + "\r");

                if (unknownSectors > 0)
                {
                    DicConsole.WriteLine("There is at least one sector that does not contain a checksum");
                }
                if (errorSectors > 0)
                {
                    DicConsole.WriteLine("There is at least one sector with incorrect checksum or errors");
                }
                if (unknownSectors == 0 && errorSectors == 0)
                {
                    DicConsole.WriteLine("All sector checksums are correct");
                }

                DicConsole.VerboseWriteLine("Checking sector checksums took {0} seconds", checkTime.TotalSeconds);

                if (MainClass.Verbose)
                {
                    DicConsole.VerboseWriteLine("LBAs with error:");
                    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.Info.Sectors)
                    {
                        DicConsole.VerboseWriteLine("\tall sectors.");
                    }
                    else
                    {
                        foreach (ulong t in unknownLbas)
                        {
                            DicConsole.VerboseWriteLine("\t{0}", t);
                        }
                    }
                }

                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.Info.Sectors;
                errorSectors   = failingLbas.Count;
                unknownSectors = unknownLbas.Count;
                if (failingLbas.Count > 0)
                {
                    correctSectors = false;
                }
                else if ((ulong)unknownLbas.Count < inputFormat.Info.Sectors)
                {
                    correctSectors = true;
                }
            }

            switch (correctImage)
            {
            case null when correctSectors is null:   return((int)ErrorNumber.NotVerificable);

            case null when correctSectors == false:  return((int)ErrorNumber.BadSectorsImageNotVerified);

            case null when correctSectors == true:   return((int)ErrorNumber.CorrectSectorsImageNotVerified);

            case false when correctSectors is null:  return((int)ErrorNumber.BadImageSectorsNotVerified);

            case false when correctSectors == false: return((int)ErrorNumber.BadImageBadSectors);

            case false when correctSectors == true:  return((int)ErrorNumber.CorrectSectorsBadImage);

            case true when correctSectors is null:   return((int)ErrorNumber.CorrectImageSectorsNotVerified);

            case true when correctSectors == false:  return((int)ErrorNumber.CorrectImageBadSectors);

            case true when correctSectors == true:   return((int)ErrorNumber.NoError);
            }

            return((int)ErrorNumber.NoError);
        }
예제 #4
0
        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("extract-files");

            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("Extract-Files command", "--debug={0}", MainClass.Debug);
            DicConsole.DebugWriteLine("Extract-Files command", "--encoding={0}", encodingName);
            DicConsole.DebugWriteLine("Extract-Files command", "--input={0}", inputFile);
            DicConsole.DebugWriteLine("Extract-Files command", "--options={0}", pluginOptions);
            DicConsole.DebugWriteLine("Extract-Files command", "--output={0}", outputDir);
            DicConsole.DebugWriteLine("Extract-Files command", "--verbose={0}", MainClass.Verbose);
            DicConsole.DebugWriteLine("Extract-Files command", "--xattrs={0}", extractXattrs);

            FiltersList filtersList = new FiltersList();
            IFilter     inputFilter = filtersList.GetFilter(inputFile);

            Dictionary <string, string> parsedOptions = Core.Options.Parse(pluginOptions);

            DicConsole.DebugWriteLine("Extract-Files command", "Parsed options:");
            foreach (KeyValuePair <string, string> parsedOption in parsedOptions)
            {
                DicConsole.DebugWriteLine("Extract-Files command", "{0} = {1}", parsedOption.Key, parsedOption.Value);
            }
            parsedOptions.Add("debug", MainClass.Debug.ToString());

            if (inputFilter == null)
            {
                DicConsole.ErrorWriteLine("Cannot open specified file.");
                return((int)ErrorNumber.CannotOpenFile);
            }

            Encoding encoding = null;

            if (encodingName != null)
            {
                try
                {
                    encoding = Claunia.Encoding.Encoding.GetEncoding(encodingName);
                    if (MainClass.Verbose)
                    {
                        DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName);
                    }
                }
                catch (ArgumentException)
                {
                    DicConsole.ErrorWriteLine("Specified encoding is not supported.");
                    return((int)ErrorNumber.EncodingUnknown);
                }
            }

            PluginBase plugins = GetPluginBase.Instance;

            try
            {
                IMediaImage imageFormat = ImageFormat.Detect(inputFilter);

                if (imageFormat == null)
                {
                    DicConsole.WriteLine("Image format not identified, not proceeding with analysis.");
                    return((int)ErrorNumber.UnrecognizedFormat);
                }

                if (MainClass.Verbose)
                {
                    DicConsole.VerboseWriteLine("Image format identified by {0} ({1}).", imageFormat.Name,
                                                imageFormat.Id);
                }
                else
                {
                    DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name);
                }

                if (outputDir == null)
                {
                    DicConsole.WriteLine("Output directory missing.");
                    return((int)ErrorNumber.MissingArgument);
                }

                if (Directory.Exists(outputDir) || File.Exists(outputDir))
                {
                    DicConsole.ErrorWriteLine("Destination exists, aborting.");
                    return((int)ErrorNumber.DestinationExists);
                }

                Directory.CreateDirectory(outputDir);

                try
                {
                    if (!imageFormat.Open(inputFilter))
                    {
                        DicConsole.WriteLine("Unable to open image format");
                        DicConsole.WriteLine("No error given");
                        return((int)ErrorNumber.CannotOpenFormat);
                    }

                    DicConsole.DebugWriteLine("Extract-Files command", "Correctly opened image file.");
                    DicConsole.DebugWriteLine("Extract-Files command", "Image without headers is {0} bytes.",
                                              imageFormat.Info.ImageSize);
                    DicConsole.DebugWriteLine("Extract-Files command", "Image has {0} sectors.",
                                              imageFormat.Info.Sectors);
                    DicConsole.DebugWriteLine("Extract-Files command", "Image identifies disk type as {0}.",
                                              imageFormat.Info.MediaType);

                    Statistics.AddMediaFormat(imageFormat.Format);
                    Statistics.AddMedia(imageFormat.Info.MediaType, false);
                    Statistics.AddFilter(inputFilter.Name);
                }
                catch (Exception ex)
                {
                    DicConsole.ErrorWriteLine("Unable to open image format");
                    DicConsole.ErrorWriteLine("Error: {0}", ex.Message);
                    return((int)ErrorNumber.CannotOpenFormat);
                }

                List <Partition> partitions = Core.Partitions.GetAll(imageFormat);
                Core.Partitions.AddSchemesToStats(partitions);

                List <string>       idPlugins;
                IReadOnlyFilesystem plugin;
                Errno error;
                if (partitions.Count == 0)
                {
                    DicConsole.DebugWriteLine("Extract-Files command", "No partitions found");
                }
                else
                {
                    DicConsole.WriteLine("{0} partitions found.", partitions.Count);

                    for (int i = 0; i < partitions.Count; i++)
                    {
                        DicConsole.WriteLine();
                        DicConsole.WriteLine("Partition {0}:", partitions[i].Sequence);

                        DicConsole.WriteLine("Identifying filesystem on partition");

                        Core.Filesystems.Identify(imageFormat, out idPlugins, partitions[i]);
                        if (idPlugins.Count == 0)
                        {
                            DicConsole.WriteLine("Filesystem not identified");
                        }
                        else if (idPlugins.Count > 1)
                        {
                            DicConsole.WriteLine($"Identified by {idPlugins.Count} plugins");

                            foreach (string pluginName in idPlugins)
                            {
                                if (plugins.ReadOnlyFilesystems.TryGetValue(pluginName, out plugin))
                                {
                                    DicConsole.WriteLine($"As identified by {plugin.Name}.");
                                    IReadOnlyFilesystem fs = (IReadOnlyFilesystem)plugin
                                                             .GetType()
                                                             .GetConstructor(Type.EmptyTypes)
                                                             ?.Invoke(new object[] { });

                                    error = fs.Mount(imageFormat, partitions[i], encoding, parsedOptions, @namespace);
                                    if (error == Errno.NoError)
                                    {
                                        string volumeName =
                                            string.IsNullOrEmpty(fs.XmlFsType.VolumeName)
                                                ? "NO NAME"
                                                : fs.XmlFsType.VolumeName;

                                        ExtractFilesInDir("/", fs, volumeName);

                                        Statistics.AddFilesystem(fs.XmlFsType.Type);
                                    }
                                    else
                                    {
                                        DicConsole.ErrorWriteLine("Unable to mount device, error {0}",
                                                                  error.ToString());
                                    }
                                }
                            }
                        }
                        else
                        {
                            plugins.ReadOnlyFilesystems.TryGetValue(idPlugins[0], out plugin);
                            DicConsole.WriteLine($"Identified by {plugin.Name}.");
                            IReadOnlyFilesystem fs = (IReadOnlyFilesystem)plugin
                                                     .GetType().GetConstructor(Type.EmptyTypes)
                                                     ?.Invoke(new object[] { });
                            error = fs.Mount(imageFormat, partitions[i], encoding, parsedOptions, @namespace);
                            if (error == Errno.NoError)
                            {
                                string volumeName = string.IsNullOrEmpty(fs.XmlFsType.VolumeName)
                                                        ? "NO NAME"
                                                        : fs.XmlFsType.VolumeName;

                                ExtractFilesInDir("/", fs, volumeName);

                                Statistics.AddFilesystem(fs.XmlFsType.Type);
                            }
                            else
                            {
                                DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString());
                            }
                        }
                    }
                }

                Partition wholePart = new Partition
                {
                    Name   = "Whole device",
                    Length = imageFormat.Info.Sectors,
                    Size   = imageFormat.Info.Sectors * imageFormat.Info.SectorSize
                };

                Core.Filesystems.Identify(imageFormat, out idPlugins, wholePart);
                if (idPlugins.Count == 0)
                {
                    DicConsole.WriteLine("Filesystem not identified");
                }
                else if (idPlugins.Count > 1)
                {
                    DicConsole.WriteLine($"Identified by {idPlugins.Count} plugins");

                    foreach (string pluginName in idPlugins)
                    {
                        if (plugins.ReadOnlyFilesystems.TryGetValue(pluginName, out plugin))
                        {
                            DicConsole.WriteLine($"As identified by {plugin.Name}.");
                            IReadOnlyFilesystem fs = (IReadOnlyFilesystem)plugin
                                                     .GetType().GetConstructor(Type.EmptyTypes)
                                                     ?.Invoke(new object[] { });
                            error = fs.Mount(imageFormat, wholePart, encoding, parsedOptions, @namespace);
                            if (error == Errno.NoError)
                            {
                                string volumeName = string.IsNullOrEmpty(fs.XmlFsType.VolumeName)
                                                        ? "NO NAME"
                                                        : fs.XmlFsType.VolumeName;

                                ExtractFilesInDir("/", fs, volumeName);

                                Statistics.AddFilesystem(fs.XmlFsType.Type);
                            }
                            else
                            {
                                DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString());
                            }
                        }
                    }
                }
                else
                {
                    plugins.ReadOnlyFilesystems.TryGetValue(idPlugins[0], out plugin);
                    DicConsole.WriteLine($"Identified by {plugin.Name}.");
                    IReadOnlyFilesystem fs =
                        (IReadOnlyFilesystem)plugin.GetType().GetConstructor(Type.EmptyTypes)?.Invoke(new object[] { });
                    error = fs.Mount(imageFormat, wholePart, encoding, parsedOptions, @namespace);
                    if (error == Errno.NoError)
                    {
                        string volumeName = string.IsNullOrEmpty(fs.XmlFsType.VolumeName)
                                                ? "NO NAME"
                                                : fs.XmlFsType.VolumeName;

                        ExtractFilesInDir("/", fs, volumeName);

                        Statistics.AddFilesystem(fs.XmlFsType.Type);
                    }
                    else
                    {
                        DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString());
                    }
                }
            }
            catch (Exception ex)
            {
                DicConsole.ErrorWriteLine($"Error reading file: {ex.Message}");
                DicConsole.DebugWriteLine("Extract-Files command", ex.StackTrace);
                return((int)ErrorNumber.UnexpectedException);
            }

            return((int)ErrorNumber.NoError);
        }
예제 #5
0
        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("convert-image");

            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);
            }

            inputFile  = extra[0];
            outputFile = extra[1];

            DicConsole.DebugWriteLine("Analyze command", "--cicm-xml={0}", cicmXml);
            DicConsole.DebugWriteLine("Analyze command", "--comments={0}", comments);
            DicConsole.DebugWriteLine("Analyze command", "--count={0}", count);
            DicConsole.DebugWriteLine("Analyze command", "--creator={0}", creator);
            DicConsole.DebugWriteLine("Analyze command", "--debug={0}", MainClass.Debug);
            DicConsole.DebugWriteLine("Analyze command", "--drive-manufacturer={0}", driveManufacturer);
            DicConsole.DebugWriteLine("Analyze command", "--drive-model={0}", driveModel);
            DicConsole.DebugWriteLine("Analyze command", "--drive-revision={0}", driveFirmwareRevision);
            DicConsole.DebugWriteLine("Analyze command", "--drive-serial={0}", driveSerialNumber);
            DicConsole.DebugWriteLine("Analyze command", "--force={0}", force);
            DicConsole.DebugWriteLine("Analyze command", "--format={0}", wantedOutputFormat);
            DicConsole.DebugWriteLine("Analyze command", "--input={0}", inputFile);
            DicConsole.DebugWriteLine("Analyze command", "--media-barcode={0}", mediaBarcode);
            DicConsole.DebugWriteLine("Analyze command", "--media-lastsequence={0}", lastMediaSequence);
            DicConsole.DebugWriteLine("Analyze command", "--media-manufacturer={0}", mediaManufacturer);
            DicConsole.DebugWriteLine("Analyze command", "--media-model={0}", mediaModel);
            DicConsole.DebugWriteLine("Analyze command", "--media-partnumber={0}", mediaPartNumber);
            DicConsole.DebugWriteLine("Analyze command", "--media-sequence={0}", mediaSequence);
            DicConsole.DebugWriteLine("Analyze command", "--media-serial={0}", mediaSerialNumber);
            DicConsole.DebugWriteLine("Analyze command", "--media-title={0}", mediaTitle);
            DicConsole.DebugWriteLine("Analyze command", "--options={0}", outputOptions);
            DicConsole.DebugWriteLine("Analyze command", "--output={0}", outputFile);
            DicConsole.DebugWriteLine("Analyze command", "--resume-file={0}", resumeFile);
            DicConsole.DebugWriteLine("Analyze command", "--verbose={0}", MainClass.Verbose);

            Dictionary <string, string> parsedOptions = Core.Options.Parse(outputOptions);

            DicConsole.DebugWriteLine("Analyze command", "Parsed options:");
            foreach (KeyValuePair <string, string> parsedOption in parsedOptions)
            {
                DicConsole.DebugWriteLine("Analyze command", "{0} = {1}", parsedOption.Key, parsedOption.Value);
            }

            if (count == 0)
            {
                DicConsole.ErrorWriteLine("Need to specify more than 0 sectors to copy at once");
                return((int)ErrorNumber.InvalidArgument);
            }

            Resume           resume  = null;
            CICMMetadataType sidecar = null;

            XmlSerializer xs = new XmlSerializer(typeof(CICMMetadataType));

            if (cicmXml != null)
            {
                if (File.Exists(cicmXml))
                {
                    try
                    {
                        StreamReader sr = new StreamReader(cicmXml);
                        sidecar = (CICMMetadataType)xs.Deserialize(sr);
                        sr.Close();
                    }
                    catch
                    {
                        DicConsole.ErrorWriteLine("Incorrect metadata sidecar file, not continuing...");
                        return((int)ErrorNumber.InvalidSidecar);
                    }
                }
                else
                {
                    DicConsole.ErrorWriteLine("Could not find metadata sidecar, not continuing...");
                    return((int)ErrorNumber.FileNotFound);
                }
            }

            xs = new XmlSerializer(typeof(Resume));
            if (resumeFile != null)
            {
                if (File.Exists(resumeFile))
                {
                    try
                    {
                        StreamReader sr = new StreamReader(resumeFile);
                        resume = (Resume)xs.Deserialize(sr);
                        sr.Close();
                    }
                    catch
                    {
                        DicConsole.ErrorWriteLine("Incorrect resume file, not continuing...");
                        return((int)ErrorNumber.InvalidResume);
                    }
                }
                else
                {
                    DicConsole.ErrorWriteLine("Could not find resume file, not continuing...");
                    return((int)ErrorNumber.FileNotFound);
                }
            }

            FiltersList filtersList = new FiltersList();
            IFilter     inputFilter = filtersList.GetFilter(inputFile);

            if (inputFilter == null)
            {
                DicConsole.ErrorWriteLine("Cannot open specified file.");
                return((int)ErrorNumber.CannotOpenFile);
            }

            if (File.Exists(outputFile))
            {
                DicConsole.ErrorWriteLine("Output file already exists, not continuing.");
                return((int)ErrorNumber.DestinationExists);
            }

            PluginBase  plugins     = GetPluginBase.Instance;
            IMediaImage inputFormat = ImageFormat.Detect(inputFilter);

            if (inputFormat == null)
            {
                DicConsole.WriteLine("Input image format not identified, not proceeding with conversion.");
                return((int)ErrorNumber.UnrecognizedFormat);
            }

            if (MainClass.Verbose)
            {
                DicConsole.VerboseWriteLine("Input image format identified by {0} ({1}).", inputFormat.Name,
                                            inputFormat.Id);
            }
            else
            {
                DicConsole.WriteLine("Input image format identified by {0}.", inputFormat.Name);
            }

            try
            {
                if (!inputFormat.Open(inputFilter))
                {
                    DicConsole.WriteLine("Unable to open image format");
                    DicConsole.WriteLine("No error given");
                    return((int)ErrorNumber.CannotOpenFormat);
                }

                DicConsole.DebugWriteLine("Convert-image command", "Correctly opened image file.");
                DicConsole.DebugWriteLine("Convert-image command", "Image without headers is {0} bytes.",
                                          inputFormat.Info.ImageSize);
                DicConsole.DebugWriteLine("Convert-image command", "Image has {0} sectors.", inputFormat.Info.Sectors);
                DicConsole.DebugWriteLine("Convert-image command", "Image identifies media type as {0}.",
                                          inputFormat.Info.MediaType);

                Statistics.AddMediaFormat(inputFormat.Format);
                Statistics.AddMedia(inputFormat.Info.MediaType, false);
                Statistics.AddFilter(inputFilter.Name);
            }
            catch (Exception ex)
            {
                DicConsole.ErrorWriteLine("Unable to open image format");
                DicConsole.ErrorWriteLine("Error: {0}", ex.Message);
                DicConsole.DebugWriteLine("Convert-image command", "Stack trace: {0}", ex.StackTrace);
                return((int)ErrorNumber.CannotOpenFormat);
            }

            List <IWritableImage> candidates = new List <IWritableImage>();

            // Try extension
            if (string.IsNullOrEmpty(wantedOutputFormat))
            {
                candidates.AddRange(plugins.WritableImages.Values.Where(t =>
                                                                        t.KnownExtensions
                                                                        .Contains(Path.GetExtension(outputFile))));
            }
            // Try Id
            else if (Guid.TryParse(wantedOutputFormat, out Guid outId))
            {
                candidates.AddRange(plugins.WritableImages.Values.Where(t => t.Id.Equals(outId)));
            }
            // Try name
            else
            {
                candidates.AddRange(plugins.WritableImages.Values.Where(t => string.Equals(t.Name, wantedOutputFormat,
                                                                                           StringComparison
                                                                                           .InvariantCultureIgnoreCase)));
            }

            if (candidates.Count == 0)
            {
                DicConsole.WriteLine("No plugin supports requested extension.");
                return((int)ErrorNumber.FormatNotFound);
            }

            if (candidates.Count > 1)
            {
                DicConsole.WriteLine("More than one plugin supports requested extension.");
                return((int)ErrorNumber.TooManyFormats);
            }

            IWritableImage outputFormat = candidates[0];

            if (MainClass.Verbose)
            {
                DicConsole.VerboseWriteLine("Output image format: {0} ({1}).", outputFormat.Name, outputFormat.Id);
            }
            else
            {
                DicConsole.WriteLine("Output image format: {0}.", outputFormat.Name);
            }

            if (!outputFormat.SupportedMediaTypes.Contains(inputFormat.Info.MediaType))
            {
                DicConsole.ErrorWriteLine("Output format does not support media type, cannot continue...");
                return((int)ErrorNumber.UnsupportedMedia);
            }

            foreach (MediaTagType mediaTag in inputFormat.Info.ReadableMediaTags)
            {
                if (outputFormat.SupportedMediaTags.Contains(mediaTag) || force)
                {
                    continue;
                }

                DicConsole.ErrorWriteLine("Converting image will lose media tag {0}, not continuing...", mediaTag);
                DicConsole.ErrorWriteLine("If you don't care, use force option.");
                return((int)ErrorNumber.DataWillBeLost);
            }

            bool useLong = inputFormat.Info.ReadableSectorTags.Count != 0;

            foreach (SectorTagType sectorTag in inputFormat.Info.ReadableSectorTags)
            {
                if (outputFormat.SupportedSectorTags.Contains(sectorTag))
                {
                    continue;
                }

                if (force)
                {
                    if (sectorTag != SectorTagType.CdTrackFlags && sectorTag != SectorTagType.CdTrackIsrc &&
                        sectorTag != SectorTagType.CdSectorSubchannel)
                    {
                        useLong = false;
                    }
                    continue;
                }

                DicConsole.ErrorWriteLine("Converting image will lose sector tag {0}, not continuing...", sectorTag);
                DicConsole
                .ErrorWriteLine("If you don't care, use force option. This will skip all sector tags converting only user data.");
                return((int)ErrorNumber.DataWillBeLost);
            }

            if (!outputFormat.Create(outputFile, inputFormat.Info.MediaType, parsedOptions, inputFormat.Info.Sectors,
                                     inputFormat.Info.SectorSize))
            {
                DicConsole.ErrorWriteLine("Error {0} creating output image.", outputFormat.ErrorMessage);
                return((int)ErrorNumber.CannotCreateFormat);
            }

            ImageInfo metadata = new ImageInfo
            {
                Application           = "DiscImageChef",
                ApplicationVersion    = Version.GetVersion(),
                Comments              = comments ?? inputFormat.Info.Comments,
                Creator               = creator ?? inputFormat.Info.Creator,
                DriveFirmwareRevision = driveFirmwareRevision ?? inputFormat.Info.DriveFirmwareRevision,
                DriveManufacturer     = driveManufacturer ?? inputFormat.Info.DriveManufacturer,
                DriveModel            = driveModel ?? inputFormat.Info.DriveModel,
                DriveSerialNumber     = driveSerialNumber ?? inputFormat.Info.DriveSerialNumber,
                LastMediaSequence     = lastMediaSequence != 0 ? lastMediaSequence : inputFormat.Info.LastMediaSequence,
                MediaBarcode          = mediaBarcode ?? inputFormat.Info.MediaBarcode,
                MediaManufacturer     = mediaManufacturer ?? inputFormat.Info.MediaManufacturer,
                MediaModel            = mediaModel ?? inputFormat.Info.MediaModel,
                MediaPartNumber       = mediaPartNumber ?? inputFormat.Info.MediaPartNumber,
                MediaSequence         = mediaSequence != 0 ? mediaSequence : inputFormat.Info.MediaSequence,
                MediaSerialNumber     = mediaSerialNumber ?? inputFormat.Info.MediaSerialNumber,
                MediaTitle            = mediaTitle ?? inputFormat.Info.MediaTitle
            };

            if (!outputFormat.SetMetadata(metadata))
            {
                DicConsole.ErrorWrite("Error {0} setting metadata, ", outputFormat.ErrorMessage);
                if (!force)
                {
                    DicConsole.ErrorWriteLine("not continuing...");
                    return((int)ErrorNumber.WriteError);
                }

                DicConsole.ErrorWriteLine("continuing...");
            }

            CICMMetadataType        cicmMetadata = inputFormat.CicmMetadata;
            List <DumpHardwareType> dumpHardware = inputFormat.DumpHardware;

            foreach (MediaTagType mediaTag in inputFormat.Info.ReadableMediaTags)
            {
                if (force && !outputFormat.SupportedMediaTags.Contains(mediaTag))
                {
                    continue;
                }

                DicConsole.WriteLine("Converting media tag {0}", mediaTag);
                byte[] tag = inputFormat.ReadDiskTag(mediaTag);
                if (outputFormat.WriteMediaTag(tag, mediaTag))
                {
                    continue;
                }

                if (force)
                {
                    DicConsole.ErrorWriteLine("Error {0} writing media tag, continuing...", outputFormat.ErrorMessage);
                }
                else
                {
                    DicConsole.ErrorWriteLine("Error {0} writing media tag, not continuing...",
                                              outputFormat.ErrorMessage);
                    return((int)ErrorNumber.WriteError);
                }
            }

            DicConsole.WriteLine("{0} sectors to convert", inputFormat.Info.Sectors);
            ulong doneSectors = 0;

            if (inputFormat is IOpticalMediaImage inputOptical && outputFormat is IWritableOpticalImage outputOptical &&
                inputOptical.Tracks != null)
            {
                if (!outputOptical.SetTracks(inputOptical.Tracks))
                {
                    DicConsole.ErrorWriteLine("Error {0} sending tracks list to output image.",
                                              outputFormat.ErrorMessage);
                    return((int)ErrorNumber.WriteError);
                }

                foreach (Track track in inputOptical.Tracks)
                {
                    doneSectors = 0;
                    ulong trackSectors = track.TrackEndSector - track.TrackStartSector + 1;

                    while (doneSectors < trackSectors)
                    {
                        byte[] sector;

                        uint sectorsToDo;
                        if (trackSectors - doneSectors >= (ulong)count)
                        {
                            sectorsToDo = (uint)count;
                        }
                        else
                        {
                            sectorsToDo = (uint)(trackSectors - doneSectors);
                        }

                        DicConsole.Write("\rConverting sectors {0} to {1} in track {3} ({2:P2} done)",
                                         doneSectors + track.TrackStartSector,
                                         doneSectors + sectorsToDo + track.TrackStartSector,
                                         (doneSectors + track.TrackStartSector) / (double)inputFormat.Info.Sectors,
                                         track.TrackSequence);

                        bool result;
                        if (useLong)
                        {
                            if (sectorsToDo == 1)
                            {
                                sector = inputFormat.ReadSectorLong(doneSectors + track.TrackStartSector);
                                result = outputFormat.WriteSectorLong(sector, doneSectors + track.TrackStartSector);
                            }
                            else
                            {
                                sector = inputFormat.ReadSectorsLong(doneSectors + track.TrackStartSector, sectorsToDo);
                                result = outputFormat.WriteSectorsLong(sector, doneSectors + track.TrackStartSector,
                                                                       sectorsToDo);
                            }
                        }
                        else
                        {
                            if (sectorsToDo == 1)
                            {
                                sector = inputFormat.ReadSector(doneSectors + track.TrackStartSector);
                                result = outputFormat.WriteSector(sector, doneSectors + track.TrackStartSector);
                            }
                            else
                            {
                                sector = inputFormat.ReadSectors(doneSectors + track.TrackStartSector, sectorsToDo);
                                result = outputFormat.WriteSectors(sector, doneSectors + track.TrackStartSector,
                                                                   sectorsToDo);
                            }
                        }

                        if (!result)
                        {
                            if (force)
                            {
                                DicConsole.ErrorWriteLine("Error {0} writing sector {1}, continuing...",
                                                          outputFormat.ErrorMessage, doneSectors);
                            }
                            else
                            {
                                DicConsole.ErrorWriteLine("Error {0} writing sector {1}, not continuing...",
                                                          outputFormat.ErrorMessage, doneSectors);
                                return((int)ErrorNumber.WriteError);
                            }
                        }

                        doneSectors += sectorsToDo;
                    }
                }

                DicConsole.Write("\rConverting sectors {0} to {1} in track {3} ({2:P2} done)", inputFormat.Info.Sectors,
                                 inputFormat.Info.Sectors, 1.0, inputOptical.Tracks.Count);
                DicConsole.WriteLine();

                foreach (SectorTagType tag in inputFormat.Info.ReadableSectorTags.OrderBy(t => t))
                {
                    if (!useLong)
                    {
                        break;
                    }

                    switch (tag)
                    {
                    case SectorTagType.AppleSectorTag:
                    case SectorTagType.CdSectorSync:
                    case SectorTagType.CdSectorHeader:
                    case SectorTagType.CdSectorSubHeader:
                    case SectorTagType.CdSectorEdc:
                    case SectorTagType.CdSectorEccP:
                    case SectorTagType.CdSectorEccQ:
                    case SectorTagType.CdSectorEcc:
                        // This tags are inline in long sector
                        continue;
                    }

                    if (force && !outputFormat.SupportedSectorTags.Contains(tag))
                    {
                        continue;
                    }

                    foreach (Track track in inputOptical.Tracks)
                    {
                        doneSectors = 0;
                        ulong  trackSectors = track.TrackEndSector - track.TrackStartSector + 1;
                        byte[] sector;
                        bool   result;

                        switch (tag)
                        {
                        case SectorTagType.CdTrackFlags:
                        case SectorTagType.CdTrackIsrc:
                            DicConsole.Write("\rConverting tag {0} in track {1} ({2:P2} done).", tag,
                                             track.TrackSequence,
                                             track.TrackSequence / (double)inputOptical.Tracks.Count);
                            sector = inputFormat.ReadSectorTag(track.TrackStartSector, tag);
                            result = outputFormat.WriteSectorTag(sector, track.TrackStartSector, tag);
                            if (!result)
                            {
                                if (force)
                                {
                                    DicConsole.ErrorWriteLine("Error {0} writing tag, continuing...",
                                                              outputFormat.ErrorMessage);
                                }
                                else
                                {
                                    DicConsole.ErrorWriteLine("Error {0} writing tag, not continuing...",
                                                              outputFormat.ErrorMessage);
                                    return((int)ErrorNumber.WriteError);
                                }
                            }

                            continue;
                        }

                        while (doneSectors < trackSectors)
                        {
                            uint sectorsToDo;
                            if (trackSectors - doneSectors >= (ulong)count)
                            {
                                sectorsToDo = (uint)count;
                            }
                            else
                            {
                                sectorsToDo =
                                    (uint)(trackSectors - doneSectors);
                            }

                            DicConsole.Write("\rConverting tag {4} for sectors {0} to {1} in track {3} ({2:P2} done)",
                                             doneSectors + track.TrackStartSector,
                                             doneSectors + sectorsToDo + track.TrackStartSector,
                                             (doneSectors + track.TrackStartSector) / (double)inputFormat.Info.Sectors,
                                             track.TrackSequence, tag);

                            if (sectorsToDo == 1)
                            {
                                sector = inputFormat.ReadSectorTag(doneSectors + track.TrackStartSector, tag);
                                result = outputFormat.WriteSectorTag(sector, doneSectors + track.TrackStartSector, tag);
                            }
                            else
                            {
                                sector = inputFormat.ReadSectorsTag(doneSectors + track.TrackStartSector, sectorsToDo,
                                                                    tag);
                                result = outputFormat.WriteSectorsTag(sector, doneSectors + track.TrackStartSector,
                                                                      sectorsToDo, tag);
                            }

                            if (!result)
                            {
                                if (force)
                                {
                                    DicConsole.ErrorWriteLine("Error {0} writing tag for sector {1}, continuing...",
                                                              outputFormat.ErrorMessage, doneSectors);
                                }
                                else
                                {
                                    DicConsole.ErrorWriteLine("Error {0} writing tag for sector {1}, not continuing...",
                                                              outputFormat.ErrorMessage, doneSectors);
                                    return((int)ErrorNumber.WriteError);
                                }
                            }

                            doneSectors += sectorsToDo;
                        }
                    }

                    switch (tag)
                    {
                    case SectorTagType.CdTrackFlags:
                    case SectorTagType.CdTrackIsrc:
                        DicConsole.Write("\rConverting tag {0} in track {1} ({2:P2} done).", tag,
                                         inputOptical.Tracks.Count, 1.0);
                        break;

                    default:
                        DicConsole.Write("\rConverting tag {4} for sectors {0} to {1} in track {3} ({2:P2} done)",
                                         inputFormat.Info.Sectors, inputFormat.Info.Sectors, 1.0,
                                         inputOptical.Tracks.Count, tag);
                        break;
                    }

                    DicConsole.WriteLine();
                }
            }
예제 #6
0
        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("decode");

            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("Decode command", "--debug={0}", MainClass.Debug);
            DicConsole.DebugWriteLine("Decode command", "--disk-tags={0}", diskTags);
            DicConsole.DebugWriteLine("Decode command", "--input={0}", inputFile);
            DicConsole.DebugWriteLine("Decode command", "--length={0}", length);
            DicConsole.DebugWriteLine("Decode command", "--sector-tags={0}", sectorTags);
            DicConsole.DebugWriteLine("Decode command", "--start={0}", startSector);
            DicConsole.DebugWriteLine("Decode command", "--verbose={0}", MainClass.Verbose);

            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 decoding");
                return((int)ErrorNumber.UnrecognizedFormat);
            }

            inputFormat.Open(inputFilter);
            Statistics.AddMediaFormat(inputFormat.Format);
            Statistics.AddMedia(inputFormat.Info.MediaType, false);
            Statistics.AddFilter(inputFilter.Name);

            if (diskTags)
            {
                if (inputFormat.Info.ReadableMediaTags.Count == 0)
                {
                    DicConsole.WriteLine("There are no disk tags in chosen disc image.");
                }
                else
                {
                    foreach (MediaTagType tag in inputFormat.Info.ReadableMediaTags)
                    {
                        switch (tag)
                        {
                        case MediaTagType.SCSI_INQUIRY:
                        {
                            byte[] inquiry = inputFormat.ReadDiskTag(MediaTagType.SCSI_INQUIRY);
                            if (inquiry == null)
                            {
                                DicConsole.WriteLine("Error reading SCSI INQUIRY response from disc image");
                            }
                            else
                            {
                                DicConsole.WriteLine("SCSI INQUIRY command response:");
                                DicConsole
                                .WriteLine("================================================================================");
                                DicConsole.WriteLine(Inquiry.Prettify(inquiry));
                                DicConsole
                                .WriteLine("================================================================================");
                            }

                            break;
                        }

                        case MediaTagType.ATA_IDENTIFY:
                        {
                            byte[] identify = inputFormat.ReadDiskTag(MediaTagType.ATA_IDENTIFY);
                            if (identify == null)
                            {
                                DicConsole.WriteLine("Error reading ATA IDENTIFY DEVICE response from disc image");
                            }
                            else
                            {
                                DicConsole.WriteLine("ATA IDENTIFY DEVICE command response:");
                                DicConsole
                                .WriteLine("================================================================================");
                                DicConsole.WriteLine(Identify.Prettify(identify));
                                DicConsole
                                .WriteLine("================================================================================");
                            }

                            break;
                        }

                        case MediaTagType.ATAPI_IDENTIFY:
                        {
                            byte[] identify = inputFormat.ReadDiskTag(MediaTagType.ATAPI_IDENTIFY);
                            if (identify == null)
                            {
                                DicConsole
                                .WriteLine("Error reading ATA IDENTIFY PACKET DEVICE response from disc image");
                            }
                            else
                            {
                                DicConsole.WriteLine("ATA IDENTIFY PACKET DEVICE command response:");
                                DicConsole
                                .WriteLine("================================================================================");
                                DicConsole.WriteLine(Identify.Prettify(identify));
                                DicConsole
                                .WriteLine("================================================================================");
                            }

                            break;
                        }

                        case MediaTagType.CD_ATIP:
                        {
                            byte[] atip = inputFormat.ReadDiskTag(MediaTagType.CD_ATIP);
                            if (atip == null)
                            {
                                DicConsole.WriteLine("Error reading CD ATIP from disc image");
                            }
                            else
                            {
                                DicConsole.WriteLine("CD ATIP:");
                                DicConsole
                                .WriteLine("================================================================================");
                                DicConsole.WriteLine(ATIP.Prettify(atip));
                                DicConsole
                                .WriteLine("================================================================================");
                            }

                            break;
                        }

                        case MediaTagType.CD_FullTOC:
                        {
                            byte[] fulltoc = inputFormat.ReadDiskTag(MediaTagType.CD_FullTOC);
                            if (fulltoc == null)
                            {
                                DicConsole.WriteLine("Error reading CD full TOC from disc image");
                            }
                            else
                            {
                                DicConsole.WriteLine("CD full TOC:");
                                DicConsole
                                .WriteLine("================================================================================");
                                DicConsole.WriteLine(FullTOC.Prettify(fulltoc));
                                DicConsole
                                .WriteLine("================================================================================");
                            }

                            break;
                        }

                        case MediaTagType.CD_PMA:
                        {
                            byte[] pma = inputFormat.ReadDiskTag(MediaTagType.CD_PMA);
                            if (pma == null)
                            {
                                DicConsole.WriteLine("Error reading CD PMA from disc image");
                            }
                            else
                            {
                                DicConsole.WriteLine("CD PMA:");
                                DicConsole
                                .WriteLine("================================================================================");
                                DicConsole.WriteLine(PMA.Prettify(pma));
                                DicConsole
                                .WriteLine("================================================================================");
                            }

                            break;
                        }

                        case MediaTagType.CD_SessionInfo:
                        {
                            byte[] sessioninfo = inputFormat.ReadDiskTag(MediaTagType.CD_SessionInfo);
                            if (sessioninfo == null)
                            {
                                DicConsole.WriteLine("Error reading CD session information from disc image");
                            }
                            else
                            {
                                DicConsole.WriteLine("CD session information:");
                                DicConsole
                                .WriteLine("================================================================================");
                                DicConsole.WriteLine(Session.Prettify(sessioninfo));
                                DicConsole
                                .WriteLine("================================================================================");
                            }

                            break;
                        }

                        case MediaTagType.CD_TEXT:
                        {
                            byte[] cdtext = inputFormat.ReadDiskTag(MediaTagType.CD_TEXT);
                            if (cdtext == null)
                            {
                                DicConsole.WriteLine("Error reading CD-TEXT from disc image");
                            }
                            else
                            {
                                DicConsole.WriteLine("CD-TEXT:");
                                DicConsole
                                .WriteLine("================================================================================");
                                DicConsole.WriteLine(CDTextOnLeadIn.Prettify(cdtext));
                                DicConsole
                                .WriteLine("================================================================================");
                            }

                            break;
                        }

                        case MediaTagType.CD_TOC:
                        {
                            byte[] toc = inputFormat.ReadDiskTag(MediaTagType.CD_TOC);
                            if (toc == null)
                            {
                                DicConsole.WriteLine("Error reading CD TOC from disc image");
                            }
                            else
                            {
                                DicConsole.WriteLine("CD TOC:");
                                DicConsole
                                .WriteLine("================================================================================");
                                DicConsole.WriteLine(TOC.Prettify(toc));
                                DicConsole
                                .WriteLine("================================================================================");
                            }

                            break;
                        }

                        default:
                            DicConsole.WriteLine("Decoder for disk tag type \"{0}\" not yet implemented, sorry.",
                                                 tag);
                            break;
                        }
                    }
                }
            }

            if (sectorTags)
            {
                if (length.ToLowerInvariant() == "all")
                {
                }
                else
                {
                    if (!ulong.TryParse(length, out ulong _))
                    {
                        DicConsole.WriteLine("Value \"{0}\" is not a valid number for length.", length);
                        DicConsole.WriteLine("Not decoding sectors tags");
                        return(3);
                    }
                }

                if (inputFormat.Info.ReadableSectorTags.Count == 0)
                {
                    DicConsole.WriteLine("There are no sector tags in chosen disc image.");
                }
                else
                {
                    foreach (SectorTagType tag in inputFormat.Info.ReadableSectorTags)
                    {
                        switch (tag)
                        {
                        default:
                            DicConsole.WriteLine("Decoder for disk tag type \"{0}\" not yet implemented, sorry.",
                                                 tag);
                            break;
                        }
                    }
                }

                // TODO: Not implemented
            }

            return((int)ErrorNumber.NoError);
        }
예제 #7
0
        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("image-info");

            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("Analyze command", "--debug={0}", MainClass.Debug);
            DicConsole.DebugWriteLine("Analyze command", "--input={0}", inputFile);
            DicConsole.DebugWriteLine("Analyze command", "--verbose={0}", MainClass.Verbose);

            FiltersList filtersList = new FiltersList();
            IFilter     inputFilter = filtersList.GetFilter(inputFile);

            if (inputFilter == null)
            {
                DicConsole.ErrorWriteLine("Cannot open specified file.");
                return((int)ErrorNumber.CannotOpenFile);
            }

            try
            {
                IMediaImage imageFormat = ImageFormat.Detect(inputFilter);

                if (imageFormat == null)
                {
                    DicConsole.WriteLine("Image format not identified.");
                    return((int)ErrorNumber.UnrecognizedFormat);
                }

                DicConsole.WriteLine("Image format identified by {0} ({1}).", imageFormat.Name, imageFormat.Id);
                DicConsole.WriteLine();

                try
                {
                    if (!imageFormat.Open(inputFilter))
                    {
                        DicConsole.WriteLine("Unable to open image format");
                        DicConsole.WriteLine("No error given");
                        return((int)ErrorNumber.CannotOpenFormat);
                    }

                    ImageInfo.PrintImageInfo(imageFormat);

                    Statistics.AddMediaFormat(imageFormat.Format);
                    Statistics.AddMedia(imageFormat.Info.MediaType, false);
                    Statistics.AddFilter(inputFilter.Name);
                }
                catch (Exception ex)
                {
                    DicConsole.ErrorWriteLine("Unable to open image format");
                    DicConsole.ErrorWriteLine("Error: {0}", ex.Message);
                    DicConsole.DebugWriteLine("Image-info command", "Stack trace: {0}", ex.StackTrace);
                    return((int)ErrorNumber.CannotOpenFormat);
                }
            }
            catch (Exception ex)
            {
                DicConsole.ErrorWriteLine($"Error reading file: {ex.Message}");
                DicConsole.DebugWriteLine("Image-info command", ex.StackTrace);
                return((int)ErrorNumber.UnexpectedException);
            }

            return((int)ErrorNumber.NoError);
        }
예제 #8
0
        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("create-sidecar");

            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("Create sidecar command", "--block-size={0}", blockSize);
            DicConsole.DebugWriteLine("Create sidecar command", "--debug={0}", MainClass.Debug);
            DicConsole.DebugWriteLine("Create sidecar command", "--encoding={0}", encodingName);
            DicConsole.DebugWriteLine("Create sidecar command", "--input={0}", inputFile);
            DicConsole.DebugWriteLine("Create sidecar command", "--tape={0}", tape);
            DicConsole.DebugWriteLine("Create sidecar command", "--verbose={0}", MainClass.Verbose);

            Encoding encoding = null;

            if (encodingName != null)
            {
                try
                {
                    encoding = Claunia.Encoding.Encoding.GetEncoding(encodingName);
                    if (MainClass.Verbose)
                    {
                        DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName);
                    }
                }
                catch (ArgumentException)
                {
                    DicConsole.ErrorWriteLine("Specified encoding is not supported.");
                    return((int)ErrorNumber.EncodingUnknown);
                }
            }

            if (File.Exists(inputFile))
            {
                if (tape)
                {
                    DicConsole.ErrorWriteLine("You cannot use --tape option when input is a file.");
                    return((int)ErrorNumber.ExpectedDirectory);
                }

                FiltersList filtersList = new FiltersList();
                IFilter     inputFilter = filtersList.GetFilter(inputFile);

                if (inputFilter == null)
                {
                    DicConsole.ErrorWriteLine("Cannot open specified file.");
                    return((int)ErrorNumber.CannotOpenFile);
                }

                try
                {
                    IMediaImage imageFormat = ImageFormat.Detect(inputFilter);

                    if (imageFormat == null)
                    {
                        DicConsole.WriteLine("Image format not identified, not proceeding with analysis.");
                        return((int)ErrorNumber.UnrecognizedFormat);
                    }

                    if (MainClass.Verbose)
                    {
                        DicConsole.VerboseWriteLine("Image format identified by {0} ({1}).", imageFormat.Name,
                                                    imageFormat.Id);
                    }
                    else
                    {
                        DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name);
                    }

                    try
                    {
                        if (!imageFormat.Open(inputFilter))
                        {
                            DicConsole.WriteLine("Unable to open image format");
                            DicConsole.WriteLine("No error given");
                            return((int)ErrorNumber.CannotOpenFormat);
                        }

                        DicConsole.DebugWriteLine("Analyze command", "Correctly opened image file.");
                    }
                    catch (Exception ex)
                    {
                        DicConsole.ErrorWriteLine("Unable to open image format");
                        DicConsole.ErrorWriteLine("Error: {0}", ex.Message);
                        return((int)ErrorNumber.CannotOpenFormat);
                    }

                    Statistics.AddMediaFormat(imageFormat.Format);
                    Statistics.AddFilter(inputFilter.Name);

                    Sidecar sidecarClass = new Sidecar(imageFormat, inputFile, inputFilter.Id, encoding);
                    sidecarClass.InitProgressEvent    += Progress.InitProgress;
                    sidecarClass.UpdateProgressEvent  += Progress.UpdateProgress;
                    sidecarClass.EndProgressEvent     += Progress.EndProgress;
                    sidecarClass.InitProgressEvent2   += Progress.InitProgress2;
                    sidecarClass.UpdateProgressEvent2 += Progress.UpdateProgress2;
                    sidecarClass.EndProgressEvent2    += Progress.EndProgress2;
                    sidecarClass.UpdateStatusEvent    += Progress.UpdateStatus;
                    System.Console.CancelKeyPress     += (sender, e) =>
                    {
                        e.Cancel = true;
                        sidecarClass.Abort();
                    };
                    CICMMetadataType sidecar = sidecarClass.Create();

                    DicConsole.WriteLine("Writing metadata sidecar");

                    FileStream xmlFs =
                        new
                        FileStream(Path.Combine(Path.GetDirectoryName(inputFile) ?? throw new InvalidOperationException(), Path.GetFileNameWithoutExtension(inputFile) + ".cicm.xml"),
                                   FileMode.CreateNew);

                    XmlSerializer xmlSer = new XmlSerializer(typeof(CICMMetadataType));
                    xmlSer.Serialize(xmlFs, sidecar);
                    xmlFs.Close();
                }
                catch (Exception ex)
                {
                    DicConsole.ErrorWriteLine($"Error reading file: {ex.Message}");
                    DicConsole.DebugWriteLine("Analyze command", ex.StackTrace);
                    return((int)ErrorNumber.UnexpectedException);
                }
            }
            else if (Directory.Exists(inputFile))
            {
                if (!tape)
                {
                    DicConsole.ErrorWriteLine("Cannot create a sidecar from a directory.");
                    return((int)ErrorNumber.ExpectedFile);
                }

                string[]      contents = Directory.GetFiles(inputFile, "*", SearchOption.TopDirectoryOnly);
                List <string> files    = contents.Where(file => new FileInfo(file).Length % blockSize == 0).ToList();

                files.Sort(StringComparer.CurrentCultureIgnoreCase);

                Sidecar sidecarClass = new Sidecar();
                sidecarClass.InitProgressEvent    += Progress.InitProgress;
                sidecarClass.UpdateProgressEvent  += Progress.UpdateProgress;
                sidecarClass.EndProgressEvent     += Progress.EndProgress;
                sidecarClass.InitProgressEvent2   += Progress.InitProgress2;
                sidecarClass.UpdateProgressEvent2 += Progress.UpdateProgress2;
                sidecarClass.EndProgressEvent2    += Progress.EndProgress2;
                sidecarClass.UpdateStatusEvent    += Progress.UpdateStatus;
                CICMMetadataType sidecar = sidecarClass.BlockTape(Path.GetFileName(inputFile), files, blockSize);

                DicConsole.WriteLine("Writing metadata sidecar");

                FileStream xmlFs =
                    new
                    FileStream(Path.Combine(Path.GetDirectoryName(inputFile) ?? throw new InvalidOperationException(), Path.GetFileNameWithoutExtension(inputFile) + ".cicm.xml"),
                               FileMode.CreateNew);

                XmlSerializer xmlSer = new XmlSerializer(typeof(CICMMetadataType));
                xmlSer.Serialize(xmlFs, sidecar);
                xmlFs.Close();
            }
            else
            {
                DicConsole.ErrorWriteLine("The specified input file cannot be found.");
            }

            return((int)ErrorNumber.NoError);
        }
예제 #9
0
        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", "--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 (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);
        }
예제 #10
0
        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);
        }