From 5febb2012dcf79a30e495f89ac0efb06f41466f0 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Tue, 25 Nov 2025 19:47:40 +0000 Subject: [PATCH] Implement abortion in image convertion process. --- Aaru.CommonTypes/Enums/ErrorNumber.cs | 6 ++++- Aaru.Core/Image/Convert/Capabilities.cs | 29 +++++++++++++++++-------- Aaru.Core/Image/Convert/Convert.cs | 15 +++++++++++-- Aaru.Core/Image/Convert/Create.cs | 2 ++ Aaru.Core/Image/Convert/Edge.cs | 27 ++++++++++++++++++----- Aaru.Core/Image/Convert/Metadata.cs | 10 ++++++--- Aaru.Core/Image/Convert/Optical.cs | 28 +++++++++++++++++------- Aaru.Core/Image/Convert/Sectors.cs | 4 ++++ Aaru.Core/Image/Convert/Tags.cs | 2 ++ Aaru.Core/Image/Convert/Tape.cs | 22 ++++++++++--------- 10 files changed, 106 insertions(+), 39 deletions(-) diff --git a/Aaru.CommonTypes/Enums/ErrorNumber.cs b/Aaru.CommonTypes/Enums/ErrorNumber.cs index 056600723..e3c243a6c 100644 --- a/Aaru.CommonTypes/Enums/ErrorNumber.cs +++ b/Aaru.CommonTypes/Enums/ErrorNumber.cs @@ -283,5 +283,9 @@ public enum ErrorNumber /// Specified sector could not be found SectorNotFound = 29, /// Image or device has not been opened - NotOpened = 30 + NotOpened = 30, + /// Canceled + ECANCELED = Canceled, + /// Canceled + Canceled = -125 } \ No newline at end of file diff --git a/Aaru.Core/Image/Convert/Capabilities.cs b/Aaru.Core/Image/Convert/Capabilities.cs index a34df7a2d..785cc5751 100644 --- a/Aaru.Core/Image/Convert/Capabilities.cs +++ b/Aaru.Core/Image/Convert/Capabilities.cs @@ -15,6 +15,8 @@ public partial class Convert /// Error if required features not supported and data would be lost ErrorNumber ValidateMediaCapabilities() { + if(_aborted) return ErrorNumber.NoError; + if(!_outputImage.SupportedMediaTypes.Contains(_mediaType)) { StoppingErrorMessage?.Invoke(UI.Output_format_does_not_support_media_type); @@ -22,8 +24,11 @@ public partial class Convert return ErrorNumber.UnsupportedMedia; } - foreach(MediaTagType mediaTag in _inputImage.Info.ReadableMediaTags.Where(mediaTag => - !_outputImage.SupportedMediaTags.Contains(mediaTag) && !_force)) + foreach(MediaTagType mediaTag in _inputImage.Info.ReadableMediaTags + .Where(mediaTag => + !_outputImage.SupportedMediaTags.Contains(mediaTag) && + !_force) + .TakeWhile(_ => !_aborted)) { StoppingErrorMessage?.Invoke(string.Format(UI.Converting_image_will_lose_media_tag_0 + Environment.NewLine + @@ -36,17 +41,23 @@ public partial class Convert return ErrorNumber.NoError; } + /// + /// Validates sector tag compatibility between formats + /// Sets useLong flag based on sector tag support to determine sector size (512 vs 2352 bytes) + /// Some tags like CD flags/ISRC don't require long sectors; subchannel data does + /// In force mode, skips unsupported tags; otherwise reports error if data would be lost + /// + /// ErrorNumber ValidateSectorTags(out bool useLong) { - // Validates sector tag compatibility between formats - // Sets useLong flag based on sector tag support to determine sector size (512 vs 2352 bytes) - // Some tags like CD flags/ISRC don't require long sectors; subchannel data does - // In force mode, skips unsupported tags; otherwise reports error if data would be lost - useLong = _inputImage.Info.ReadableSectorTags.Count != 0; - foreach(SectorTagType sectorTag in _inputImage.Info.ReadableSectorTags.Where(sectorTag => - !_outputImage.SupportedSectorTags.Contains(sectorTag))) + if(_aborted) return ErrorNumber.NoError; + + foreach(SectorTagType sectorTag in _inputImage.Info.ReadableSectorTags + .Where(sectorTag => + !_outputImage.SupportedSectorTags.Contains(sectorTag)) + .TakeWhile(_ => !_aborted)) { if(_force) { diff --git a/Aaru.Core/Image/Convert/Convert.cs b/Aaru.Core/Image/Convert/Convert.cs index 9a02c197f..67974fca3 100644 --- a/Aaru.Core/Image/Convert/Convert.cs +++ b/Aaru.Core/Image/Convert/Convert.cs @@ -227,6 +227,8 @@ public partial class Convert foreach(TapeFile tapeFile in inputTape.Files) { + if(_aborted) break; + UpdateProgress?.Invoke(string.Format(UI.Converting_file_0_of_partition_1, tapeFile.File, tapeFile.Partition), @@ -244,6 +246,8 @@ public partial class Convert foreach(TapePartition tapePartition in inputTape.TapePartitions) { + if(_aborted) break; + UpdateProgress?.Invoke(string.Format(UI.Converting_tape_partition_0, tapePartition.Number), currentPartition + 1, inputTape.TapePartitions.Count); @@ -270,7 +274,7 @@ public partial class Convert if(errno != ErrorNumber.NoError) return errno; } - if(_resume != null || dumpHardware != null) + if((_resume != null || dumpHardware != null) && !_aborted) { InitProgress?.Invoke(); @@ -287,7 +291,7 @@ public partial class Convert ret = false; - if(_sidecar != null || metadata != null) + if((_sidecar != null || metadata != null) && !_aborted) { InitProgress?.Invoke(); PulseProgress?.Invoke(UI.Writing_metadata); @@ -301,6 +305,13 @@ public partial class Convert EndProgress?.Invoke(); } + if(_aborted) + { + UpdateStatus?.Invoke(UI.Operation_canceled_the_output_file_is_not_correct); + + return ErrorNumber.Canceled; + } + var closed = false; InitProgress?.Invoke(); diff --git a/Aaru.Core/Image/Convert/Create.cs b/Aaru.Core/Image/Convert/Create.cs index 8bcde68e4..900eb1416 100644 --- a/Aaru.Core/Image/Convert/Create.cs +++ b/Aaru.Core/Image/Convert/Create.cs @@ -13,6 +13,8 @@ public partial class Convert /// Error code if creation fails private ErrorNumber CreateOutputImage() { + if(_aborted) return ErrorNumber.NoError; + InitProgress?.Invoke(); PulseProgress?.Invoke(UI.Invoke_Opening_image_file); diff --git a/Aaru.Core/Image/Convert/Edge.cs b/Aaru.Core/Image/Convert/Edge.cs index 13f0fb8e4..fcb4f7dbf 100644 --- a/Aaru.Core/Image/Convert/Edge.cs +++ b/Aaru.Core/Image/Convert/Edge.cs @@ -15,6 +15,8 @@ public partial class Convert /// Error code if conversion fails in non-force mode ErrorNumber ConvertNegativeSectors(bool useLong) { + if(_aborted) return ErrorNumber.NoError; + ErrorNumber errno = ErrorNumber.NoError; InitProgress?.Invoke(); @@ -22,6 +24,8 @@ public partial class Convert // There's no -0 for(uint i = 1; i <= _negativeSectors; i++) { + if(_aborted) break; + byte[] sector; UpdateProgress?.Invoke(string.Format(UI.Converting_negative_sector_0_of_1, i, _negativeSectors), @@ -96,7 +100,8 @@ public partial class Convert EndProgress?.Invoke(); - foreach(SectorTagType tag in _inputImage.Info.ReadableSectorTags.TakeWhile(_ => useLong)) + foreach(SectorTagType tag in _inputImage.Info.ReadableSectorTags.TakeWhile(_ => useLong) + .TakeWhile(_ => !_aborted)) { switch(tag) { @@ -125,6 +130,8 @@ public partial class Convert for(uint i = 1; i <= _negativeSectors; i++) { + if(_aborted) break; + UpdateProgress?.Invoke(string.Format(UI.Converting_tag_1_for_negative_sector_0, i, tag), i, _negativeSectors); @@ -167,12 +174,15 @@ public partial class Convert return errno; } + /// + /// Converts overflow sectors (lead-out) from input to output image + /// Handles both long and short sector formats with progress indication + /// Also converts associated sector tags if present + /// + /// Error code if conversion fails in non-force mode ErrorNumber ConvertOverflowSectors(bool useLong) { - // Converts overflow sectors (lead-out) from input to output image - // Handles both long and short sector formats with progress indication - // Also converts associated sector tags if present - // Returns error code if conversion fails in non-force mode + if(_aborted) return ErrorNumber.NoError; ErrorNumber errno = ErrorNumber.NoError; @@ -180,6 +190,8 @@ public partial class Convert for(uint i = 0; i < _overflowSectors; i++) { + if(_aborted) break; + byte[] sector; UpdateProgress?.Invoke(string.Format(UI.Converting_overflow_sector_0_of_1, i, _overflowSectors), @@ -254,7 +266,8 @@ public partial class Convert EndProgress?.Invoke(); - foreach(SectorTagType tag in _inputImage.Info.ReadableSectorTags.TakeWhile(_ => useLong)) + foreach(SectorTagType tag in _inputImage.Info.ReadableSectorTags.TakeWhile(_ => useLong) + .TakeWhile(_ => !_aborted)) { switch(tag) { @@ -283,6 +296,8 @@ public partial class Convert for(uint i = 1; i <= _overflowSectors; i++) { + if(_aborted) break; + UpdateProgress?.Invoke(string.Format(UI.Converting_tag_1_for_overflow_sector_0, i, tag), i, _overflowSectors); diff --git a/Aaru.Core/Image/Convert/Metadata.cs b/Aaru.Core/Image/Convert/Metadata.cs index 111606d8f..290344ee2 100644 --- a/Aaru.Core/Image/Convert/Metadata.cs +++ b/Aaru.Core/Image/Convert/Metadata.cs @@ -6,11 +6,15 @@ namespace Aaru.Core.Image; public partial class Convert { + /// + /// Builds and applies complete ImageInfo metadata to output image + /// Copies input metadata and applies command-line overrides (title, comments, creator, drive info, etc.) + /// Sets Aaru application version and applies all metadata fields to output format + /// + /// ErrorNumber SetImageMetadata() { - // Builds and applies complete ImageInfo metadata to output image - // Copies input metadata and applies command-line overrides (title, comments, creator, drive info, etc.) - // Sets Aaru application version and applies all metadata fields to output format + if(_aborted) return ErrorNumber.NoError; var imageInfo = new CommonTypes.Structs.ImageInfo { diff --git a/Aaru.Core/Image/Convert/Optical.cs b/Aaru.Core/Image/Convert/Optical.cs index a4d4ecb8b..1429ddefa 100644 --- a/Aaru.Core/Image/Convert/Optical.cs +++ b/Aaru.Core/Image/Convert/Optical.cs @@ -32,18 +32,18 @@ public partial class Convert if(errno != ErrorNumber.NoError) return errno; - Dictionary isrcs = new(); - Dictionary trackFlags = new(); + Dictionary isrcs = []; + Dictionary trackFlags = []; string mcn = null; HashSet subchannelExtents = []; - Dictionary smallestPregapLbaPerTrack = new(); + Dictionary smallestPregapLbaPerTrack = []; var tracks = new Track[inputOptical.Tracks.Count]; for(var i = 0; i < tracks.Length; i++) { tracks[i] = new Track { - Indexes = new Dictionary(), + Indexes = [], Description = inputOptical.Tracks[i].Description, EndSector = inputOptical.Tracks[i].EndSector, StartSector = inputOptical.Tracks[i].StartSector, @@ -147,6 +147,7 @@ public partial class Convert ErrorNumber ConvertOpticalSectors(IOpticalMediaImage inputOptical, IWritableOpticalImage outputOptical, bool useLong) { + if(_aborted) return ErrorNumber.NoError; InitProgress?.Invoke(); InitProgress2?.Invoke(); byte[] generatedTitleKeys = null; @@ -154,6 +155,8 @@ public partial class Convert foreach(Track track in inputOptical.Tracks) { + if(_aborted) break; + UpdateProgress?.Invoke(string.Format(UI.Converting_sectors_in_track_0_of_1, currentTrack + 1, inputOptical.Tracks.Count), @@ -165,6 +168,7 @@ public partial class Convert while(doneSectors < trackSectors) { + if(_aborted) break; byte[] sector; uint sectorsToDo; @@ -340,7 +344,9 @@ public partial class Convert HashSet subchannelExtents, Dictionary smallestPregapLbaPerTrack) { - foreach(SectorTagType tag in inputOptical.Info.ReadableSectorTags.Order().TakeWhile(_ => useLong)) + foreach(SectorTagType tag in inputOptical.Info.ReadableSectorTags.Order() + .TakeWhile(_ => useLong) + .TakeWhile(_ => !_aborted)) { switch(tag) { @@ -439,6 +445,7 @@ public partial class Convert while(doneSectors < trackSectors) { + if(_aborted) break; uint sectorsToDo; if(trackSectors - doneSectors >= _count) @@ -616,12 +623,15 @@ public partial class Convert return ErrorNumber.NoError; } + /// + /// Decrypts DVD sectors using CSS (Content Scramble System) decryption + /// Retrieves decryption keys from sector tags or generates them from ISO9660 filesystem + /// Only MPEG packets within sectors can be encrypted + /// void DecryptDvdSector(ref byte[] sector, IOpticalMediaImage inputOptical, ulong sectorAddress, uint sectorsToDo, PluginRegister plugins, ref byte[] generatedTitleKeys) { - // Decrypts DVD sectors using CSS (Content Scramble System) decryption - // Retrieves decryption keys from sector tags or generates them from ISO9660 filesystem - // Only MPEG packets within sectors can be encrypted + if(_aborted) return; // Only sectors which are MPEG packets can be encrypted. if(!Mpeg.ContainsMpegPackets(sector, sectorsToDo)) return; @@ -682,6 +692,8 @@ public partial class Convert /// void GenerateDvdTitleKeys(IOpticalMediaImage inputOptical, PluginRegister plugins, ref byte[] generatedTitleKeys) { + if(_aborted) return; + List partitions = Partitions.GetAll(inputOptical); partitions = partitions.FindAll(p => diff --git a/Aaru.Core/Image/Convert/Sectors.cs b/Aaru.Core/Image/Convert/Sectors.cs index 32f40bae7..1799c94cb 100644 --- a/Aaru.Core/Image/Convert/Sectors.cs +++ b/Aaru.Core/Image/Convert/Sectors.cs @@ -9,6 +9,8 @@ public partial class Convert { ErrorNumber ConvertSectors(bool useLong, bool isTape) { + if(_aborted) return ErrorNumber.NoError; + InitProgress?.Invoke(); ErrorNumber errno = ErrorNumber.NoError; ulong doneSectors = 0; @@ -133,6 +135,8 @@ public partial class Convert ErrorNumber ConvertSectorsTags(bool useLong) { + if(_aborted) return ErrorNumber.NoError; + foreach(SectorTagType tag in _inputImage.Info.ReadableSectorTags.TakeWhile(_ => useLong)) { switch(tag) diff --git a/Aaru.Core/Image/Convert/Tags.cs b/Aaru.Core/Image/Convert/Tags.cs index 3089544ee..d9769348a 100644 --- a/Aaru.Core/Image/Convert/Tags.cs +++ b/Aaru.Core/Image/Convert/Tags.cs @@ -16,6 +16,8 @@ public partial class Convert /// Status code ErrorNumber ConvertMediaTags() { + if(_aborted) return ErrorNumber.NoError; + InitProgress?.Invoke(); ErrorNumber errorNumber = ErrorNumber.NoError; diff --git a/Aaru.Core/Image/Convert/Tape.cs b/Aaru.Core/Image/Convert/Tape.cs index f6d3abdb3..86bd57a09 100644 --- a/Aaru.Core/Image/Convert/Tape.cs +++ b/Aaru.Core/Image/Convert/Tape.cs @@ -7,26 +7,28 @@ namespace Aaru.Core.Image; public partial class Convert { + /// + /// Validates tape image format compatibility + /// Checks if input is tape-based but output format doesn't support tape images + /// + /// Error if unsupported media type combination detected ErrorNumber ValidateTapeImage(ITapeImage inputTape, IWritableTapeImage outputTape) { - // Validates tape image format compatibility - // Checks if input is tape-based but output format doesn't support tape images - // Returns error if unsupported media type combination detected - - if(inputTape?.IsTape != true || outputTape is not null) return ErrorNumber.NoError; + if(_aborted || inputTape?.IsTape != true || outputTape is not null) return ErrorNumber.NoError; StoppingErrorMessage?.Invoke(UI.Input_format_contains_a_tape_image_and_is_not_supported_by_output_format); return ErrorNumber.UnsupportedMedia; } + /// + /// Configures output format for tape image handling + /// Calls SetTape() on output to initialize tape mode if both input and output support tapes + /// + /// Error if tape mode initialization fails ErrorNumber SetupTapeImage(ITapeImage inputTape, IWritableTapeImage outputTape) { - // Configures output format for tape image handling - // Calls SetTape() on output to initialize tape mode if both input and output support tapes - // Returns error if tape mode initialization fails - - if(inputTape?.IsTape != true || outputTape == null) return ErrorNumber.NoError; + if(_aborted || inputTape?.IsTape != true || outputTape == null) return ErrorNumber.NoError; bool ret = outputTape.SetTape();