Merge pull request #40 from ShawnMcGough/main

usb drive validation, file hash verification, PowerShell 7 support
This commit is contained in:
Dave Russell
2026-05-30 04:54:29 +10:00
committed by GitHub
2 changed files with 52 additions and 7 deletions
+1
View File
@@ -22,6 +22,7 @@ Now supports encrypted volumes.
| Drive source | DSM version | Btrfs/Ext | Storage Pool type | RAID | Encrypted | Notes |
|--------------|----------------|-----------|-------------------|-------|-----------|-----------------|
| DS925+ | 7.3.2 Update 3 | Btrfs | Multiple Volume | SHR | no | 3 drives |
| DS916+ | 7.2.1 Update 9 | Btrfs | Single Volume | SHR | no | 4 drives |
| DS720+ | 7.2.1 Update 4 | Btrfs | Multiple Volume | SHR | Volume | Single drive |
| DS720+ | 7.2.1 Update 4 | Btrfs | Multiple Volume | SHR | no | Single drive |
| DS1812+ | 6.2.4 Update 7 | Btrfs | Multiple Volume | SHR | no | Single drive |
+51 -7
View File
@@ -12,7 +12,10 @@ Write-Host "=========================================" -ForegroundColor Cyan
Write-Host ""
# Find files in the same directory as this script
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
# Use $PSScriptRoot (works in both PS 5.1 and PS 7); it's always set when
# running as a script, whereas $MyInvocation.MyCommand.Path can be $null
# in some hosts or when the script is dot-sourced.
$ScriptDir = $PSScriptRoot
$btrfsSrc = Join-Path $ScriptDir "btrfs.ko"
$recoverSrc = Join-Path $ScriptDir "syno_recover_data.sh"
@@ -34,7 +37,9 @@ if (-not (Test-Path $recoverSrc)) {
# List removable drives to help user identify the correct one
Write-Host "Removable drives currently available:" -ForegroundColor Cyan
$removableDrives = Get-WmiObject Win32_LogicalDisk | Where-Object { $_.DriveType -eq 2 }
# Use Get-CimInstance instead of Get-WmiObject so the script works on both
# Windows PowerShell 5.1 and PowerShell 7.x (Get-WmiObject was removed in PS 7).
$removableDrives = Get-CimInstance -ClassName Win32_LogicalDisk -Filter 'DriveType = 2'
if ($removableDrives) {
foreach ($drive in $removableDrives) {
$size = [math]::Round($drive.Size / 1GB, 0)
@@ -47,11 +52,35 @@ if ($removableDrives) {
Write-Host ""
# Prompt for drive letter
Write-Host "Enter the drive letter of your Ubuntu 19.10 USB drive (e.g. G): " -ForegroundColor Cyan -NoNewline
$letter = Read-Host
$letter = $letter.Trim().TrimEnd(':').ToUpper()
# Loop until the user enters a single A-Z letter that maps to an existing drive,
# otherwise an empty/garbage input would produce confusing "could not find :\..." errors below.
do {
Write-Host "Enter the drive letter of your Ubuntu 19.10 USB drive (e.g. G): " -ForegroundColor Cyan -NoNewline
$letter = (Read-Host).Trim().TrimEnd(':').ToUpper()
if ($letter -notmatch '^[A-Z]$') {
Write-Host " Please enter a single letter (A-Z)." -ForegroundColor Yellow
$letter = $null
} elseif (-not (Test-Path "${letter}:\")) {
Write-Host " Drive ${letter}: was not found." -ForegroundColor Yellow
$letter = $null
}
} until ($letter)
$UsbDrive = "${letter}:"
# Safety check: if the chosen letter isn't in the removable-drives list, make the
# user explicitly confirm. Guards against accidentally typing a fixed/system drive.
$removableLetters = @($removableDrives | ForEach-Object { $_.DeviceID.TrimEnd(':').ToUpper() })
if ($removableLetters -notcontains $letter) {
Write-Host ""
Write-Host "WARNING: ${UsbDrive} is NOT detected as a removable drive." -ForegroundColor Yellow
Write-Host "Type 'YES' to continue anyway: " -ForegroundColor Yellow -NoNewline
if ((Read-Host) -ne 'YES') {
Write-Host "Aborted." -ForegroundColor Red
Read-Host "Press Enter to exit"
exit 1
}
}
Write-Host ""
# Verify it looks like the correct drive
@@ -94,7 +123,15 @@ if (-not (Test-Path $btrfsDest)) {
Read-Host "Press Enter to exit"
exit 1
}
Write-Host "Copied btrfs.ko successfully ($([math]::Round((Get-Item $btrfsDest).Length / 1MB, 1)) MB)." -ForegroundColor Green
# Verify the copy by SHA-256 hash, not just by existence. Test-Path returns true
# even on a truncated/corrupt copy, which is a real risk with cheap USB media.
if ((Get-FileHash $btrfsSrc -Algorithm SHA256).Hash -ne (Get-FileHash $btrfsDest -Algorithm SHA256).Hash) {
Write-Host "ERROR: btrfs.ko on USB drive does not match source (hash mismatch). The copy is corrupt." -ForegroundColor Red
Write-Host ""
Read-Host "Press Enter to exit"
exit 1
}
Write-Host "Copied btrfs.ko successfully ($([math]::Round((Get-Item $btrfsDest).Length / 1MB, 1)) MB, hash-verified)." -ForegroundColor Green
# Copy syno_recover_data.sh to USB drive root
$recoverDest = "$UsbDrive\syno_recover_data.sh"
@@ -114,7 +151,14 @@ if (-not (Test-Path $recoverDest)) {
Read-Host "Press Enter to exit"
exit 1
}
Write-Host "Copied syno_recover_data.sh successfully." -ForegroundColor Green
# Verify the copy by SHA-256 hash (see note above on btrfs.ko).
if ((Get-FileHash $recoverSrc -Algorithm SHA256).Hash -ne (Get-FileHash $recoverDest -Algorithm SHA256).Hash) {
Write-Host "ERROR: syno_recover_data.sh on USB drive does not match source (hash mismatch). The copy is corrupt." -ForegroundColor Red
Write-Host ""
Read-Host "Press Enter to exit"
exit 1
}
Write-Host "Copied syno_recover_data.sh successfully (hash-verified)." -ForegroundColor Green
Write-Host ""
Write-Host "USB drive setup successfully!" -ForegroundColor Green