protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            try
            {
                inputFormat.ReadSectorLong(0);
                chkLongSector.Checked = true;
            }
            catch { chkLongSector.Visible = false; }

            lblSectors.Text = $"of {inputFormat.Info.Sectors}";
            nmuSector.Value = 0;
            OnNmuSectorValueChanged(nmuSector, e);
        }
Пример #2
0
        internal static void DoPrintHex(PrintHexOptions options)
        {
            DicConsole.DebugWriteLine("PrintHex command", "--debug={0}", options.Debug);
            DicConsole.DebugWriteLine("PrintHex command", "--verbose={0}", options.Verbose);
            DicConsole.DebugWriteLine("PrintHex command", "--input={0}", options.InputFile);
            DicConsole.DebugWriteLine("PrintHex command", "--start={0}", options.StartSector);
            DicConsole.DebugWriteLine("PrintHex command", "--length={0}", options.Length);
            DicConsole.DebugWriteLine("PrintHex command", "--long-sectors={0}", options.LongSectors);
            DicConsole.DebugWriteLine("PrintHex command", "--WidthBytes={0}", options.WidthBytes);

            FiltersList filtersList = new FiltersList();
            IFilter     inputFilter = filtersList.GetFilter(options.InputFile);

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

            IMediaImage inputFormat = ImageFormat.Detect(inputFilter);

            if (inputFormat == null)
            {
                DicConsole.ErrorWriteLine("Unable to recognize image format, not verifying");
                return;
            }

            inputFormat.Open(inputFilter);

            for (ulong i = 0; i < options.Length; i++)
            {
                DicConsole.WriteLine("Sector {0}", options.StartSector + i);

                if (inputFormat.Info.ReadableSectorTags == null)
                {
                    DicConsole
                    .WriteLine("Requested sectors with tags, unsupported by underlying image format, printing only user data.");
                    options.LongSectors = false;
                }
                else
                {
                    if (inputFormat.Info.ReadableSectorTags.Count == 0)
                    {
                        DicConsole
                        .WriteLine("Requested sectors with tags, unsupported by underlying image format, printing only user data.");
                        options.LongSectors = false;
                    }
                }

                byte[] sector = options.LongSectors
                                    ? inputFormat.ReadSectorLong(options.StartSector + i)
                                    : inputFormat.ReadSector(options.StartSector + i);

                DiscImageChef.PrintHex.PrintHexArray(sector, options.WidthBytes);
            }

            Core.Statistics.AddCommand("print-hex");
        }
Пример #3
0
        public ViewSectorViewModel([NotNull] IMediaImage inputFormat)
        {
            _inputFormat = inputFormat;

            try
            {
                inputFormat.ReadSectorLong(0);
                LongSectorChecked = true;
            }
            catch
            {
                LongSectorVisible = false;
            }

            TotalSectorsText = $"of {inputFormat.Info.Sectors}";
            SectorNumber     = 0;
        }
