2017-06-12 22:59:47 +01:00
// /***************************************************************************
2020-02-27 12:31:25 +00:00
// Aaru Data Preservation Suite
2017-06-12 22:59:47 +01:00
// ----------------------------------------------------------------------------
//
// Filename : ResumeSupport.cs
2017-12-19 03:50:57 +00:00
// Author(s) : Natalia Portillo <claunia@claunia.com>
2017-06-12 22:59:47 +01:00
//
2017-12-19 03:50:57 +00:00
// Component : Core algorithms.
2017-06-12 22:59:47 +01:00
//
// --[ Description ] ----------------------------------------------------------
//
2017-12-19 03:50:57 +00:00
// Contains logic to support dump resuming.
2017-06-12 22:59:47 +01:00
//
// --[ License ] --------------------------------------------------------------
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
2020-01-03 17:51:30 +00:00
// Copyright © 2011-2020 Natalia Portillo
2017-06-12 22:59:47 +01:00
// ****************************************************************************/
2017-12-19 03:50:57 +00:00
using System ;
2017-06-20 05:48:09 +01:00
using System.Collections.Generic ;
2020-02-27 00:33:26 +00:00
using Aaru.CommonTypes.Extents ;
using Aaru.CommonTypes.Metadata ;
2017-06-20 05:48:09 +01:00
using Schemas ;
2020-02-27 00:33:26 +00:00
using PlatformID = Aaru . CommonTypes . Interop . PlatformID ;
using Version = Aaru . CommonTypes . Interop . Version ;
2017-06-20 05:48:09 +01:00
2020-02-27 00:33:26 +00:00
namespace Aaru.Core.Devices.Dumping
2017-06-12 22:59:47 +01:00
{
2020-01-09 16:14:00 +00:00
/// <summary>Implements resume support</summary>
internal static class ResumeSupport
2017-06-12 22:59:47 +01:00
{
2020-01-09 16:14:00 +00:00
/// <summary>Process resume</summary>
2017-12-23 01:46:08 +00:00
/// <param name="isLba">If drive is LBA</param>
/// <param name="removable">If media is removable from device</param>
/// <param name="blocks">Media blocks</param>
/// <param name="manufacturer">Device manufacturer</param>
/// <param name="model">Device model</param>
/// <param name="serial">Device serial</param>
/// <param name="platform">Platform where the dump is made</param>
/// <param name="resume">Previous resume, or null</param>
/// <param name="currentTry">Current dumping hardware</param>
/// <param name="extents">Dumped extents</param>
2020-01-09 16:14:00 +00:00
/// <param name="firmware">Firmware revision</param>
/// <param name="isTape">Set to <c>true</c> if device is a streaming tape, <c>false</c> otherwise</param>
2017-12-23 17:41:23 +00:00
/// <exception cref="System.NotImplementedException">If device uses CHS addressing</exception>
/// <exception cref="System.InvalidOperationException">
/// If the provided resume does not correspond with the current in
/// progress dump
/// </exception>
2020-01-09 16:14:00 +00:00
internal static void Process ( bool isLba , bool removable , ulong blocks , string manufacturer , string model ,
string serial , PlatformID platform , ref Resume resume ,
ref DumpHardwareType currentTry , ref ExtentsULong extents , string firmware ,
2020-03-11 15:28:04 +00:00
bool @private , bool isTape = false )
2017-06-12 22:59:47 +01:00
{
2020-03-11 15:28:04 +00:00
if ( @private )
serial = null ;
2017-06-20 05:48:09 +01:00
if ( resume ! = null )
{
2020-01-09 16:14:00 +00:00
if ( ! isLba )
throw new NotImplementedException ( "Resuming CHS devices is currently not supported." ) ;
2017-06-20 05:48:09 +01:00
2019-05-01 00:40:19 +01:00
if ( resume . Tape ! = isTape )
throw new
InvalidOperationException ( $"Resume file specifies a {(resume.Tape ? " tape " : " not tape ")} device but you're requesting to dump a {(isTape ? " tape " : " not tape ")} device, not continuing..." ) ;
2017-06-20 05:48:09 +01:00
if ( resume . Removable ! = removable )
2017-12-19 20:33:03 +00:00
throw new
2017-12-23 01:46:08 +00:00
InvalidOperationException ( $"Resume file specifies a {(resume.Removable ? " removable " : " non removable ")} device but you're requesting to dump a {(removable ? " removable " : " non removable ")} device, not continuing..." ) ;
2017-06-20 05:48:09 +01:00
2020-01-09 16:14:00 +00:00
if ( ! isTape & &
resume . LastBlock ! = blocks - 1 )
2017-12-19 20:33:03 +00:00
throw new
2017-12-23 01:46:08 +00:00
InvalidOperationException ( $"Resume file specifies a device with {resume.LastBlock + 1} blocks but you're requesting to dump one with {blocks} blocks, not continuing..." ) ;
2017-06-20 05:48:09 +01:00
2020-01-09 16:14:00 +00:00
foreach ( DumpHardwareType oldTry in resume . Tries )
2017-06-20 05:48:09 +01:00
{
2017-12-23 01:46:08 +00:00
if ( ! removable )
{
2020-01-09 16:14:00 +00:00
if ( oldTry . Manufacturer ! = manufacturer )
2017-12-23 01:46:08 +00:00
throw new
2020-01-09 16:14:00 +00:00
InvalidOperationException ( $"Resume file specifies a device manufactured by {oldTry.Manufacturer} but you're requesting to dump one by {manufacturer}, not continuing..." ) ;
2017-06-20 05:48:09 +01:00
2020-01-09 16:14:00 +00:00
if ( oldTry . Model ! = model )
2017-12-23 01:46:08 +00:00
throw new
2020-01-09 16:14:00 +00:00
InvalidOperationException ( $"Resume file specifies a device model {oldTry.Model} but you're requesting to dump model {model}, not continuing..." ) ;
2017-06-20 05:48:09 +01:00
2020-01-09 16:14:00 +00:00
if ( oldTry . Serial ! = serial )
2017-12-23 01:46:08 +00:00
throw new
2020-01-09 16:14:00 +00:00
InvalidOperationException ( $"Resume file specifies a device with serial {oldTry.Serial} but you're requesting to dump one with serial {serial}, not continuing..." ) ;
if ( oldTry . Firmware ! = firmware )
throw new
InvalidOperationException ( $"Resume file specifies a device with firmware version {oldTry.Firmware} but you're requesting to dump one with firmware version {firmware}, not continuing..." ) ;
2017-12-23 01:46:08 +00:00
}
2017-06-20 05:48:09 +01:00
2020-01-09 16:14:00 +00:00
if ( oldTry . Software = = null )
2017-12-23 17:41:23 +00:00
throw new InvalidOperationException ( "Found corrupt resume file, cannot continue..." ) ;
2017-06-20 05:48:09 +01:00
2020-02-29 18:03:35 +00:00
if ( oldTry . Software . Name ! = "Aaru" | |
2020-01-09 16:14:00 +00:00
oldTry . Software . OperatingSystem ! = platform . ToString ( ) | |
oldTry . Software . Version ! = Version . GetVersion ( ) )
continue ;
2017-12-19 20:33:03 +00:00
2020-01-09 16:14:00 +00:00
if ( removable & & ( oldTry . Manufacturer ! = manufacturer | | oldTry . Model ! = model | |
oldTry . Serial ! = serial | | oldTry . Firmware ! = firmware ) )
continue ;
2017-12-21 06:06:19 +00:00
2020-01-09 16:14:00 +00:00
currentTry = oldTry ;
2017-12-29 01:26:58 +00:00
extents = ExtentsConverter . FromMetadata ( currentTry . Extents ) ;
2020-01-09 16:14:00 +00:00
2017-12-21 06:06:19 +00:00
break ;
2017-06-20 05:48:09 +01:00
}
2020-01-09 16:14:00 +00:00
if ( currentTry ! = null )
return ;
2017-12-21 06:06:19 +00:00
currentTry = new DumpHardwareType
2017-06-20 05:48:09 +01:00
{
2020-01-09 16:14:00 +00:00
Software = CommonTypes . Metadata . Version . GetSoftwareType ( ) , Manufacturer = manufacturer ,
Model = model , Serial = serial ,
Firmware = firmware
2017-12-21 06:06:19 +00:00
} ;
2020-01-09 16:14:00 +00:00
2017-12-21 06:06:19 +00:00
resume . Tries . Add ( currentTry ) ;
extents = new ExtentsULong ( ) ;
2017-06-20 05:48:09 +01:00
}
else
{
resume = new Resume
{
2020-01-09 16:14:00 +00:00
Tries = new List < DumpHardwareType > ( ) , CreationDate = DateTime . UtcNow ,
BadBlocks = new List < ulong > ( ) ,
LastBlock = isTape ? 0 : blocks - 1 , Tape = isTape
2017-06-20 05:48:09 +01:00
} ;
2020-01-09 16:14:00 +00:00
2017-06-20 05:48:09 +01:00
currentTry = new DumpHardwareType
{
2020-01-09 16:14:00 +00:00
Software = CommonTypes . Metadata . Version . GetSoftwareType ( ) , Manufacturer = manufacturer ,
Model = model , Serial = serial ,
Firmware = firmware
2017-06-20 05:48:09 +01:00
} ;
2020-01-09 16:14:00 +00:00
2017-06-20 05:48:09 +01:00
resume . Tries . Add ( currentTry ) ;
2017-12-29 01:26:58 +00:00
extents = new ExtentsULong ( ) ;
2017-06-20 05:48:09 +01:00
resume . Removable = removable ;
}
2017-06-12 22:59:47 +01:00
}
}
2017-12-19 20:33:03 +00:00
}