The blacklist, whilst previously useful for safety, is now becoming obsolete - on my current system, the main storage is at /dev/nvme* and if I plug in a USB stick it shows up as /dev/sdb which was previously blacklisted. To make this more flexible, remove the blacklist and instead check if the specified device is mounted, has a partition that is mounted, or is otherwise in use according to the kernel, and show an appropriate error and quit if so. To make this robust, also ensure we handle where the specified device is a symlink to another device. (From OE-Core rev: 49043de1a7716ad612fb92a2e8a52e43d253c800) Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
3.5 KiB
Executable File
#!/bin/sh
SPDX-License-Identifier: GPL-2.0-only
1MB blocksize
BLOCKSIZE=1048576
usage() { echo "Usage: $(basename $0) IMAGE DEVICE" }
image_details() { IMG=$1 echo "Image details" echo "=============" echo " image: $(basename $IMG)" # stat format is different on Mac OS and Linux if [ "$(uname)" = "Darwin" ]; then echo " size: $(stat -L -f '%z bytes' $IMG)" echo " modified: $(stat -L -f '%Sm' $IMG)" else echo " size: $(stat -L -c '%s bytes' $IMG)" echo " modified: $(stat -L -c '%y' $IMG)" fi echo " type: $(file -L -b $IMG)" echo "" }
device_details() { BLOCK_SIZE=512
echo "Device details"
echo "=============="
# Collect disk info using diskutil on Mac OS
if [ "$(uname)" = "Darwin" ]; then
diskutil info $DEVICE | egrep "(Device Node|Media Name|Total Size)"
return
fi
# Default / Linux information collection
ACTUAL_DEVICE=`readlink -f $DEVICE`
DEV=`basename $ACTUAL_DEVICE`
if [ "$ACTUAL_DEVICE" != "$DEVICE" ] ; then
echo " device: $DEVICE -> $ACTUAL_DEVICE"
else
echo " device: $DEVICE"
fi
if [ -f "/sys/class/block/$DEV/device/vendor" ]; then
echo " vendor: $(cat /sys/class/block/$DEV/device/vendor)"
else
echo " vendor: UNKNOWN"
fi
if [ -f "/sys/class/block/$DEV/device/model" ]; then
echo " model: $(cat /sys/class/block/$DEV/device/model)"
else
echo " model: UNKNOWN"
fi
if [ -f "/sys/class/block/$DEV/size" ]; then
echo " size: $(($(cat /sys/class/block/$DEV/size) * $BLOCK_SIZE)) bytes"
else
echo " size: UNKNOWN"
fi
echo ""
}
check_mount_device() { if cat /proc/self/mounts | awk '{ print $1 }' | grep /dev/ | grep -q -E "^$1$" ; then return 0 fi return 1 }
is_mounted() {
if [ "$(uname)" = "Darwin" ]; then
if df | awk '{ print $1 }' | grep /dev/ | grep -q -E "^$1(s[0-9]+)?$" ; then
return 0
fi
else
if check_mount_device $1 ; then
return 0
fi
DEV=basename $1
if [ -d /sys/class/block/$DEV/ ] ; then
PARENT_BLKDEV=basename $(readlink -f "/sys/class/block/$DEV/..")
if [ "$PARENT_BLKDEV" != "block" ] ; then
if check_mount_device $PARENT_BLKDEV ; then
return 0
fi
fi
for CHILD_BLKDEV in find /sys/class/block/$DEV/ -mindepth 1 -maxdepth 1 -name "$DEV*" -type d
do
if check_mount_device /dev/basename $CHILD_BLKDEV ; then
return 0
fi
done
fi
fi
return 1
}
is_inuse() {
HOLDERS_DIR="/sys/class/block/basename $1/holders"
if [ -d $HOLDERS_DIR ] && [ ls -A $HOLDERS_DIR ] ; then
return 0
fi
return 1
}
if [ $# -ne 2 ]; then usage exit 1 fi
IMAGE=$1 DEVICE=$2
if [ ! -e "$IMAGE" ]; then echo "ERROR: Image $IMAGE does not exist" usage exit 1 fi
if [ "$(uname)" = "Darwin" ]; then
# readlink doesn't support -f on MacOS, just assume it isn't a symlink
ACTUAL_DEVICE=$DEVICE
else
ACTUAL_DEVICE=readlink -f $DEVICE
fi
if is_mounted $ACTUAL_DEVICE ; then
echo "ERROR: Device $DEVICE is currently mounted - check if this is the right device, and unmount it first if so"
device_details
exit 1
fi
if is_inuse $ACTUAL_DEVICE ; then
echo "ERROR: Device $DEVICE is currently in use (possibly part of LVM) - check if this is the right device!"
device_details
exit 1
fi
if [ ! -w "$DEVICE" ]; then echo "ERROR: Device $DEVICE does not exist or is not writable" usage exit 1 fi
image_details $IMAGE device_details
printf "Write $IMAGE to $DEVICE [y/N]? " read RESPONSE if [ "$RESPONSE" != "y" ]; then echo "Write aborted" exit 0 fi
echo "Writing image..." if which pv >/dev/null 2>&1; then pv "$IMAGE" | dd of="$DEVICE" bs="$BLOCKSIZE" else dd if="$IMAGE" of="$DEVICE" bs="$BLOCKSIZE" fi sync