diff --git a/.continue/rules/project.md b/.continue/rules/project.md index 7c1b8de..9b411cb 100644 --- a/.continue/rules/project.md +++ b/.continue/rules/project.md @@ -14,6 +14,12 @@ description: mtm-ddwipe project conventions - Keep messages short and clear. - Keep help concise, usage-first, and warning-focused. - Preserve the fallback wipe flow: secure discard, zero discard, then `dd` zero-fill. +- Keep optional tools optional. +- Use extra wipe methods only if the command is present. +- Use `ddrescue` or `dd_rescue` only after `dd` fails. +- Keep `nvme-cli` and `hdparm` optional. +- Use `nvme` and `hdparm` only on matching device types. +- Do not make new external tools required. - Keep changes minimal and preserve intent. - Keep `./continue/rules/project.md` aligned and concise. - If non-interactive support is added, make it an opt-in safety flag. @@ -21,3 +27,4 @@ description: mtm-ddwipe project conventions # Project identity - Main script: `mtm-ddwipe` - License: GNU GPL v3 + diff --git a/mtm-ddwipe b/mtm-ddwipe index bfef696..32d4902 100644 --- a/mtm-ddwipe +++ b/mtm-ddwipe @@ -13,9 +13,10 @@ Usage: mtm-ddwipe DEVICE Wipe a block device. Warnings: - - This is destructive and irreversible. - - The target device must not be mounted or in use. - - blkdiscard support depends on the device and firmware. + - Destructive and irreversible. + - Target must not be mounted or in use. + - Optional tools: blkdiscard, ddrescue, dd_rescue, nvme-cli, hdparm. + - nvme and hdparm need matching device types. - dd fallback may take a long time. Version: ${VERSION} @@ -67,6 +68,26 @@ check_device_not_in_use() { fi } +is_nvme_device() { + local dev="$1" + local sysdev + + sysdev="/sys$(lsblk -ndo PATH "$dev" 2>/dev/null | head -n1)" + [ -n "$sysdev" ] || return 1 + [ -e "$sysdev" ] || return 1 + [ -d "$sysdev/device" ] || return 1 + [ -e "$sysdev/device/uevent" ] || return 1 + grep -q '^NVME=1$' "$sysdev/device/uevent" +} + +is_ata_device() { + local dev="$1" + local tran + + tran="$(lsblk -ndo TRAN "$dev" 2>/dev/null | head -n1)" + [ "$tran" = "sata" ] || [ "$tran" = "ata" ] +} + confirm_wipe() { local dev="$1" local choice="" @@ -135,8 +156,40 @@ wipe_with_dd() { log "dd zero" dd if=/dev/zero of="$dev" bs=1M status=progress conv=fsync - log "Wiped with dd, check if full size is written." - log "Otherwise use a mechanical destruction of the device." +} + +wipe_with_ddrescue() { + local dev="$1" + + command -v ddrescue >/dev/null 2>&1 || return 1 + log "ddrescue zero" + ddrescue -f -n /dev/zero "$dev" +} + +wipe_with_dd_rescue() { + local dev="$1" + + command -v dd_rescue >/dev/null 2>&1 || return 1 + log "dd_rescue zero" + dd_rescue -f /dev/zero "$dev" +} + +wipe_with_nvme() { + local dev="$1" + + command -v nvme >/dev/null 2>&1 || return 1 + is_nvme_device "$dev" || return 1 + log "nvme format" + nvme format "$dev" -s 1 >/dev/null +} + +wipe_with_hdparm() { + local dev="$1" + + command -v hdparm >/dev/null 2>&1 || return 1 + is_ata_device "$dev" || return 1 + log "hdparm secure erase" + hdparm --security-erase NULL "$dev" } wipe_dev() { @@ -164,6 +217,20 @@ wipe_dev() { return fi + echo "" + if wipe_with_nvme "$dev"; then + echo "" + log "Device $dev wiped." + return + fi + + echo "" + if wipe_with_hdparm "$dev"; then + echo "" + log "Device $dev wiped." + return + fi + echo "" if wipe_with_dd "$dev"; then echo "" @@ -171,6 +238,20 @@ wipe_dev() { return fi + echo "" + if wipe_with_ddrescue "$dev"; then + echo "" + log "Device $dev wiped." + return + fi + + echo "" + if wipe_with_dd_rescue "$dev"; then + echo "" + log "Device $dev wiped." + return + fi + die "Wipe failed. The device may not be fully overwritten." }