10 Commits

Author SHA1 Message Date
matmoul ab346342d5 docs: update usage and shell style conventions 2026-04-28 01:03:19 +02:00
matmoul bf9cbe918f chore: remove VS Code ignore rules 2026-04-28 00:35:05 +02:00
matmoul 62ac956836 fix: reorder wipe method fallback sequence 2026-04-28 00:33:27 +02:00
matmoul 07c210164a feat: add optional wipe tool fallbacks by device type 2026-04-28 00:28:50 +02:00
matmoul c56aec350d docs: tighten project conventions for mtm-ddwipe 2026-04-27 23:46:51 +02:00
matmoul 956cfd7325 fix: tighten mtm-ddwipe usage and device checks
Add an explicit mounted-device check with findmnt, shorten confirmation prompts, and align the usage text and log wording with the current script name.
2026-04-27 23:40:28 +02:00
matmoul 55c55a4a08 feat: strengthen wipe safety checks and confirmation flow
Add mounted/in-use device detection, show detailed device info before confirmation, and require an exact wipe phrase to proceed. Also move status output to stderr and refresh the usage warnings for clearer destructive-action guidance.
2026-04-27 23:37:40 +02:00
matmoul ecc6e5b038 fix: harden mtm-ddwipe confirmation and wipe flow
Add strict shell options, root and block-device validation, and a typed-device confirmation prompt before wiping. Preserve the fallback wipe sequence through secure discard, zero discard, and dd, while tightening error handling and keeping messages concise.
2026-04-27 23:32:45 +02:00
matmoul 7011426381 docs: clarify mtm-ddwipe safety and prompt conventions 2026-04-27 23:20:07 +02:00
matmoul b01e72cba6 fix: improve mtm-ddwipe argument handling and timing output 2026-04-27 23:17:16 +02:00
4 changed files with 285 additions and 108 deletions
+23 -16
View File
@@ -3,23 +3,30 @@ description: mtm-ddwipe project conventions
--- ---
# Project conventions # Project conventions
- Use English throughout the project. - Use English.
- Keep shell scripts Bash-based when Bash is already used by the project. - Use Bash for shell scripts.
- Preserve the current behavior of the main script: - Keep `mtm-ddwipe` focused on wiping block devices.
- `mtm-ddwipe`: wipe devices. - Keep `mtm-ddwipe` interactive by default.
- Strengthen destructive-action safety checks in `mtm-ddwipe` when making changes. - Require explicit confirmation before destructive actions.
- Keep `mtm-ddwipe` interactive by default unless a change explicitly adds a safe opt-in flag. - Validate real block devices and refuse mounted or in-use targets.
- Keep user-facing messages short, clear, and in English. - Show clear device details before confirmation.
- Prefer minimal, focused changes that do not alter the intent of the existing scripts, unless the script behavior is intentionally updated. - Keep destructive safeguards strict and explicit.
- Maintain `.continue/rules/project.md` whenever project conventions or script behavior change. - Keep messages short and clear.
- `mtm-ddwipe` is a small Bash script with helper functions. - Keep help concise, usage-first, and warning-focused.
- Keep the host and line-number removal behavior intact. - Preserve the fallback wipe flow: secure discard, zero discard, then `dd` zero-fill.
- `mtm-ddwipe` must print a usage line and support `-h`/`--help`. - Keep optional tools optional.
- Validate that wipe targets are real block devices before operating on them. - Use extra wipe methods only if the command is present.
- Keep short, explicit confirmation prompts before destructive operations. - Use `ddrescue` or `dd_rescue` only after `dd` fails.
- Keep error and help messages short, clear, and in English. - Keep `nvme` and `hdparm` optional.
- Keep help text concise and usage-first. - Use `nvme` and `hdparm` only on matching device types.
- Do not make new external tools required.
- Keep changes minimal and preserve intent.
- Keep this file aligned and concise.
- Prefer tabs for indentation.
- Prefer `${var}` notation in Bash.
- If non-interactive support is added, make it an opt-in safety flag.
# Project identity # Project identity
- Main script: `mtm-ddwipe` - Main script: `mtm-ddwipe`
- License: GNU GPL v3 - License: GNU GPL v3
-14
View File
@@ -1,14 +0,0 @@
# ---> VisualStudioCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/*.code-snippets
# Local History for Visual Studio Code
.history/
# Built Visual Studio Code Extensions
*.vsix
+17
View File
@@ -1,2 +1,19 @@
# mtm-ddwipe # mtm-ddwipe
Wipe a block device.
Warning: destructive and irreversible.
Target must be a real block device, not mounted, and not in use.
Usage:
mtm-ddwipe DEVICE
mtm-ddwipe -h | --help
Options:
-h, --help Show help.
Notes:
- Interactive by default.
- Confirm exactly before wiping.
- Optional tools: blkdiscard, ddrescue, dd_rescue, nvme, hdparm.
Executable → Regular
+235 -68
View File
@@ -1,104 +1,271 @@
#!/bin/bash #!/bin/bash
set -euo pipefail
IFS=$'\n\t'
declare -r DEV="${1}" VERSION="0.0.4"
declare STARTDATE="" STARTDATE=0
declare STARTDATESTRING="" STARTDATESTRING=""
show_help() { usage() {
echo "Usage: mtm-ddwipe DEVICE" cat <<EOF
echo "" Usage: mtm-ddwipe DEVICE
echo "Wipe a block device."
echo "Version: 0.0.3" Wipe a block device.
Warnings:
- Destructive and irreversible.
- Target must be a real block device, not mounted, and not in use.
- Optional tools: blkdiscard, ddrescue, dd_rescue, nvme, hdparm.
- dd fallback may take a long time.
Version: ${VERSION}
EOF
}
log() {
echo "$*" >&2
}
die() {
echo "Error: $*" >&2
exit 1
} }
check_args() { check_args() {
case "${1}" in if [ $# -ne 1 ]; then
case "${1:-}" in
-h|--help) -h|--help)
show_help usage
exit 0 exit 0
;; ;;
"") "")
show_help usage
exit 1 exit 1
;; ;;
-*)
die "Invalid option."
;;
esac esac
}
check_dev_exist() { usage
if [ ! -e "${1}" ]; then
echo "Missing device."
exit 1 exit 1
fi fi
} }
check_dev_block() { check_device() {
if [ ! -b "${1}" ]; then local dev="${1}"
echo "Not a block device."
exit 1 [ -e "${dev}" ] || die "Missing device: ${dev}"
[ -b "${dev}" ] || die "Not a block device: ${dev}"
}
check_device_not_in_use() {
local dev="${1}"
if findmnt -rn --target "${dev}" >/dev/null 2>&1; then
die "Device is mounted: ${dev}"
fi fi
if lsblk -nrpo NAME,MOUNTPOINT "${dev}" | awk '$2 != "" { found=1 } END { exit !found }'; then
die "Device or child is mounted: ${dev}"
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() { confirm_wipe() {
lsblk "${1}" local dev="${1}"
local choice=""
echo "Device:"
lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINT,MODEL,SERIAL "${dev}"
echo ""
echo "Type exactly: WIPE ${dev}"
read -r -p "Confirm: " choice
[ "${choice}" = "WIPE ${dev}" ] || die "Canceled"
echo "" echo ""
read -r -p "Wipe ${1} (y/[n])? " CHOICE
case "${CHOICE}" in
y|Y ) echo "";;
* )
echo "Canceled"
exit 1
;;
esac
} }
wipe_dev() { confirm_root() {
STARTDATE=$(date +%s) if [ "${EUID:-$(id -u)}" -ne 0 ]; then
STARTDATESTRING="$(date)" die "This tool must be run as root."
echo "Begin wiping device ${1}"
echo ""
echo "Start date :"
echo "${STARTDATESTRING}"
echo ""
echo "blkdiscard secure"
if ! blkdiscard -f -p 500M -s -v "${1}"; then
echo ""
echo "blkdiscard zero"
if ! blkdiscard -f -p 500M -z -v "${1}"; then
echo ""
echo "dd zero"
if ! dd if=/dev/zero of="${1}" bs=1M status=progress; then
# Need check if dd has all writed, if yes, return no error
# echo "Error wiping device ${1}, use phisical destroy !"
echo "Wiped with dd, check if full size is writed."
echo "Otherwise use a mechanical destruction of the device."
print_time
exit 1
fi fi
fi }
fi
echo "" format_duration() {
echo "Device ${1} wiped." local total="${1}"
local hours minutes seconds
hours=$((total / 3600))
minutes=$(((total % 3600) / 60))
seconds=$((total % 60))
printf '%02d:%02d:%02d\n' "${hours}" "${minutes}" "${seconds}"
} }
print_time() { print_time() {
echo "" local enddate calctime
echo "Start date :"
echo "${STARTDATESTRING}"
ENDDATE=$(date +%s)
echo "" echo ""
echo "End date :" log "Start date :"
date log "${STARTDATESTRING}"
enddate=$(date +%s)
calctime=$((enddate - STARTDATE))
CALCTIME=$((ENDDATE-STARTDATE))
echo "" echo ""
echo "Total time :" log "End date :"
date -d@${CALCTIME} -u +%H:%M:%S date >&2
echo ""
log "Total time :"
format_duration "${calctime}" >&2
} }
check_args "${DEV}" wipe_with_blkdiscard_secure() {
check_dev_exist "${DEV}" local dev="${1}"
check_dev_block "${DEV}"
confirm_wipe "${DEV}" log "blkdiscard secure"
wipe_dev "${DEV}" blkdiscard -f -p 500M -s -v "${dev}"
}
wipe_with_blkdiscard_zero() {
local dev="${1}"
log "blkdiscard zero"
blkdiscard -f -p 500M -z -v "${dev}"
}
wipe_with_dd() {
local dev="${1}"
log "dd zero"
dd if=/dev/zero of="${dev}" bs=1M status=progress conv=fsync
}
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() {
local dev="${1}"
STARTDATE=$(date +%s)
STARTDATESTRING="$(date)"
log "Begin wiping: ${dev}"
echo ""
log "Start date :"
log "${STARTDATESTRING}"
echo ""
if wipe_with_blkdiscard_secure "${dev}"; then
echo ""
log "Device ${dev} wiped."
return
fi
echo ""
if wipe_with_blkdiscard_zero "${dev}"; then
echo ""
log "Device ${dev} wiped."
return
fi
echo ""
if wipe_with_dd "${dev}"; then
echo ""
log "Device ${dev} wiped."
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
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
die "Wipe failed. The device may not be fully overwritten."
}
main() {
check_args "$@"
confirm_root
check_device "${1}"
check_device_not_in_use "${1}"
confirm_wipe "${1}"
wipe_dev "${1}"
print_time print_time
}
main "$@"