1

/path/to/directory/ is a path that points within an encrypted volume, to an arbitrary depth. In a bash script I need to determine if the block device related to this path is a removable device. I'm using Arch Linux.

I have looked at a lot of similar questions (such as these listed below and others) but did not find a suitable answer:

This is an example of what I'm working with:

findmnt -n -o SOURCE --target /path/to/directory/
/dev/mapper/luksdev[/@subvolume]

findmnt -D --target /path/to/directory
SOURCE                         FSTYPE  SIZE   USED AVAIL USE% TARGET
/dev/mapper/luksdev[/@subvolume] btrfs   4.5T 203.5G  4.3T   4% /path/to/directory

df -P /path/to/directory/ | awk 'END{print $1}'
/dev/mapper/luksdev

(The findmnt parameter --target seems to be required if the path is not the exact mountpoint.)

If the script can determine the block device (e.g., /dev/sda1) associated with /dev/mapper/luksdev, I get a step closer:

udevadm info --query=all --name=/dev/sda1 | grep ID_BUS | grep "=usb"
E: ID_BUS=usb

But I assume not all removable devices are usb, right?

By the way, I am OK with methods specific to BTRFS, if that makes this any easier. I did check:

btrfs - Find physical block device of root filesystem on an encrypted filesystem? - Unix & Linux Stack Exchange

EDIT: based on answer by Vojtech Trefny, here is what I have:

mapper_path=$(findmnt -n -o SOURCE --target /path/to/directory/ | cut -d [ -f 1)
mydev=$(lsblk -sl -o NAME /${mapper_path} | tail -n 1)
drive_name=$(udisksctl info -b /dev/${mydev} | grep "Drive:" | cut -d"'" -f2)
drive_name=$(echo $drive_name | sed -e 's|/org/freedesktop/UDisks2/drives/||')
udisksctl info -d ${drive_name} | grep "\sRemovable:" | cut -d":" -f2 | tr -d "[:blank:]"
MountainX
  • 17,168
  • 59
  • 155
  • 264

1 Answers1

3

From the /dev/mapper path, the easiest way to get the disk name should be lsblk with -s to list devices in inverse order:

$ lsblk -sl -o NAME /dev/mapper/<name> | tail -1
sda

Easiest way from here is probably to check removable property from sysfs

$ cat /sys/block/sda/removable
0

but I'd recommend using UDisks here, it does some extra checks on top of the sysfs information so I assume sysfs can be wrong about some removable devices. You can either use busctl to communicate with UDisks over DBus or udisksctl and grep from the output.

$ busctl get-property org.freedesktop.UDisks2 /org/freedesktop/UDisks2/block_devices/sda org.freedesktop.UDisks2.Block Drive 
o "/org/freedesktop/UDisks2/drives/<drive_name>"

$ busctl get-property org.freedesktop.UDisks2 /org/freedesktop/UDisks2/drives/<drive_name> org.freedesktop.UDisks2.Drive Removable 
b false

or

$ udisksctl info -b /dev/sda | grep "Drive:" | cut -d"'" -f2
/org/freedesktop/UDisks2/drives/<drive_name>

$ udisksctl info -d <drive_name> | grep "\sRemovable:" | cut -d":" -f2 | tr -d "[:blank:]"
false
Vojtech Trefny
  • 16,922
  • 6
  • 24
  • 48
  • Very helpful. Thank you. Unfortunately, when using either `busctl` or `udisksctl` I get the error `Error looking up object for drive /org/freedesktop/UDisks2/drives/SanDisk_Cruzer_Blade_XYZ123456789`. If I use `/sys/block/sdX/removable` it does give the expected value of `1` for USB sticks, but for a removable USB HDD (WD Elements) it reports 0. – MountainX Oct 10 '20 at 07:20
  • 1
    @MountainX that's because it's not removable. You can't the platter and change it with another ;-) What you're asking for is impossible. You can only make "educated" guesses (USB -> "removable", etc). –  Oct 10 '20 at 07:31
  • @MountainX `realpath /sys/block/sda` will tell you the full path to the device. Starting from there, you can make some guesses. –  Oct 10 '20 at 07:41
  • @MountainX Is the drive visible in `udisksctl dump`? If the `sda` object says the drive is `/org/freedesktop/UDisks2/drives/SanDisk_Cruzer_Blade_XYZ123456789` and then the drive object is not there, that's a bug in UDisks, unfortunately. – Vojtech Trefny Oct 10 '20 at 07:47
  • 1
    @VojtechTrefny: I figured the issue out, and accepted your answer. See edit in my question for details. – MountainX Oct 10 '20 at 08:14