mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 11:14:25 +00:00
Implement abortion in image convertion process.
This commit is contained in:
@@ -283,5 +283,9 @@ public enum ErrorNumber
|
||||
/// <summary>Specified sector could not be found</summary>
|
||||
SectorNotFound = 29,
|
||||
/// <summary>Image or device has not been opened</summary>
|
||||
NotOpened = 30
|
||||
NotOpened = 30,
|
||||
/// <summary>Canceled</summary>
|
||||
ECANCELED = Canceled,
|
||||
/// <summary>Canceled</summary>
|
||||
Canceled = -125
|
||||
}
|
||||
@@ -15,6 +15,8 @@ public partial class Convert
|
||||
/// <returns>Error if required features not supported and data would be lost</returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// </summary>
|
||||
/// <param name="useLong"></param>
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -13,6 +13,8 @@ public partial class Convert
|
||||
/// <returns>Error code if creation fails</returns>
|
||||
private ErrorNumber CreateOutputImage()
|
||||
{
|
||||
if(_aborted) return ErrorNumber.NoError;
|
||||
|
||||
InitProgress?.Invoke();
|
||||
PulseProgress?.Invoke(UI.Invoke_Opening_image_file);
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@ public partial class Convert
|
||||
/// <returns>Error code if conversion fails in non-force mode</returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// </summary>
|
||||
/// <returns>Error code if conversion fails in non-force mode</returns>
|
||||
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);
|
||||
|
||||
@@ -6,11 +6,15 @@ namespace Aaru.Core.Image;
|
||||
|
||||
public partial class Convert
|
||||
{
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
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
|
||||
{
|
||||
|
||||
@@ -32,18 +32,18 @@ public partial class Convert
|
||||
|
||||
if(errno != ErrorNumber.NoError) return errno;
|
||||
|
||||
Dictionary<byte, string> isrcs = new();
|
||||
Dictionary<byte, byte> trackFlags = new();
|
||||
Dictionary<byte, string> isrcs = [];
|
||||
Dictionary<byte, byte> trackFlags = [];
|
||||
string mcn = null;
|
||||
HashSet<int> subchannelExtents = [];
|
||||
Dictionary<byte, int> smallestPregapLbaPerTrack = new();
|
||||
Dictionary<byte, int> smallestPregapLbaPerTrack = [];
|
||||
var tracks = new Track[inputOptical.Tracks.Count];
|
||||
|
||||
for(var i = 0; i < tracks.Length; i++)
|
||||
{
|
||||
tracks[i] = new Track
|
||||
{
|
||||
Indexes = new Dictionary<ushort, int>(),
|
||||
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<int> subchannelExtents,
|
||||
Dictionary<byte, int> 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// </summary>
|
||||
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
|
||||
/// </summary>
|
||||
void GenerateDvdTitleKeys(IOpticalMediaImage inputOptical, PluginRegister plugins, ref byte[] generatedTitleKeys)
|
||||
{
|
||||
if(_aborted) return;
|
||||
|
||||
List<Partition> partitions = Partitions.GetAll(inputOptical);
|
||||
|
||||
partitions = partitions.FindAll(p =>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -16,6 +16,8 @@ public partial class Convert
|
||||
/// <returns>Status code</returns>
|
||||
ErrorNumber ConvertMediaTags()
|
||||
{
|
||||
if(_aborted) return ErrorNumber.NoError;
|
||||
|
||||
InitProgress?.Invoke();
|
||||
ErrorNumber errorNumber = ErrorNumber.NoError;
|
||||
|
||||
|
||||
@@ -7,26 +7,28 @@ namespace Aaru.Core.Image;
|
||||
|
||||
public partial class Convert
|
||||
{
|
||||
/// <summary>
|
||||
/// Validates tape image format compatibility
|
||||
/// Checks if input is tape-based but output format doesn't support tape images
|
||||
/// </summary>
|
||||
/// <returns>Error if unsupported media type combination detected</returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configures output format for tape image handling
|
||||
/// Calls SetTape() on output to initialize tape mode if both input and output support tapes
|
||||
/// </summary>
|
||||
/// <returns>Error if tape mode initialization fails</returns>
|
||||
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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user