Files
poky/scripts/contrib/ddimage
Paul Eggleton d3a9f43305 scripts/contrib/ddimage: replace blacklist with mount check
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>
2019-07-03 17:00:57 +01:00

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