ddimage 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. #!/bin/sh
  2. #
  3. # SPDX-License-Identifier: GPL-2.0-only
  4. #
  5. # 1MB blocksize
  6. BLOCKSIZE=1048576
  7. usage() {
  8. echo "Usage: $(basename $0) IMAGE DEVICE"
  9. }
  10. image_details() {
  11. IMG=$1
  12. echo "Image details"
  13. echo "============="
  14. echo " image: $(basename $IMG)"
  15. # stat format is different on Mac OS and Linux
  16. if [ "$(uname)" = "Darwin" ]; then
  17. echo " size: $(stat -L -f '%z bytes' $IMG)"
  18. echo " modified: $(stat -L -f '%Sm' $IMG)"
  19. else
  20. echo " size: $(stat -L -c '%s bytes' $IMG)"
  21. echo " modified: $(stat -L -c '%y' $IMG)"
  22. fi
  23. echo " type: $(file -L -b $IMG)"
  24. echo ""
  25. }
  26. device_details() {
  27. BLOCK_SIZE=512
  28. echo "Device details"
  29. echo "=============="
  30. # Collect disk info using diskutil on Mac OS
  31. if [ "$(uname)" = "Darwin" ]; then
  32. diskutil info $DEVICE | egrep "(Device Node|Media Name|Total Size)"
  33. return
  34. fi
  35. # Default / Linux information collection
  36. ACTUAL_DEVICE=`readlink -f $DEVICE`
  37. DEV=`basename $ACTUAL_DEVICE`
  38. if [ "$ACTUAL_DEVICE" != "$DEVICE" ] ; then
  39. echo " device: $DEVICE -> $ACTUAL_DEVICE"
  40. else
  41. echo " device: $DEVICE"
  42. fi
  43. if [ -f "/sys/class/block/$DEV/device/vendor" ]; then
  44. echo " vendor: $(cat /sys/class/block/$DEV/device/vendor)"
  45. else
  46. echo " vendor: UNKNOWN"
  47. fi
  48. if [ -f "/sys/class/block/$DEV/device/model" ]; then
  49. echo " model: $(cat /sys/class/block/$DEV/device/model)"
  50. else
  51. echo " model: UNKNOWN"
  52. fi
  53. if [ -f "/sys/class/block/$DEV/size" ]; then
  54. echo " size: $(($(cat /sys/class/block/$DEV/size) * $BLOCK_SIZE)) bytes"
  55. else
  56. echo " size: UNKNOWN"
  57. fi
  58. echo ""
  59. }
  60. check_mount_device() {
  61. if cat /proc/self/mounts | awk '{ print $1 }' | grep /dev/ | grep -q -E "^$1$" ; then
  62. return 0
  63. fi
  64. return 1
  65. }
  66. is_mounted() {
  67. if [ "$(uname)" = "Darwin" ]; then
  68. if df | awk '{ print $1 }' | grep /dev/ | grep -q -E "^$1(s[0-9]+)?$" ; then
  69. return 0
  70. fi
  71. else
  72. if check_mount_device $1 ; then
  73. return 0
  74. fi
  75. DEV=`basename $1`
  76. if [ -d /sys/class/block/$DEV/ ] ; then
  77. PARENT_BLKDEV=`basename $(readlink -f "/sys/class/block/$DEV/..")`
  78. if [ "$PARENT_BLKDEV" != "block" ] ; then
  79. if check_mount_device $PARENT_BLKDEV ; then
  80. return 0
  81. fi
  82. fi
  83. for CHILD_BLKDEV in `find /sys/class/block/$DEV/ -mindepth 1 -maxdepth 1 -name "$DEV*" -type d`
  84. do
  85. if check_mount_device /dev/`basename $CHILD_BLKDEV` ; then
  86. return 0
  87. fi
  88. done
  89. fi
  90. fi
  91. return 1
  92. }
  93. is_inuse() {
  94. HOLDERS_DIR="/sys/class/block/`basename $1`/holders"
  95. if [ -d $HOLDERS_DIR ] && [ `ls -A $HOLDERS_DIR` ] ; then
  96. return 0
  97. fi
  98. return 1
  99. }
  100. if [ $# -ne 2 ]; then
  101. usage
  102. exit 1
  103. fi
  104. IMAGE=$1
  105. DEVICE=$2
  106. if [ ! -e "$IMAGE" ]; then
  107. echo "ERROR: Image $IMAGE does not exist"
  108. usage
  109. exit 1
  110. fi
  111. if [ ! -e "$DEVICE" ]; then
  112. echo "ERROR: Device $DEVICE does not exist"
  113. usage
  114. exit 1
  115. fi
  116. if [ "$(uname)" = "Darwin" ]; then
  117. # readlink doesn't support -f on MacOS, just assume it isn't a symlink
  118. ACTUAL_DEVICE=$DEVICE
  119. else
  120. ACTUAL_DEVICE=`readlink -f $DEVICE`
  121. fi
  122. if is_mounted $ACTUAL_DEVICE ; then
  123. echo "ERROR: Device $DEVICE is currently mounted - check if this is the right device, and unmount it first if so"
  124. device_details
  125. exit 1
  126. fi
  127. if is_inuse $ACTUAL_DEVICE ; then
  128. echo "ERROR: Device $DEVICE is currently in use (possibly part of LVM) - check if this is the right device!"
  129. device_details
  130. exit 1
  131. fi
  132. if [ ! -w "$DEVICE" ]; then
  133. echo "ERROR: Device $DEVICE is not writable - possibly use sudo?"
  134. usage
  135. exit 1
  136. fi
  137. image_details $IMAGE
  138. device_details
  139. printf "Write $IMAGE to $DEVICE [y/N]? "
  140. read RESPONSE
  141. if [ "$RESPONSE" != "y" ]; then
  142. echo "Write aborted"
  143. exit 0
  144. fi
  145. echo "Writing image..."
  146. if which pv >/dev/null 2>&1; then
  147. pv "$IMAGE" | dd of="$DEVICE" bs="$BLOCKSIZE"
  148. else
  149. dd if="$IMAGE" of="$DEVICE" bs="$BLOCKSIZE"
  150. fi
  151. sync