henry_flower: A melancholy wolf (Default)
henry_flower ([personal profile] henry_flower) wrote2026-01-03 05:13 am

Фільтрування removable драйвів

Хотів звільнити usb драйва від лайнаксних gpt партішонів, щоб заформатувати потім його ув віндюку, і отримав ось це:

$ sudo fdisk -l /dev/sdi
Disk /dev/sdi: 112.64 GiB, 120945901568 bytes, 236222464 sectors
Disk model: Transcend 128GB
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x00000000

Device     Boot      Start        End    Sectors  Size Id Type
/dev/sdi1       4294967295 8589934589 4294967295    2T ff BBT
/dev/sdi2       4294967295 8589934589 4294967295    2T ff BBT
/dev/sdi3       4294967295 8589934589 4294967295    2T ff BBT
/dev/sdi4       4294967295 6854241533 2559274239  1.2T ff BBT

Виявляється, як видаляти все через копіювання /dev/zero на перший та останній МБ, віндюка побачить відсутність партішонів і, ув якості помсти, зробить superfloppy. Супер-шо?

'Removable media without either GPT or MBR formatting is considered a "superfloppy". The entire media is treated as a single partition.'

(З майкрософтських питань-відповідей про gpt.)

Щоб цього не сталосі (і ув fdisk не їхав дах) треба заздалегідь мати

$ lsblk /dev/sdi
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
sdi      8:128  1 120.3M  0 disk
└─sdi1   8:129  1 119.3M  0 part

Я спитав себе чому за стільки років не маю скрипта який би робив очищення та 'правільно' заформатовував дівайса, а замість того кожного разу гооглю офсети для dd. Цікавого там є 0, кожний читач може написати те коректно самотужки, але що мені не подобається ув таких скриптах і чого я боюся, це те, що слухаючи сирену, я можу випадково передати їм ім'я не usb драйву, а внутрішнього ssd, і тоді Smokey, my friend, you're entering a world of pain.

Перевірити ув лайнаксі чи є блоковий носій знімним, можна подивившись ув файла /sys/block/XXX/removable. Тоді, проітерувавши все з /sys/block/, стає легко відфільтрувати непотрібне. Якщо такий шелóвий скрипта намалює список зі usb-драйвів користувачу, останній зможе безпечно вибрати потрібний, а перший надрукує результат вибору для наступної аплікації:

$ ./blockdevrem-select | xargs sudo ./blockdevrem-wipe

Тобто, скрипта, який небезпечно маніпулює байтами на дівайсі, нічого не знає про нутрощі скрипта який дозволяє дівайса вибрати. Запускати другий без першого зазвичай немає потреби.

Віджет меню ув dialog(1) очікує парного числа параметрів, але у нас вони можуть містити пробіли, тому як не використовувати баша з його масивами, доведеться змінювати IFS.

$ cat blockdevrem-select
#!/bin/sh

eh() { echo "blockdevrem-select error: $*" 1>&2; exit 1; }

test -d /sys/block || eh /sys/block is not a directory
command -v dialog >/dev/null || eh 'no dialog(1)'

# shellcheck disable=2012
removables() {
    ls -1 /sys/block | while read -r name; do
        [ "`cat /sys/block/"$name"/removable`" = 1 ] &&
            [ "`cat /sys/block/"$name"/size`" != 0 ] &&
            desc "$name"
    done
}

US=`printf '\037'`

desc() {
    cat "/sys/block/$1/device/vendor" "/sys/block/$1/device/model" | xargs |
        xargs -0 printf "%s$US%s$US" "/dev/$1"
}

dev=`removables`; [ "$dev" = "" ] && eh no USB drives

reply=`mktemp`
trap 'rm -f $reply' 0 1 2 15
exec 3> "$reply"

IFS=$US
dialog --output-fd 3 --title -- "${1:-Select a removable drive}" --keep-tite \
       --menu "${2:-}" 0 0 0 $dev 1>&2 &&
    cat "$reply"