hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#!/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 [ ! -e "$DEVICE" ]; then
   echo "ERROR: Device $DEVICE 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 is not writable - possibly use sudo?"
   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