-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathsdrestore
executable file
·190 lines (165 loc) · 4.88 KB
/
sdrestore
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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#!/bin/bash
#--------------------------------------------------------------------------------
# SDRestore
# A script to decompress and restore an image onto a device such as an SD Card
#--------------------------------------------------------------------------------
# Daniel Bull
#------------------------------------------------------------------------------*/
# Settings
THISAPP=sdrestore
TEMPFOLDER=/tmp/sdbackup
SETTINGSFILE=~/.sdbackup
DEFAULTDEV=""
# Automatically install what we need
if [[ ! `type -P "unp"` || ! `type -P "ddrescue"` || ! `type -P "lshw"` ]]; then
echo "It looks like this is the first time $THISAPP has been run."
echo "Installing required packages..."
echo
sudo apt-get install unp gddrescue lshw || { echo "Error: Please install unp, gddrescue and lshw" 1>&2; exit 1;}
echo "Done..."
echo
fi
# Create the temporary folder if it doesn't already exist
if [[ ! -d "$TEMPFOLDER" ]]; then
mkdir "$TEMPFOLDER" || { echo "Error: Cannot create temporary folder" 1>&2; exit 1; }
fi
# Check filename parameter is present
if [[ "$1" = "" ]]; then
echo "Usage: $THISAPP <filename> [<device>]" 1>&2
exit
fi
# Check the source file exists
FILE="$1"
if [[ ! -f "$FILE" ]]; then
# Try with a .gz extension
if [[ ! -f "$FILE.gz" ]]; then
echo "Error: $1 doesnt exist?" 1>&2
exit 1
fi
FILE+=".gz"
fi
# Get a device name
if [[ "$2" != "" ]]; then
# Supplied on CLI
DEV="$2"
else
# Get the default
if [[ -f "$SETTINGSFILE" ]]; then
DEFAULTDEV=`cat "$SETTINGSFILE"`
fi
# Scan for disks
echo "Scanning drives..."
declare -a DEVICES
declare -a SIZES
declare -a NAMES
DEVICE=0;
while read LINE; do
if grep -q 'description: ' <<< "$LINE"; then
DEVICE=$((DEVICE+1))
DEVICES[$DEVICE]=""
SIZES[$DEVICE]=""
NAMES[$DEVICE]=""
elif grep -q 'logical name: ' <<< "$LINE"; then
DEVICES[$DEVICE]="`cut -d':' -f2 <<< $LINE`"
elif grep -q 'size:' <<< "$LINE"; then
SIZES[$DEVICE]+="`cut -d':' -f2 <<< $LINE`"
elif grep -q 'product: ' <<< "$LINE"; then
NAMES[$DEVICE]+="`cut -d':' -f2 <<< $LINE`"
fi
done < <(sudo lshw -class disk 2> /dev/null)
# Display a list of options
echo
DEFAULTSELECT=0
for I in "${!DEVICES[@]}"; do
if [[ "${SIZES[$I]}" ]]; then
echo "$I) ${DEVICES[$I]} ${NAMES[$I]}${SIZES[$I]}"
else
echo "$I) ${DEVICES[$I]} ${NAMES[$I]} (currently empty)"
fi
if [[ "${DEVICES[$I]:1}" = "$DEFAULTDEV" ]]; then
DEFAULTSELECT=$I
fi
done
echo "0) Cancel"
# Ask the user to select
echo
DEV=""
while ! [[ "$DEV" ]]; do
read -p "Please select your device [$DEFAULTSELECT]: " SELECTED
if ! [[ "$SELECTED" ]]; then
SELECTED=$DEFAULTSELECT
fi
if [[ "$SELECTED" = 0 ]]; then
exit;
fi
if [[ "$SELECTED" =~ ^[01234567890]$ ]]; then
DEV="${DEVICES["$SELECTED"]:1}"
fi
done
fi
# Check the device exists
if [[ ! -b "$DEV" ]]; then
echo "Error: $DEV is not a block device?" 1>&2
exit 1;
fi
# Confirm
read -p "Restore from $FILE to $DEV is that correct? [y/N]: " -n1 AGREE
if ! [[ "$AGREE" =~ ^[yY]$ ]]; then
exit
fi
echo
echo
# Filenames
LOCKFILE="$TEMPFOLDER/`echo "$DEV" | tr "/" "_"`.lock"
TEMPFILE="$TEMPFOLDER/`echo "$FILE_$DEV" | tr "/" "_"`.tempfile"
ERRFILE="$TEMPFOLDER/`echo "$FILE_$DEV" | tr "/" "_"`.error"
# Test and create lockfile
if [[ -f $LOCKFILE ]]; then
echo "Error: There is a `cat $LOCKFILE` currently running on $DEV" 1>&2;
exit 1;
fi
echo $THISAPP > $LOCKFILE
# Trap for failure
trap 'rm "$LOCKFILE" 2> /dev/null; rm "$TEMPFILE" 2> /dev/null; rm "$ERRFILE" 2> /dev/null' EXIT
# Clean up anything left over from a previous attempt
sudo rm "$TEMPFILE" 2> /dev/null
sudo rm "$ERRFILE" 2> /dev/null
# Unmount the card
echo "Unmounting any mounted partitions..."
for PARTITION in "$DEV"*; do
if [[ -b "$PARTITION" ]]; then
if egrep -qs ^"$PARTITION " /proc/mounts; then
sudo umount "$PARTITION" 2> /dev/null || { echo "Error: Cannot unmount $PARTITION" 1>&2; exit 1; }
fi
fi
done
# See if the file needs decompressing
if [[ "`file \"$FILE\" | grep 'compressed\|archive'`" ]]; then
# Decompress the file
echo "Decompressing..."
ucat "$FILE" > "$TEMPFILE" 2> "$ERRFILE" || { echo "Error: Cannot decompress $FILE" 1>&2; exit 1; }
if [[ -s "$ERRFILE" ]]; then
echo "Error: Cannot decompress $FILE" 1>&2;
exit 1;
fi
RESTOREFILE="$TEMPFILE"
else
# No temp file needed
RESTOREFILE="$FILE"
fi
# Check its not still compressed
if [[ "`file \"$RESTOREFILE\" | grep 'compressed\|archive'`" ]]; then
echo "Error: Cannot decompress $FILE" 1>&2;
exit 1;
fi
# Restore the file
echo "Restoring "`ls -lah "$RESTOREFILE" | awk -F " " {'print $5'}`" to $DEV..."
echo
sudo ddrescue --force --synchronous "$RESTOREFILE" "$DEV" || exit 1;
echo
echo "Syncing the card ready for ejection..."
sync
echo "Restore complete."
# Set device as default
echo "$DEV" > "$SETTINGSFILE"