Пример #4
0
        public static void DoConvert(ConvertImageOptions options)
        {
            DicConsole.DebugWriteLine("Analyze command", "--debug={0}", options.Debug);
            DicConsole.DebugWriteLine("Analyze command", "--verbose={0}", options.Verbose);
            DicConsole.DebugWriteLine("Analyze command", "--input={0}", options.InputFile);
            DicConsole.DebugWriteLine("Analyze command", "--output={0}", options.OutputFile);
            DicConsole.DebugWriteLine("Analyze command", "--format={0}", options.OutputFormat);
            DicConsole.DebugWriteLine("Analyze command", "--count={0}", options.Count);
            DicConsole.DebugWriteLine("Analyze command", "--force={0}", options.Force);
            DicConsole.DebugWriteLine("Analyze command", "--creator={0}", options.Creator);
            DicConsole.DebugWriteLine("Analyze command", "--media-title={0}", options.MediaTitle);
            DicConsole.DebugWriteLine("Analyze command", "--comments={0}", options.Comments);
            DicConsole.DebugWriteLine("Analyze command", "--media-manufacturer={0}", options.MediaManufacturer);
            DicConsole.DebugWriteLine("Analyze command", "--media-model={0}", options.MediaModel);
            DicConsole.DebugWriteLine("Analyze command", "--media-serial={0}", options.MediaSerialNumber);
            DicConsole.DebugWriteLine("Analyze command", "--media-barcode={0}", options.MediaBarcode);
            DicConsole.DebugWriteLine("Analyze command", "--media-partnumber={0}", options.MediaPartNumber);
            DicConsole.DebugWriteLine("Analyze command", "--media-sequence={0}", options.MediaSequence);
            DicConsole.DebugWriteLine("Analyze command", "--media-lastsequence={0}", options.LastMediaSequence);
            DicConsole.DebugWriteLine("Analyze command", "--drive-manufacturer={0}", options.DriveManufacturer);
            DicConsole.DebugWriteLine("Analyze command", "--drive-model={0}", options.DriveModel);
            DicConsole.DebugWriteLine("Analyze command", "--drive-serial={0}", options.DriveSerialNumber);
            DicConsole.DebugWriteLine("Analyze command", "--drive-revision={0}", options.DriveFirmwareRevision);
            DicConsole.DebugWriteLine("Analyze command", "--cicm-xml={0}", options.CicmXml);
            DicConsole.DebugWriteLine("Analyze command", "--resume-file={0}", options.ResumeFile);
            DicConsole.DebugWriteLine("Analyze command", "--options={0}", options.Options);

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

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

            if (options.Count == 0)
            {
                DicConsole.ErrorWriteLine("Need to specify more than 0 sectors to copy at once");
                return;
            }

            Resume           resume  = null;
            CICMMetadataType sidecar = null;

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

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

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

            FiltersList filtersList = new FiltersList();
            IFilter     inputFilter = filtersList.GetFilter(options.InputFile);

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

            if (File.Exists(options.OutputFile))
            {
                DicConsole.ErrorWriteLine("Output file already exists, not continuing.");
                return;
            }

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

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

            if (options.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;
                }

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

                Core.Statistics.AddMediaFormat(inputFormat.Format);
                Core.Statistics.AddMedia(inputFormat.Info.MediaType, false);
                Core.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;
            }

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

            // Try extension
            if (string.IsNullOrEmpty(options.OutputFormat))
            {
                candidates.AddRange(plugins.WritableImages.Values.Where(t =>
                                                                        t.KnownExtensions
                                                                        .Contains(Path.GetExtension(options
                                                                                                    .OutputFile))));
            }
            // Try Id
            else if (Guid.TryParse(options.OutputFormat, 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, options.OutputFormat,
                                                                                           StringComparison
                                                                                           .InvariantCultureIgnoreCase)));
            }

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

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

            IWritableImage outputFormat = candidates[0];

            if (options.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;
            }

            foreach (MediaTagType mediaTag in inputFormat.Info.ReadableMediaTags)
            {
                if (outputFormat.SupportedMediaTags.Contains(mediaTag) || options.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;
            }

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

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

                if (options.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;
            }

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

            CommonTypes.Structs.ImageInfo metadata = new CommonTypes.Structs.ImageInfo
            {
                Application           = "DiscImageChef",
                ApplicationVersion    = Version.GetVersion(),
                Comments              = options.Comments ?? inputFormat.Info.Comments,
                Creator               = options.Creator ?? inputFormat.Info.Creator,
                DriveFirmwareRevision = options.DriveFirmwareRevision ?? inputFormat.Info.DriveFirmwareRevision,
                DriveManufacturer     = options.DriveManufacturer ?? inputFormat.Info.DriveManufacturer,
                DriveModel            = options.DriveModel ?? inputFormat.Info.DriveModel,
                DriveSerialNumber     = options.DriveSerialNumber ?? inputFormat.Info.DriveSerialNumber,
                LastMediaSequence     =
                    options.LastMediaSequence != 0 ? options.LastMediaSequence : inputFormat.Info.LastMediaSequence,
                MediaBarcode      = options.MediaBarcode ?? inputFormat.Info.MediaBarcode,
                MediaManufacturer = options.MediaManufacturer ?? inputFormat.Info.MediaManufacturer,
                MediaModel        = options.MediaModel ?? inputFormat.Info.MediaModel,
                MediaPartNumber   = options.MediaPartNumber ?? inputFormat.Info.MediaPartNumber,
                MediaSequence     = options.MediaSequence != 0 ? options.MediaSequence : inputFormat.Info.MediaSequence,
                MediaSerialNumber = options.MediaSerialNumber ?? inputFormat.Info.MediaSerialNumber,
                MediaTitle        = options.MediaTitle ?? inputFormat.Info.MediaTitle
            };

            if (!outputFormat.SetMetadata(metadata))
            {
                DicConsole.ErrorWrite("Error {0} setting metadata, ", outputFormat.ErrorMessage);
                if (!options.Force)
                {
                    DicConsole.ErrorWriteLine("not continuing...");
                    return;
                }

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

            List <Track> tracks;

            try { tracks = inputFormat.Tracks; }
            catch (Exception) { tracks = null; }

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

            if (tracks != null)
            {
                if (!outputFormat.SetTracks(tracks))
                {
                    DicConsole.ErrorWriteLine("Error {0} sending tracks list to output image.",
                                              outputFormat.ErrorMessage);
                    return;
                }
            }

            foreach (MediaTagType mediaTag in inputFormat.Info.ReadableMediaTags)
            {
                if (options.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 (options.Force)
                {
                    DicConsole.ErrorWriteLine("Error {0} writing media tag, continuing...", outputFormat.ErrorMessage);
                }
                else
                {
                    DicConsole.ErrorWriteLine("Error {0} writing media tag, not continuing...",
                                              outputFormat.ErrorMessage);
                    return;
                }
            }

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

            if (tracks == null)
            {
                DicConsole.WriteLine("Setting geometry to {0} cylinders, {1} heads and {2} sectors per track",
                                     inputFormat.Info.Cylinders, inputFormat.Info.Heads,
                                     inputFormat.Info.SectorsPerTrack);
                if (!outputFormat.SetGeometry(inputFormat.Info.Cylinders, inputFormat.Info.Heads,
                                              inputFormat.Info.SectorsPerTrack))
                {
                    DicConsole.ErrorWriteLine("Error {0} setting geometry, image may be incorrect, continuing...",
                                              outputFormat.ErrorMessage);
                }

                while (doneSectors < inputFormat.Info.Sectors)
                {
                    byte[] sector;

                    uint sectorsToDo;
                    if (inputFormat.Info.Sectors - doneSectors >= (ulong)options.Count)
                    {
                        sectorsToDo = (uint)options.Count;
                    }
                    else
                    {
                        sectorsToDo = (uint)(inputFormat.Info.Sectors - doneSectors);
                    }

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

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

                    if (!result)
                    {
                        if (options.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;
                        }
                    }

                    doneSectors += sectorsToDo;
                }

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

                foreach (SectorTagType tag in inputFormat.Info.ReadableSectorTags)
                {
                    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 (options.Force && !outputFormat.SupportedSectorTags.Contains(tag))
                    {
                        continue;
                    }

                    doneSectors = 0;
                    while (doneSectors < inputFormat.Info.Sectors)
                    {
                        byte[] sector;

                        uint sectorsToDo;
                        if (inputFormat.Info.Sectors - doneSectors >= (ulong)options.Count)
                        {
                            sectorsToDo = (uint)options.Count;
                        }
                        else
                        {
                            sectorsToDo = (uint)(inputFormat.Info.Sectors - doneSectors);
                        }

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

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

                        if (!result)
                        {
                            if (options.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;
                            }
                        }

                        doneSectors += sectorsToDo;
                    }

                    DicConsole.Write("\rConverting tag {2} for sectors {0} to {1} ({2:P2} done)",
                                     inputFormat.Info.Sectors, inputFormat.Info.Sectors, 1.0, tag);
                    DicConsole.WriteLine();
                }
            }
            else
            {
                foreach (Track track in tracks)
                {
                    doneSectors = 0;
                    ulong trackSectors = track.TrackEndSector - track.TrackStartSector + 1;

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

                        uint sectorsToDo;
                        if (trackSectors - doneSectors >= (ulong)options.Count)
                        {
                            sectorsToDo = (uint)options.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 (options.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;
                            }
                        }

                        doneSectors += sectorsToDo;
                    }
                }

                DicConsole.Write("\rConverting sectors {0} to {1} in track {3} ({2:P2} done)", inputFormat.Info.Sectors,
                                 inputFormat.Info.Sectors, 1.0, 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 (options.Force && !outputFormat.SupportedSectorTags.Contains(tag))
                    {
                        continue;
                    }

                    foreach (Track track in 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)tracks.Count);
                            sector = inputFormat.ReadSectorTag(track.TrackStartSector, tag);
                            result = outputFormat.WriteSectorTag(sector, track.TrackStartSector, tag);
                            if (!result)
                            {
                                if (options.Force)
                                {
                                    DicConsole.ErrorWriteLine("Error {0} writing tag, continuing...",
                                                              outputFormat.ErrorMessage);
                                }
                                else
                                {
                                    DicConsole.ErrorWriteLine("Error {0} writing tag, not continuing...",
                                                              outputFormat.ErrorMessage);
                                    return;
                                }
                            }

                            continue;
                        }

                        while (doneSectors < trackSectors)
                        {
                            uint sectorsToDo;
                            if (trackSectors - doneSectors >= (ulong)options.Count)
                            {
                                sectorsToDo = (uint)options.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 (options.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;
                                }
                            }

                            doneSectors += sectorsToDo;
                        }
                    }

                    switch (tag)
                    {
                    case SectorTagType.CdTrackFlags:
                    case SectorTagType.CdTrackIsrc:
                        DicConsole.Write("\rConverting tag {0} in track {1} ({2:P2} done).", tag, 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, tracks.Count,
                                         tag);
                        break;
                    }

                    DicConsole.WriteLine();
                }
            }

            bool ret = false;

            if (resume != null || dumpHardware != null)
            {
                if (resume != null)
                {
                    ret = outputFormat.SetDumpHardware(resume.Tries);
                }
                else if (dumpHardware != null)
                {
                    ret = outputFormat.SetDumpHardware(dumpHardware);
                }
                if (ret)
                {
                    DicConsole.WriteLine("Written dump hardware list to output image.");
                }
            }

            ret = false;
            if (sidecar != null || cicmMetadata != null)
            {
                if (sidecar != null)
                {
                    ret = outputFormat.SetCicmMetadata(sidecar);
                }
                else if (cicmMetadata != null)
                {
                    ret = outputFormat.SetCicmMetadata(cicmMetadata);
                }
                if (ret)
                {
                    DicConsole.WriteLine("Written CICM XML metadata to output image.");
                }
            }

            DicConsole.WriteLine("Closing output image.");

            if (!outputFormat.Close())
            {
                DicConsole.ErrorWriteLine("Error {0} closing output image... Contents are not correct.",
                                          outputFormat.ErrorMessage);
            }

            DicConsole.WriteLine();
            DicConsole.WriteLine("Conversion done.");

            Core.Statistics.AddCommand("convert-image");
        }
