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