3cf085c115c0f04d2839da76e9f40431cf61fdff
[project/luci.git] / modules / freifunk / root / usr / sbin / remote-update
1 #!/bin/sh
2
3 local tempfile=/tmp/remote-upgrade.img
4 local D2='\([0-9]\{2\}\)'
5 local D4='\([0-9]\{4\}\)'
6 local NL='
7 '
8
9 find_architecture()
10 {
11         opkg list_installed 'base-files-*' | \
12                 sed -ne 's/base-files-\([^ ]\+\).*/\1/p'
13 }
14
15 find_image()
16 {
17         case "$1" in
18                 atheros)
19                         if grep -q '"vmlinux.bin.l7"' /proc/mtd; then
20                                 echo "openwrt-fonera-combined.img"
21                         else
22                                 echo "openwrt-ubiquity-combined.img"
23                         fi
24                 ;;
25                 brcm-2.4)
26                         echo "openwrt-brcm-2.4-squashfs.trx"
27                 ;;
28         esac
29 }
30
31 check_image()
32 {
33         local file; for file in /lib/upgrade/*.sh; do . $file; done
34         if platform_check_image "$1" >/dev/null 2>/dev/null; then
35                 return 0
36         fi
37         return 1
38 }
39
40 find_remote_checksum()
41 {
42         wget -qO- ${1%/*}/md5sums 2>/dev/null | \
43                 sed -ne '/'$2'/ { s/ .*//p }'
44 }
45
46 find_local_checksum()
47 {
48         set -- $(md5sum "$tempfile")
49         echo $1
50 }
51
52 find_remote_version()
53 {
54         wget -qO- "${1%/*}/VERSION.txt" 2>/dev/null | \
55                 sed -ne "s!.*$D4/$D2/$D2 $D2:$D2.*!\\1\\2\\3\\4\\5!p;t"
56 }
57
58 find_local_version()
59 {
60         if [ -f /rom/etc/banner ]; then
61                 sed -ne "s!.*$D4/$D2/$D2 $D2:$D2.*!\\1\\2\\3\\4\\5!p;t" \
62                         /rom/etc/banner
63         else
64                 date +"%Y%m%d%H%M" -r /bin/sh
65         fi
66 }
67
68 stop_service()
69 {
70         [ -x /etc/init.d/$1 ] && {
71                 echo -n "Stopping service $1 ... "
72                 /etc/init.d/$1 stop >/dev/null 2>/dev/null
73                 echo "done"
74         }
75 }
76
77 do_wait()
78 {
79         if [ ${1:-0} -gt 0 ]; then
80                 echo -n "${2:-Waiting} "
81                 for i in $(seq 1 $1); do
82                         printf "%-2dseconds" $(($1-$i))
83                         sleep 1
84                         echo -en "\b\b\b\b\b\b\b\b\b"
85                 done
86                 echo "${NL}"
87         fi
88 }
89
90 version_compare()
91 {
92         local v1="$1"
93         local v2="$2"
94
95         while [ -n "$v1" -o -n "$v2" ]; do
96                 if [ -z "${v2:0:4}" -o "${v1:0:4}" -gt "${v2:0:4}" ]; then
97                         return 1
98                 elif [ -z "${v1:0:4}" -o "${v1:0:4}" -lt "${v2:0:4}" ]; then
99                         return 2
100                 fi
101
102                 v1="${v1:4}"
103                 v2="${v2:4}"
104         done
105
106         return 0
107 }
108
109 usage()
110 {
111         cat <<EOT
112
113 Usage:
114   remote-update -h
115   remote-update -c
116   remote-update -w
117   remote-update [-d] [-n] [-v] [-y] [-s <sleep seconds>] [-u <update url>]
118
119 Actions:
120   -h    Display this help message and exit.
121   -c    Check for firmware update and exit.
122   -w    Fetch image and exit, do not perform flash write.
123
124 Options:
125   -d    Do not detach from terminal.
126   -n    Do not backup configuration.
127   -v    Skip verification of downloaded image.
128   -y    Assume defaults for all questions.
129
130   -s <seconds>
131     Sleep given amount of seconds before invoking firmware burn.
132     If ommitted and '-y' is not used, 5 seconds are assumed.
133
134   -u <url>
135     Fetch firmware image from given url. A file "md5sums" is expected
136     in the same remote directory. If there is no such file, use -v to
137     suppress verification.
138
139 EOT
140
141         exit 1
142 }
143
144
145 while getopts "s:u:cdnvwyh" flag; do
146         case $flag in
147                 s) sleeptime="$OPTARG";;
148                 u) updateurl="$OPTARG";;
149                 c) checkupdate=1;;
150                 d) nodetach=1;;
151                 n) nobackup=1;;
152                 v) noverify=1;;
153                 w) noflash=1;;
154                 y) noquestions=1;;
155                 *) usage;;
156         esac
157 done
158
159
160 local image_url="$updateurl"
161 local image_name="${image_url##*/}"
162
163 [ -z "$image_url" ] && {
164         local arch=$(find_architecture)
165         local image=$(find_image "$arch")
166         local repo=$(uci get freifunk.upgrade.repository 2>/dev/null)
167
168         [ -z "$arch" ] && {
169                 echo "Can not determine the current architecture."
170                 exit 1
171         }
172
173         [ -z "$repo" ] && {
174                 echo "No repository configured in 'freifunk.upgrade.repository'."
175                 echo "Use the '-u' flag to specify an image location."
176                 exit 1
177         }
178
179         [ -z "$image" ] && {
180                 echo "No suitable image for the '$arch' architecture."
181                 echo "Your platform is not supported."
182                 exit 1
183         }
184
185         echo "Architecture: $arch"
186         echo "Repository:   $repo"
187
188         image_name="$image"
189         image_url="${repo%/}/$arch/$image"
190 }
191
192
193 if [ "$checkupdate" = 1 ]; then
194         local v1=$(find_local_version)
195         local v2=$(find_remote_version "$image_url")
196
197         [ -n "$v1" -a -n "$v2" ] && {
198                 version_compare "$v1" "$v2"
199                 [ $? == 2 ] && {
200                         echo "Update available! $v1 -> $v2"
201                 } || {
202                         echo "Local version $v1 is up to date"
203                 }
204         } || {
205                 echo "No remote time stamp found."
206                 exit 1
207         }
208 else
209         if [ "$noquestions" != 1 ]; then
210                 echo -n "${NL}About to download $image_name. Continue? [y] "
211                 read answer
212                 case "$answer" in
213                         [nN]) exit 1;;
214                 esac
215         fi
216
217         echo -n "Downloading $image_name ... "
218         rm -f $tempfile
219         wget -qO $tempfile "$image_url" 2>/dev/null
220         [ $? == 0 ] && echo done || {
221                 echo failed
222                 rm -f $tempfile
223                 exit 1
224         }
225
226         if [ "$noverify" != 1 ]; then
227                 echo -n "Verifying $image_name ... "
228
229                 local md5_remote=$(find_remote_checksum "$image_url" "$image_name")
230                 local md5_local=$(find_local_checksum)
231
232                 check_image "$tempfile"
233                 local image_ok=$?
234
235                 if [ $image_ok = 0 -a -n "$md5_remote" -a -n "$md5_local" -a "$md5_remote" = "$md5_local" ]; then
236                         echo "done"
237                 else
238                         if [ $image_ok != 0 ]; then
239                                 echo "unsupported image type"
240                         else
241                                 echo "checksum mismatch! (local:${md5_local:-(none)} remote:${md5_remote:-(none)})"
242                         fi
243
244                         local answer=n
245                         if [ "$noquestions" != 1 ]; then
246                                 echo -n "${NL}Verification failed. Continue anyway? [n] "
247                                 read answer
248                         fi
249
250                         case "$answer" in
251                                 [yYjJ]*) : ;;
252                                 *)
253                                         echo "Aborting."
254                                         rm -f $tempfile
255                                         exit 1
256                                 ;;
257                         esac
258                 fi
259         fi
260
261         if [ "$noflash" != 1 ]; then
262                 if [ -f "$tempfile" ]; then
263                         if [ "$noquestions" == 1 ]; then
264                                 do_wait ${sleeptime:-5} "${NL}About to start flashing, hit <Ctrl-C> to abort!${NL}${NL}Starting in"
265                         else
266                                 if [ -z "$nobackup" ]; then
267                                         echo -n "${NL}Keep configuration files? [y] "
268                                         read answer
269                                         case "$answer" in
270                                                 [nN]) nobackup=1;;
271                                         esac
272                                 fi
273
274                                 echo -n "${NL}About to start flashing!${NL}Hit <Enter> to continue or <Ctrl-C> to abort.${NL}"
275                                 read answer
276                         fi
277
278                         for s in lucid collectd; do stop_service $s; done
279
280                         if [ "$nodetach" != 1 ]; then
281                                 echo -n "Starting sysupgrade in background ... "
282                                 /bin/busybox start-stop-daemon -S -b -x /sbin/sysupgrade -- ${nobackup:+-n} "$tempfile"
283                                 echo "done"
284                         else
285                                 echo "Executing sysupgrade ... "
286                                 exec /sbin/sysupgrade ${nobackup:+-n} "$tempfile"
287                         fi
288                 else
289                         echo "No upgrade image found!"
290                         exit 1
291                 fi
292         else
293                 echo "Image saved in '$tempfile'"
294         fi
295 fi