Пример #5
0
        public static int Invoke(bool debug, bool verbose, string imagePath, ulong length, bool longSectors,
                                 ulong start, ushort width)
        {
            MainClass.PrintCopyright();

            if (debug)
            {
                DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
            }

            if (verbose)
            {
                DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
            }

            Statistics.AddCommand("print-hex");

            DicConsole.DebugWriteLine("PrintHex command", "--debug={0}", debug);
            DicConsole.DebugWriteLine("PrintHex command", "--input={0}", imagePath);
            DicConsole.DebugWriteLine("PrintHex command", "--length={0}", length);
            DicConsole.DebugWriteLine("PrintHex command", "--long-sectors={0}", longSectors);
            DicConsole.DebugWriteLine("PrintHex command", "--start={0}", start);
            DicConsole.DebugWriteLine("PrintHex command", "--verbose={0}", verbose);
            DicConsole.DebugWriteLine("PrintHex command", "--width={0}", width);

            var     filtersList = new FiltersList();
            IFilter inputFilter = filtersList.GetFilter(imagePath);

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

            inputFormat.Open(inputFilter);

            for (ulong i = 0; i < length; i++)
            {
                DicConsole.WriteLine("Sector {0}", start + i);

                if (inputFormat.Info.ReadableSectorTags == null)
                {
                    DicConsole.
                    WriteLine("Requested sectors with tags, unsupported by underlying image format, printing only user data.");

                    longSectors = false;
                }
                else
                {
                    if (inputFormat.Info.ReadableSectorTags.Count == 0)
                    {
                        DicConsole.
                        WriteLine("Requested sectors with tags, unsupported by underlying image format, printing only user data.");

                        longSectors = false;
                    }
                }

                byte[] sector = longSectors ? inputFormat.ReadSectorLong(start + i)
                                    : inputFormat.ReadSector(start + i);

                PrintHex.PrintHexArray(sector, width);
            }

            return((int)ErrorNumber.NoError);
        }
