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