Files
duplicati/Tools/Verification/DuplicatiVerify.ps1
T

162 lines
5.2 KiB
PowerShell
Raw Normal View History

2018-02-02 13:39:34 +01:00
#Requires -Version 5.1
2017-02-20 19:44:04 +01:00
param
(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]$FileOrDir
)
2016-08-20 00:22:33 +02:00
2018-02-02 13:39:34 +01:00
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
enum RemoteVolumeState
{
# Indicates that the remote volume is being created
Temporary
# Indicates that the remote volume is being uploaded
Uploading
# Indicates that the remote volume has been uploaded
Uploaded
# Indicates that the remote volume has been uploaded, and seen by a list operation
Verified
# Indicattes that the remote volume should be deleted
Deleting
# Indicates that the remote volume was successfully deleted from the remote location
Deleted
}
enum RemoteVolumeType
{
# Contains data blocks
Blocks
# Contains file lists
Files
# Contains redundant lookup information
Index
}
2016-08-20 00:22:33 +02:00
function HexToBase64
{
param
(
[Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)]
[string]$s
)
[array]$return = @()
for ($i = 0; $i -lt $s.Length ; $i += 2) {
$return += [Byte]::Parse($s.Substring($i, 2), [System.Globalization.NumberStyles]::HexNumber)
}
Write-Output $([Convert]::ToBase64String($return))
}
function Verify-Hashes
{
[CmdletBinding(PositionalBinding=$false)]
param
(
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
2018-02-02 21:30:52 +01:00
[System.IO.FileInfo]$filename
2016-08-20 00:22:33 +02:00
)
[int]$errorCount = 0
[int]$checked = 0
2018-02-02 13:52:08 +01:00
$remoteVolumes = $((Get-Content $filename) -Join "`n" | ConvertFrom-Json) | Sort-Object Name
2018-02-02 13:39:34 +01:00
$statsState = @{}
foreach ($n in 0..5) { $statsState.Add($n, $(New-Object PSObject -Property @{SumSize=0;SumCount=0})) }
$statsType = @{}
foreach ($n in 0..2) { $statsType.Add($n, $(New-Object PSObject -Property @{SumSize=0;SumCount=0})) }
2017-02-20 19:44:04 +01:00
2016-08-20 00:22:33 +02:00
foreach ($remoteVolume in $remoteVolumes) {
[string]$volFileName = $remoteVolume.Name
2018-02-02 21:30:52 +01:00
[string]$volFilePath = Join-Path -Path $filename.DirectoryName -ChildPath $volFileName
2016-08-20 00:22:33 +02:00
if(-not $(Test-Path $volFilePath)) {
2018-02-02 13:39:34 +01:00
if($remoteVolume.State -eq $([RemoteVolumeState]::Deleted -as [int])) {
$checked++
$statsState[$($remoteVolume.State)].SumCount += 1
$statsState[$($remoteVolume.State)].SumSize += $remoteVolume.Size
$statsType[$($remoteVolume.Type)].SumCount += 1
$statsType[$($remoteVolume.Type)].SumSize += $remoteVolume.Size
} else {
Write-Host "File missing: $volFileName" -ForegroundColor Red
$errorCount++
}
2016-08-20 00:22:33 +02:00
} else {
Write-Host "Verifying file $volFileName"
2018-02-02 13:39:34 +01:00
$checked++
$statsState[$($remoteVolume.State)].SumCount += 1
$statsState[$($remoteVolume.State)].SumSize += $remoteVolume.Size
$statsType[$($remoteVolume.Type)].SumCount += 1
$statsType[$($remoteVolume.Type)].SumSize += $remoteVolume.Size
2016-08-20 00:22:33 +02:00
$shaHash = Get-FileHash -Path $volFilePath -Algorithm SHA256
if($remoteVolume.Hash -ne $(HexToBase64 $shaHash.Hash)) {
Write-Host "*** Hash check failed for file: $volFileName" -ForegroundColor Red
$errorCount++
}
}
}
2018-02-02 21:30:52 +01:00
[string]$prefix = $filename.Name -replace "-verification.json", ""
[array]$filesInStorage = Get-ChildItem $(Join-Path $filename.DirectoryName "$prefix*") -Exclude $filename.Name -File | `
2017-02-20 19:44:04 +01:00
Select-Object -ExpandProperty Name | Sort-Object
[array]$filesInVerification = $remoteVolumes | Select-Object -ExpandProperty Name | Sort-Object
2018-02-02 13:39:34 +01:00
2017-02-20 19:44:04 +01:00
$filesInStorage | Where-Object {$filesInVerification -NotContains $_} | ForEach-Object {
Write-Host "Found extra file which is not in verification file: $_" -ForegroundColor Red
$errorCount++
}
2016-08-20 00:22:33 +02:00
if($errorCount -gt 0) {
2017-02-20 19:44:04 +01:00
Write-Host "`nErrors were found" -ForegroundColor Red
2016-08-20 00:22:33 +02:00
} else {
2017-02-20 19:44:04 +01:00
Write-Host "`nNo errors found" -ForegroundColor Green
2016-08-20 00:22:33 +02:00
}
2018-02-02 13:39:34 +01:00
Write-Host "`nSTATISTICS:"
foreach ($n in 0..5) {
Write-Host "`t$([Enum]::ToObject([RemoteVolumeState], $n)) - Count $($statsState[$n].SumCount), Size $("{0:n1} GB" -f ($statsState[$n].SumSize / 1gb))"
}
Write-Host
foreach ($n in 0..2) {
Write-Host "`t$([Enum]::ToObject([RemoteVolumeType], $n)) - Count $($statsType[$n].SumCount), Size $("{0:n1} GB" -f ($statsType[$n].SumSize / 1gb))"
}
Write-Host
2016-08-20 00:22:33 +02:00
return $errorCount
}
2017-02-20 19:44:04 +01:00
if(-not $(Test-Path $FileOrDir)) {
Write-Host "No such file or directory: $FileOrDir" -ForegroundColor Red
2018-02-02 13:39:34 +01:00
exit 1
2016-08-20 00:22:33 +02:00
}
2017-02-20 19:44:04 +01:00
if(Test-Path $FileOrDir -PathType Leaf) {
2018-02-02 13:39:34 +01:00
exit $(Verify-Hashes -filename $FileOrDir)
}
2016-08-20 00:22:33 +02:00
2018-02-02 21:30:52 +01:00
$verFiles = @(Get-ChildItem $FileOrDir -Filter "*-verification.json" -File)
2016-08-20 00:22:33 +02:00
2018-02-02 13:39:34 +01:00
if ($verFiles.Count -eq 0) {
Write-Host "No verification files in folder: $FileOrDir"
exit 1
}
[int]$errorCount = 0
2018-02-02 21:30:52 +01:00
foreach ($verFile in $verFiles) {
Write-Host "Verifying file: $($verFile.Name)"
$errorCount += $(Verify-Hashes -filename $verFile.FullName)
2018-02-02 13:39:34 +01:00
}
exit $errorCount