Пример #6
0
        public static int Invoke(bool verbose, bool debug, string cicmXml, string comments, int count, string creator,
                                 string driveFirmwareRevision, string driveManufacturer, string driveModel,
                                 string driveSerialNumber, bool force, string inputPath, int lastMediaSequence,
                                 string mediaBarcode, string mediaManufacturer, string mediaModel,
                                 string mediaPartNumber, int mediaSequence, string mediaSerialNumber, string mediaTitle,
                                 string outputPath, string outputOptions, string resumeFile, string format)
        {
            MainClass.PrintCopyright();

            if (debug)
            {
                AaruConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
            }

            if (verbose)
            {
                AaruConsole.VerboseWriteLineEvent += System.Console.WriteLine;
            }

            Statistics.AddCommand("convert-image");

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

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

            AaruConsole.DebugWriteLine("Analyze command", "Parsed options:");

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

            if (count == 0)
            {
                AaruConsole.ErrorWriteLine("Need to specify more than 0 sectors to copy at once");

                return((int)ErrorNumber.InvalidArgument);
            }

            Resume           resume  = null;
            CICMMetadataType sidecar = null;
            MediaType        mediaType;

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

            if (cicmXml != null)
            {
                if (File.Exists(cicmXml))
                {
                    try
                    {
                        var sr = new StreamReader(cicmXml);
                        sidecar = (CICMMetadataType)xs.Deserialize(sr);
                        sr.Close();
                    }
                    catch (Exception ex)
                    {
                        AaruConsole.ErrorWriteLine("Incorrect metadata sidecar file, not continuing...");
                        AaruConsole.DebugWriteLine("Image conversion", $"{ex}");

                        return((int)ErrorNumber.InvalidSidecar);
                    }
                }
                else
                {
                    AaruConsole.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
                    {
                        var sr = new StreamReader(resumeFile);
                        resume = (Resume)xs.Deserialize(sr);
                        sr.Close();
                    }
                    catch (Exception ex)
                    {
                        AaruConsole.ErrorWriteLine("Incorrect resume file, not continuing...");
                        AaruConsole.DebugWriteLine("Image conversion", $"{ex}");

                        return((int)ErrorNumber.InvalidResume);
                    }
                }
                else
                {
                    AaruConsole.ErrorWriteLine("Could not find resume file, not continuing...");

                    return((int)ErrorNumber.FileNotFound);
                }
            }

            var     filtersList = new FiltersList();
            IFilter inputFilter = filtersList.GetFilter(inputPath);

            if (inputFilter == null)
            {
                AaruConsole.ErrorWriteLine("Cannot open specified file.");

                return((int)ErrorNumber.CannotOpenFile);
            }

            if (File.Exists(outputPath))
            {
                AaruConsole.ErrorWriteLine("Output file already exists, not continuing.");

                return((int)ErrorNumber.DestinationExists);
            }

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

            if (inputFormat == null)
            {
                AaruConsole.WriteLine("Input image format not identified, not proceeding with conversion.");

                return((int)ErrorNumber.UnrecognizedFormat);
            }

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

            try
            {
                if (!inputFormat.Open(inputFilter))
                {
                    AaruConsole.WriteLine("Unable to open image format");
                    AaruConsole.WriteLine("No error given");

                    return((int)ErrorNumber.CannotOpenFormat);
                }

                mediaType = inputFormat.Info.MediaType;

                // Obsolete types
                #pragma warning disable 612
                switch (mediaType)
                {
                case MediaType.SQ1500:
                    mediaType = MediaType.SyJet;

                    break;

                case MediaType.Bernoulli:
                    mediaType = MediaType.Bernoulli10;

                    break;

                case MediaType.Bernoulli2:
                    mediaType = MediaType.BernoulliBox2_20;

                    break;
                }
                #pragma warning restore 612

                AaruConsole.DebugWriteLine("Convert-image command", "Correctly opened image file.");

                AaruConsole.DebugWriteLine("Convert-image command", "Image without headers is {0} bytes.",
                                           inputFormat.Info.ImageSize);

                AaruConsole.DebugWriteLine("Convert-image command", "Image has {0} sectors.", inputFormat.Info.Sectors);

                AaruConsole.DebugWriteLine("Convert-image command", "Image identifies media type as {0}.", mediaType);

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

                return((int)ErrorNumber.CannotOpenFormat);
            }

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

            // Try extension
            if (string.IsNullOrEmpty(format))
            {
                candidates.AddRange(plugins.WritableImages.Values.Where(t =>
                                                                        t.KnownExtensions.
                                                                        Contains(Path.GetExtension(outputPath))));
            }

            // Try Id
            else if (Guid.TryParse(format, 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, format,
                                                                                           StringComparison.
                                                                                           InvariantCultureIgnoreCase)));
            }

            if (candidates.Count == 0)
            {
                AaruConsole.WriteLine("No plugin supports requested extension.");

                return((int)ErrorNumber.FormatNotFound);
            }

            if (candidates.Count > 1)
            {
                AaruConsole.WriteLine("More than one plugin supports requested extension.");

                return((int)ErrorNumber.TooManyFormats);
            }

            IWritableImage outputFormat = candidates[0];

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

            if (!outputFormat.SupportedMediaTypes.Contains(mediaType))
            {
                AaruConsole.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;
                }

                AaruConsole.ErrorWriteLine("Converting image will lose media tag {0}, not continuing...", mediaTag);
                AaruConsole.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;
                }

                AaruConsole.ErrorWriteLine("Converting image will lose sector tag {0}, not continuing...", sectorTag);

                AaruConsole.
                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(outputPath, mediaType, parsedOptions, inputFormat.Info.Sectors,
                                     inputFormat.Info.SectorSize))
            {
                AaruConsole.ErrorWriteLine("Error {0} creating output image.", outputFormat.ErrorMessage);

                return((int)ErrorNumber.CannotCreateFormat);
            }

            var metadata = new ImageInfo
            {
                Application           = "Aaru",
                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))
            {
                AaruConsole.ErrorWrite("Error {0} setting metadata, ", outputFormat.ErrorMessage);

                if (!force)
                {
                    AaruConsole.ErrorWriteLine("not continuing...");

                    return((int)ErrorNumber.WriteError);
                }

                AaruConsole.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;
                }

                AaruConsole.WriteLine("Converting media tag {0}", mediaTag);
                byte[] tag = inputFormat.ReadDiskTag(mediaTag);

                if (outputFormat.WriteMediaTag(tag, mediaTag))
                {
                    continue;
                }

                if (force)
                {
                    AaruConsole.ErrorWriteLine("Error {0} writing media tag, continuing...", outputFormat.ErrorMessage);
                }
                else
                {
                    AaruConsole.ErrorWriteLine("Error {0} writing media tag, not continuing...",
                                               outputFormat.ErrorMessage);

                    return((int)ErrorNumber.WriteError);
                }
            }

            AaruConsole.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))
                {
                    AaruConsole.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);
                        }

                        AaruConsole.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 useNotLong = false;
                        bool result     = false;

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

                            if (!result &&
                                sector.Length % 2352 != 0)
                            {
                                if (!force)
                                {
                                    AaruConsole.ErrorWriteLine("Input image is not returning raw sectors, use force if you want to continue...");

                                    return((int)Errno.InOutError);
                                }

                                useNotLong = true;
                            }
                        }

                        if (!useLong || useNotLong)
                        {
                            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)
                            {
                                AaruConsole.ErrorWriteLine("Error {0} writing sector {1}, continuing...",
                                                           outputFormat.ErrorMessage,
                                                           doneSectors + track.TrackStartSector);
                            }
                            else
                            {
                                AaruConsole.ErrorWriteLine("Error {0} writing sector {1}, not continuing...",
                                                           outputFormat.ErrorMessage,
                                                           doneSectors + track.TrackStartSector);

                                return((int)ErrorNumber.WriteError);
                            }
                        }

                        doneSectors += sectorsToDo;
                    }
                }

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

                AaruConsole.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:
                            AaruConsole.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)
                                {
                                    AaruConsole.ErrorWriteLine("Error {0} writing tag, continuing...",
                                                               outputFormat.ErrorMessage);
                                }
                                else
                                {
                                    AaruConsole.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);
                            }

                            AaruConsole.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)
                                {
                                    AaruConsole.ErrorWriteLine("Error {0} writing tag for sector {1}, continuing...",
                                                               outputFormat.ErrorMessage,
                                                               doneSectors + track.TrackStartSector);
                                }
                                else
                                {
                                    AaruConsole.
                                    ErrorWriteLine("Error {0} writing tag for sector {1}, not continuing...",
                                                   outputFormat.ErrorMessage, doneSectors + track.TrackStartSector);

                                    return((int)ErrorNumber.WriteError);
                                }
                            }

                            doneSectors += sectorsToDo;
                        }
                    }

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

                        break;

                    default:
                        AaruConsole.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;
                    }

                    AaruConsole.WriteLine();
                }
            }
Пример #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("print-hex");

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

            if (startSector is null)
            {
                DicConsole.ErrorWriteLine("Missing starting sector.");
                return((int)ErrorNumber.MissingArgument);
            }

            inputFile = extra[0];

            DicConsole.DebugWriteLine("PrintHex command", "--debug={0}", MainClass.Debug);
            DicConsole.DebugWriteLine("PrintHex command", "--input={0}", inputFile);
            DicConsole.DebugWriteLine("PrintHex command", "--length={0}", length);
            DicConsole.DebugWriteLine("PrintHex command", "--long-sectors={0}", longSectors);
            DicConsole.DebugWriteLine("PrintHex command", "--start={0}", startSector);
            DicConsole.DebugWriteLine("PrintHex command", "--verbose={0}", MainClass.Verbose);
            DicConsole.DebugWriteLine("PrintHex command", "--WidthBytes={0}", widthBytes);

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

            inputFormat.Open(inputFilter);

            for (ulong i = 0; i < length; i++)
            {
                DicConsole.WriteLine("Sector {0}", startSector + i);

                if (inputFormat.Info.ReadableSectorTags == null)
                {
                    DicConsole
                    .WriteLine("Requested sectors with tags, unsupported by underlying image format, printing only user data.");
                    longSectors = false;
                }
                else
                {
                    if (inputFormat.Info.ReadableSectorTags.Count == 0)
                    {
                        DicConsole
                        .WriteLine("Requested sectors with tags, unsupported by underlying image format, printing only user data.");
                        longSectors = false;
                    }
                }

                byte[] sector = longSectors
                                    ? inputFormat.ReadSectorLong(startSector.Value + i)
                                    : inputFormat.ReadSector(startSector.Value + i);

                PrintHex.PrintHexArray(sector, widthBytes);
            }

            return((int)ErrorNumber.NoError);
        }
        public void Convert()
        {
            Environment.CurrentDirectory = DataFolder;

            Resume           resume  = null;
            CICMMetadataType sidecar = null;

            var     filtersList = new FiltersList();
            IFilter inputFilter = filtersList.GetFilter(InputPath);

            Assert.IsNotNull(inputFilter, "Cannot open specified file.");

            string outputPath = Path.Combine(Path.GetTempPath(), SuggestedOutputFilename);

            Assert.IsFalse(File.Exists(outputPath), "Output file already exists, not continuing.");

            IMediaImage inputFormat = ImageFormat.Detect(inputFilter);

            Assert.IsNotNull(inputFormat, "Input image format not identified, not proceeding with conversion.");

            Assert.IsTrue(inputFormat.Open(inputFilter), "Unable to open image format");

            Assert.IsTrue(OutputFormat.SupportedMediaTypes.Contains(inputFormat.Info.MediaType),
                          "Output format does not support media type, cannot continue...");

            if (inputFormat.Info.ReadableSectorTags.Count == 0)
            {
                Assert.IsFalse(UseLong, "Input image does not support long sectors.");
            }

            var inputOptical  = inputFormat as IOpticalMediaImage;
            var outputOptical = OutputFormat as IWritableOpticalImage;

            Assert.IsNotNull(inputOptical, "Could not treat existing image as optical disc.");
            Assert.IsNotNull(outputOptical, "Could not treat new image as optical disc.");
            Assert.IsNotNull(inputOptical.Tracks, "Existing image contains no tracks.");

            Assert.IsTrue(outputOptical.Create(outputPath, inputFormat.Info.MediaType, ParsedOptions, inputFormat.Info.Sectors, inputFormat.Info.SectorSize),
                          $"Error {outputOptical.ErrorMessage} creating output image.");

            var metadata = new ImageInfo
            {
                Application           = "Aaru",
                ApplicationVersion    = Version.GetVersion(),
                Comments              = inputFormat.Info.Comments,
                Creator               = inputFormat.Info.Creator,
                DriveFirmwareRevision = inputFormat.Info.DriveFirmwareRevision,
                DriveManufacturer     = inputFormat.Info.DriveManufacturer,
                DriveModel            = inputFormat.Info.DriveModel,
                DriveSerialNumber     = inputFormat.Info.DriveSerialNumber,
                LastMediaSequence     = inputFormat.Info.LastMediaSequence,
                MediaBarcode          = inputFormat.Info.MediaBarcode,
                MediaManufacturer     = inputFormat.Info.MediaManufacturer,
                MediaModel            = inputFormat.Info.MediaModel,
                MediaPartNumber       = inputFormat.Info.MediaPartNumber,
                MediaSequence         = inputFormat.Info.MediaSequence,
                MediaSerialNumber     = inputFormat.Info.MediaSerialNumber,
                MediaTitle            = inputFormat.Info.MediaTitle
            };

            Assert.IsTrue(outputOptical.SetMetadata(metadata),
                          $"Error {outputOptical.ErrorMessage} setting metadata, ");

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

            foreach (MediaTagType mediaTag in inputFormat.Info.ReadableMediaTags.Where(mediaTag =>
                                                                                       outputOptical.SupportedMediaTags.Contains(mediaTag)))
            {
                AaruConsole.WriteLine("Converting media tag {0}", mediaTag);
                byte[] tag = inputFormat.ReadDiskTag(mediaTag);

                Assert.IsTrue(outputOptical.WriteMediaTag(tag, mediaTag));
            }

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

            Assert.IsTrue(outputOptical.SetTracks(inputOptical.Tracks),
                          $"Error {outputOptical.ErrorMessage} sending tracks list to output image.");

            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 >= SECTORS_TO_READ)
                    {
                        sectorsToDo = SECTORS_TO_READ;
                    }
                    else
                    {
                        sectorsToDo = (uint)(trackSectors - doneSectors);
                    }

                    bool useNotLong = false;
                    bool result     = false;

                    if (UseLong)
                    {
                        if (sectorsToDo == 1)
                        {
                            sector = inputFormat.ReadSectorLong(doneSectors + track.TrackStartSector);
                            result = outputOptical.WriteSectorLong(sector, doneSectors + track.TrackStartSector);
                        }
                        else
                        {
                            sector = inputFormat.ReadSectorsLong(doneSectors + track.TrackStartSector, sectorsToDo);

                            result = outputOptical.WriteSectorsLong(sector, doneSectors + track.TrackStartSector,
                                                                    sectorsToDo);
                        }

                        if (!result &&
                            sector.Length % 2352 != 0)
                        {
                            useNotLong = true;
                        }
                    }

                    if (!UseLong || useNotLong)
                    {
                        if (sectorsToDo == 1)
                        {
                            sector = inputFormat.ReadSector(doneSectors + track.TrackStartSector);
                            result = outputOptical.WriteSector(sector, doneSectors + track.TrackStartSector);
                        }
                        else
                        {
                            sector = inputFormat.ReadSectors(doneSectors + track.TrackStartSector, sectorsToDo);

                            result = outputOptical.WriteSectors(sector, doneSectors + track.TrackStartSector,
                                                                sectorsToDo);
                        }
                    }

                    Assert.IsTrue(result,
                                  $"Error {outputOptical.ErrorMessage} writing sector {doneSectors + track.TrackStartSector}, not continuing...");

                    doneSectors += sectorsToDo;
                }
            }

            Dictionary <byte, string> isrcs                  = new Dictionary <byte, string>();
            Dictionary <byte, byte>   trackFlags             = new Dictionary <byte, byte>();
            string                 mcn                       = null;
            HashSet <int>          subchannelExtents         = new HashSet <int>();
            Dictionary <byte, int> smallestPregapLbaPerTrack = new Dictionary <byte, int>();

            Track[] tracks = new Track[inputOptical.Tracks.Count];

            for (int i = 0; i < tracks.Length; i++)
            {
                tracks[i] = new Track
                {
                    Indexes                = new Dictionary <ushort, int>(),
                    TrackDescription       = inputOptical.Tracks[i].TrackDescription,
                    TrackEndSector         = inputOptical.Tracks[i].TrackEndSector,
                    TrackStartSector       = inputOptical.Tracks[i].TrackStartSector,
                    TrackPregap            = inputOptical.Tracks[i].TrackPregap,
                    TrackSequence          = inputOptical.Tracks[i].TrackSequence,
                    TrackSession           = inputOptical.Tracks[i].TrackSession,
                    TrackBytesPerSector    = inputOptical.Tracks[i].TrackBytesPerSector,
                    TrackRawBytesPerSector = inputOptical.Tracks[i].TrackRawBytesPerSector,
                    TrackType              = inputOptical.Tracks[i].TrackType,
                    TrackSubchannelType    = inputOptical.Tracks[i].TrackSubchannelType
                };

                foreach (KeyValuePair <ushort, int> idx in inputOptical.Tracks[i].Indexes)
                {
                    tracks[i].Indexes[idx.Key] = idx.Value;
                }
            }

            foreach (SectorTagType tag in inputFormat.Info.ReadableSectorTags.Where(t => t == SectorTagType.CdTrackIsrc).
                     OrderBy(t => t))
            {
                foreach (Track track in tracks)
                {
                    byte[] isrc = inputFormat.ReadSectorTag(track.TrackSequence, tag);

                    if (isrc is null)
                    {
                        continue;
                    }

                    isrcs[(byte)track.TrackSequence] = Encoding.UTF8.GetString(isrc);
                }
            }

            foreach (SectorTagType tag in inputFormat.Info.ReadableSectorTags.
                     Where(t => t == SectorTagType.CdTrackFlags).OrderBy(t => t))
            {
                foreach (Track track in tracks)
                {
                    byte[] flags = inputFormat.ReadSectorTag(track.TrackSequence, tag);

                    if (flags is null)
                    {
                        continue;
                    }

                    trackFlags[(byte)track.TrackSequence] = flags[0];
                }
            }

            for (ulong s = 0; s < inputFormat.Info.Sectors; s++)
            {
                if (s > int.MaxValue)
                {
                    break;
                }

                subchannelExtents.Add((int)s);
            }

            foreach (SectorTagType tag in inputFormat.Info.ReadableSectorTags.OrderBy(t => t).TakeWhile(tag => UseLong))
            {
                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 (!outputOptical.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:
                        sector = inputFormat.ReadSectorTag(track.TrackSequence, tag);
                        result = outputOptical.WriteSectorTag(sector, track.TrackSequence, tag);

                        Assert.IsTrue(result, $"Error {outputOptical.ErrorMessage} writing tag, not continuing...");

                        continue;
                    }

                    while (doneSectors < trackSectors)
                    {
                        uint sectorsToDo;

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

                        if (sectorsToDo == 1)
                        {
                            sector = inputFormat.ReadSectorTag(doneSectors + track.TrackStartSector, tag);

                            if (tag == SectorTagType.CdSectorSubchannel)
                            {
                                bool indexesChanged = CompactDisc.WriteSubchannelToImage(MmcSubchannel.Raw,
                                                                                         MmcSubchannel.Raw, sector, doneSectors + track.TrackStartSector, 1, null,
                                                                                         isrcs, (byte)track.TrackSequence, ref mcn, tracks, subchannelExtents, true,
                                                                                         outputOptical, true, true, null, null, smallestPregapLbaPerTrack, false);

                                if (indexesChanged)
                                {
                                    outputOptical.SetTracks(tracks.ToList());
                                }

                                result = true;
                            }
                            else
                            {
                                result = outputOptical.WriteSectorTag(sector, doneSectors + track.TrackStartSector,
                                                                      tag);
                            }
                        }
                        else
                        {
                            sector = inputFormat.ReadSectorsTag(doneSectors + track.TrackStartSector, sectorsToDo, tag);

                            if (tag == SectorTagType.CdSectorSubchannel)
                            {
                                bool indexesChanged = CompactDisc.WriteSubchannelToImage(MmcSubchannel.Raw,
                                                                                         MmcSubchannel.Raw, sector, doneSectors + track.TrackStartSector, sectorsToDo,
                                                                                         null, isrcs, (byte)track.TrackSequence, ref mcn, tracks, subchannelExtents,
                                                                                         true, outputOptical, true, true, null, null, smallestPregapLbaPerTrack, false);

                                if (indexesChanged)
                                {
                                    outputOptical.SetTracks(tracks.ToList());
                                }

                                result = true;
                            }
                            else
                            {
                                result = outputOptical.WriteSectorsTag(sector, doneSectors + track.TrackStartSector,
                                                                       sectorsToDo, tag);
                            }
                        }

                        Assert.IsTrue(result,
                                      $"Error {outputOptical.ErrorMessage} writing tag for sector {doneSectors + track.TrackStartSector}, not continuing...");

                        doneSectors += sectorsToDo;
                    }
                }
            }

            if (isrcs.Count > 0)
            {
                foreach (KeyValuePair <byte, string> isrc in isrcs)
                {
                    outputOptical.WriteSectorTag(Encoding.UTF8.GetBytes(isrc.Value), isrc.Key,
                                                 SectorTagType.CdTrackIsrc);
                }
            }

            if (trackFlags.Count > 0)
            {
                foreach ((byte track, byte flags) in trackFlags)
                {
                    outputOptical.WriteSectorTag(new[]
                    {
                        flags
                    }, track, SectorTagType.CdTrackFlags);
                }
            }

            if (mcn != null)
            {
                outputOptical.WriteMediaTag(Encoding.UTF8.GetBytes(mcn), MediaTagType.CD_MCN);
            }

            if (resume != null ||
                dumpHardware != null)
            {
                if (resume != null)
                {
                    outputOptical.SetDumpHardware(resume.Tries);
                }
                else if (dumpHardware != null)
                {
                    outputOptical.SetDumpHardware(dumpHardware);
                }
            }

            if (sidecar != null ||
                cicmMetadata != null)
            {
                if (sidecar != null)
                {
                    outputOptical.SetCicmMetadata(sidecar);
                }
                else if (cicmMetadata != null)
                {
                    outputOptical.SetCicmMetadata(cicmMetadata);
                }
            }

            Assert.True(outputOptical.Close(),
                        $"Error {outputOptical.ErrorMessage} closing output image... Contents are not correct.");

            // Some images will never generate the same
            if (Md5 != null)
            {
                string md5 = Md5Context.File(outputPath, out _);

                Assert.AreEqual(Md5, md5, "Hashes are different");
            }

            File.Delete(outputPath);
        }