-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathupdate
543 lines (464 loc) · 18.2 KB
/
update
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
#!/usr/bin/perl
#
# This script is for use with the Open Glider Network FLARM Detection System only
# Any other uses are NOT authorised
#
# Code has been sponsored by Temeletry Limited (http://www.temeletry.co.uk)
#
# Copyright (c) 2014, Melissa Jenkins, Temeletry Limited ([email protected])
#
use strict;
use File::Copy;
use File::stat;
use Cwd;
# to make sure the file was downloaded properly
# md5sum 57b80f87891f936b9dcd3f38edee7722 RmeupofZYXEIBjkLLbQuxblRB91JL4szA6tTylb4gkggYUJ3YDt1uazxHK7/HmAYlBjcZq+wgrFvqifD9TFB1nl3JBacSmvE5hpp9M+Csbd9kWrYx4xxOBcGO3cns53bG2nHKiD9nkFfhbQ5O71gujXZ4KhCxmydT/zrOK0zrgNYkhQWgBvID78vwl+WRPRg+2w2vyjTr0iOFCgDJCnhxXzoCkC57o3R7mfXc0P22nRhm2P3FOGdo//mzdX6GGaiE5YKq+ufhKn6rimCVqfkn8uc5zY6L4J26/sZDoIAfSQuC6E1zd+uzHFsrtZNg+0YUvnL6DTA8W5Zzof5M7KOrA==
my $version='2.1a';
my $old_handle = select (STDOUT);
$| = 1; # perform flush after each write to STDOUT
select ($old_handle);
my $scriptname = $0;
if( ! ($scriptname =~ m|^/| )) {
$scriptname = cwd() . "/".$0;
$scriptname =~ s|/./|/|;
}
# do they want help?
if( $ARGV[0] =~ '[-]+h' ) {
print "$scriptname - OGN Updater v$version\n\n".
" -r reboot after running. If installing this will tell the crontab to issue a reboot \n".
" after it has checked for updates. Service will not be restarted till after it boots.\n".
" -i Do not start the service when done.\n".
" -t Test, print what path, user and configuration file is being worked on.\n";
exit 1;
}
if( $> != 0 ) {
die "You need to run this as root, or use sudo";
}
# The image version was not good and would sit waiting for a LONG time, use the one from 1.3
my $startupepoch = 1429006250; # on linux date -d '10/25/2014' '+%s', on bsd date -f '%m/%d/%Y' -j '+%s' '1/1/2000'
# old style tokens
if( -e '/home/pi/sitetoken.txt' ) {
move( '/home/pi/sitetoken.txt', '/etc/sitetoken.txt' );
}
# keep the same site id for the whole thing
my $token; my $aprscall = '*early';
if( ! -e "/etc/sitetoken.txt" ) {
my $code = qx( /bin/dd if=/dev/urandom bs=1 count=8 status=noxfer 2>/dev/null );
($token) = join('-',unpack('H4 H4 H4', $code ));
qx( echo $token > /etc/sitetoken.txt );
}
else {
$token = qx( cat /etc/sitetoken.txt );
chomp $token;
}
## exit when a script update is found
print "Checking for updates to update script ($scriptname, existing version $version)... ";
if( ! -e $scriptname ) {
status( "scriptnamewrong,$scriptname" );
die "Unable to identify script name ($scriptname)" ;
}
{
my $lasttime = stat($scriptname)->mtime;
my $currenttime;
my $tempname = '/tmp/update.temporary';
unlink( $tempname );
system( "/usr/bin/curl -s -R https://ognconfig.onglide.com/files/v2.1/update -# -o $tempname" );
if( -e "$tempname" ) {
$currenttime = stat($tempname)->mtime;
}
else {
status("error,no_temp_file");
}
if( defined( $currenttime ) && $lasttime != $currenttime ) {
my ($md5sum_calculated,$md5sum_expected,$signature);
if( qx( /bin/grep -v '^# md5sum' $tempname | /usr/bin/md5sum ) =~ /^([0-9a-f]+) / ) {
$md5sum_calculated = $1;
}
if( qx( /bin/grep -e '^# md5sum' $tempname ) =~ /md5sum ([0-9a-f]+) (.*)/ ) {
$md5sum_expected = $1;
$signature = $2;
}
# if they are defined and the same
if( defined( $md5sum_expected ) && $md5sum_expected eq $md5sum_calculated ) {
# we need to check to make sure we have our public key saved away, without this
# we can't validate the identify
{
if( ! open( OUT, '>', '/etc/ognupdatekey.pem' ) ) {
status("error,write,/etc/ognupdatekey.pem,$!");
if( ! -e '/etc/ognupdatekey.pem' ) {
status("error,nokey");
}
}
print OUT "-----BEGIN PUBLIC KEY-----\n".
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArG/od7cdIuhSvKXNbO80\n".
"tFncaCfwuKUrBGxGE6uxzXRfwcCIn8UukGTnzdMEErh441K+itC69KhgkEhY809K\n".
"sxKMJqZ2FL6lXdin7eIMpOKLIXKmwwRYyTYdChXbnrd3Y5e9BXOWEUJVsg2PYrDt\n".
"xQnm20PiUgQXVCoW0xuxCnltj69nWGdXWPwhvFYT2ulhIXfVivJmUvHESK2GbYTo\n".
"h2Fv7aIQACv4EK7UpPb9zPqBrV4MmwqAKP2LzycIdmlH9D1ebB9T2hK31MIegKuV\n".
"VWQFQyqzxnFou3n1WYN3RBe5VdPuabQGXe4VQGmJVR1/1GQ+rPLRaQYU2zDYdLi1\n".
"EQIDAQAB\n".
"-----END PUBLIC KEY-----\n";
close( OUT );
}
# execute openssl to
my $md5sum_signed = qx( echo "$signature" | /usr/bin/base64 -d | /usr/bin/openssl rsautl -verify -inkey /etc/ognupdatekey.pem -keyform PEM -pubin );
chomp( $md5sum_signed );
if( ! -e '/etc/ognupdatekey.pem' ) {
$md5sum_signed = $md5sum_calculated;
status("not_checking_signature");
print "*** Not Checking signature as no pem file exists ***\n";
}
# make sure it matches
if( defined( $md5sum_signed ) && $md5sum_signed eq $md5sum_calculated ) {
# and that it isn't the same as the one we are running (datetime issue locally)
my $current_md5sum = '';
if( qx( /bin/grep -e '^# md5sum' $scriptname ) =~ /md5sum ([0-9a-f]+) (.*)/ ) {
$current_md5sum = $1;
}
if( $current_md5sum ne $md5sum_calculated ) {
copy( $tempname, $scriptname );
unlink( $tempname );
qx( /bin/chmod +x $scriptname );
status( "scriptupdate" );
print "an update has been found, restarting script.\n";
exec $scriptname, @ARGV ;
}
else {
print "already up to date\n";
status( "uptodate,$current_md5sum" );
}
}
else {
print "invalid signature, not signed by correct key? ($md5sum_signed != $md5sum_calculated), not updating script.\n";
status( "sig_problem,".($md5sum_signed||'?').','.($md5sum_expected||'?') );
}
}
else {
print "invalid checksum ($md5sum_expected != $md5sum_calculated), not updating script.\n";
status( "checksum_problem,".($md5sum_calculated||'?').','.($md5sum_expected||'?') );
}
}
else {
print "up to date.\n";
status("uptodate,".($currenttime||'-').",$lasttime");
}
if( -e "$tempname" ) {
unlink( $tempname );
}
}
## Make sure we have the correct procServer configuration file before we do anything as it
# won't work without it!
if( ! -e '/etc/rtlsdr-ogn.conf' ) {
status( 'noconfig' );
die "Unable to find /etc/rtlsdr-ogn.conf\n";
}
if( $ARGV[0] eq '-t' ) {
status( "testing" );
}
print "Checking automatic updater is installed...";
my $check = qx( /usr/bin/crontab -u root -l );
if( $check =~ /update/ ) {
print "yes.\n";
}
elsif( $ARGV[0] eq '-t' ) {
print "no. testing only\n";
}
else {
# if we are installing and have been asked to do a reboot after running
# then we will add the -r flag to the crontab
my $reboot = '';
if( $ARGV[0] eq '-r' ) {
$reboot = '-r';
}
my $when = sprintf( "%d %d", int(rand(59)), (int(rand(7))+23)%24 );
if( ! open( OUT, "| /usr/bin/crontab -u root -" )) {
status("error,write,crontab,$!");
die "unable to write to crontab to install";
}
print OUT $check;
print OUT "$when * * * $scriptname $reboot\n";
close( OUT );
$when =~ s/ /:/;
status( "crontab/$when" );
print "installed.\n";
}
# what we read from the configuration file
my %config;
my @config_order;
my %config_description;
# next check for daemon startup script and extra details from that
my $installdirectory;
my $username;
my $configfile;# if you need to copy it from /tmp/rtlsdr-ogn.site.conf after the upgrade
my $os; my $processor;
{
my $fh;
if( ! open( $fh, '<', "/etc/rtlsdr-ogn.conf" )) {
status("error,open,/etc/rtlsdr-ogn.conf,$!");
die "Unable to read /etc/rtlsdr-ogn.conf";
}
while( <$fh> ) {
my $line = $_;
chomp $line;
if( $line =~ m|^50000\s+([a-z0-9_-]+)\s+([a-z0-9/._-]+)\s+([a-z0-9/._-]+)\s+([a-z0-9/._-]+)|i ) {
$installdirectory = $2;
$username = $1;
$configfile = $4;
}
}
# sanity check
if( ! ($installdirectory =~ m|/rtlsdr-ogn$|) ) {
status('failed/idir');
die "Please change your /etc/rtlsdr-ogn.conf to point to the rtlsdr-ogn directory rather than a version specific directory.";
}
# remove the rtlsdr as this is included in the original distributions
my $installeddirectory = $installdirectory;
$installdirectory =~ s/rtlsdr-ogn$//;
$installdirectory =~ s|/$||;
# exactly where is the config file, find it the same way the ogn process would - change into the directory
# and then convert to an absolute path
chdir $installeddirectory;
my $expandedconfigfile = Cwd::abs_path( $configfile );
copy( $expandedconfigfile, "/tmp/rtlsdr-ogn.site.conf" );
chdir $installdirectory;
read_config();
$aprscall = $config{APRS_Call}||'unknown';
$aprscall =~ s/"//g;
# make sure the device has been configured, if not then don't do anything
if( $aprscall eq 'Example' || $aprscall eq 'unknown' ) {
status( "failed/unconfigured" );
die "This device has not yet been configured.\nPlease edit $expandedconfigfile\n".
"If you are using an image from https://ognconfig.onglide.com or the bootstrap you should complete configuration before running this.\n".
"If the update script has been installed then it will automatically retry the update every night.\n";
}
# next step is to check which install it is
$processor = qx( /bin/uname -p );
my $hardware = qx( cat /proc/cpuinfo | grep Hardware );
$os = qx( /bin/uname -a );
my $download;
my $md5download = 'http://download.glidernet.org/md5.txt';
my $filename;
my $dist;
my $osv = undef;
if( -e '/etc/init.d/flarm-update' ) {
print "Disabling old updater...";
if( $ARGV[0] ne '-t' ) {
status("old_disabled");
qx( /usr/sbin/update-rc.d flarm-update remove 2>/dev/null);
unlink "/etc/init.d/flarm-update";
print "done.\n";
}
else {
print "skipped... testing\n";
}
}
if( $hardware =~ /BCM2708/ || ( $os =~ /arm/ && -e "$installdirectory/rtlsdr-ogn/gpu_dev") ) {
$filename = "rtlsdr-ogn-bin-RPI-GPU-latest.tgz";
$download = "http://download.glidernet.org/rpi-gpu/$filename";
$dist = 'RPI-GPU';
$os = 'raspberry';
$osv=qx( /bin/uname -r );
}
elsif( $processor =~ /arm/ || $os =~ /arm/ ) {
$filename = "rtlsdr-ogn-bin-ARM-latest.tgz";
$download = "http://download.glidernet.org/arm/$filename";
$dist = 'ARM';
}
elsif( $processor =~ /32/ || $processor =~ /i[0-9]86/ || $os =~ /[0-9]86-pae/ ) {
$filename = "rtlsdr-ogn-bin-x86-latest.tgz";
$download = "http://download.glidernet.org/x86/$filename";
$dist = 'x86';
}
elsif( $processor =~ /64/ ) {
$filename = "rtlsdr-ogn-bin-x64-latest.tgz";
$download = "http://download.glidernet.org/x64/$filename";
$dist = 'x64';
}
else {
my $sstring = "unidentified,$os,$processor,$hardware,".qx( uname -a ).",".qx( uname -m );
$sstring =~ s/[^A-Za-z0-9_.]/_/g;
status( $sstring );
die "Unable to identify installation type :(\n".
"os: $os\n".
"processor: $processor\n".
"uname -m: ". qx( uname -m ). "\n".
"Please email melissa-ognconfig\@littlebluecar with the above output for help!\n";
}
# identify the existing version
my $existingversion = readlink( $installdirectory."/rtlsdr-ogn" );
status( $installdirectory.','.($existingversion||'?').','.$dist );
status( "iedd,".$installeddirectory );
print "Source: $download\n".
"Installation Directory: $installdirectory\n";
print "Configuration file: $configfile ($expandedconfigfile)\n";
print "Callsign: $aprscall\n";
print "\nExisting version: $existingversion\n";
if( $ARGV[0] eq '-t' ) {
print "\n Testing only - no changes made\n";
exit;
}
# this is a work around as the OGN official startup script will hang on NTP for a LONG time
# use the 1_3 version as it is less prone to this problem
{
my $startuptime = stat("/etc/init.d/rtlsdr-ogn")->mtime;
if( $startuptime < $startupepoch ) {
system( "/usr/bin/curl 'https://ognconfig.onglide.com/files/v2.1/rtlsdr-ogn' -R -# -o /etc/init.d/rtlsdr-ogn" );
qx( /bin/chmod +x /etc/init.d/rtlsdr-ogn );
qx( /usr/bin/sudo /usr/sbin/update-rc.d -f rtlsdr-ogn defaults 2>/dev/null);
status( "upgrading/rtlsdr-ogn" );
}
}
# First we need to check the MD5 status and see if we have a different checksum as this will
# trump the file date check we used to use
my $expectedchecksum = 'expected';
{
my $f = "$installdirectory/md5.txt";
my $lasttime = -e $f ? stat($f)->mtime : 0;
qx( /usr/bin/curl -s -z $f $md5download -o $f );
my $currenttime = stat($f)->mtime;
if( qx( cat $f | /bin/grep $filename ) =~ /^([0-9a-f]+) / ) {
$expectedchecksum = $1;
}
# if the file has changed then we need to check to see if the checksum has changed
if ( $lasttime != $currenttime ) {
print "Fetched new checksum file\n";
my $currentchecksum = 'current';
if( qx( /usr/bin/md5sum $installdirectory/$filename ) =~ /^([0-9a-f]+) / ) {
$currentchecksum = $1;
}
if( $currentchecksum ne $expectedchecksum ) {
status( "md5sumdiff,$download,$currentchecksum,$expectedchecksum");
system( "touch -d 2000-01-01T00:00:00 $installdirectory/$filename" );
print "md5: checksum incorrect ($currentchecksum != $expectedchecksum), marking current download as old\n"
}
}
else {
status("md5sum,file_date_unchanged");
}
}
# check for a new download and that the dates are different from before
my $lasttime = -e "$installdirectory/$filename" ? stat("$installdirectory/$filename")->mtime : 0;
qx( /usr/bin/curl -s -z $installdirectory/$filename $download -o $installdirectory/$filename );
my $currenttime = stat("$installdirectory/$filename")->mtime;
# check what version is in the archive
my $symlinkdetails = qx( /bin/tar tf $installdirectory/$filename | grep -e 'rtlsdr-ogn-' | head -1 );
my $archiveversion;
chomp( $symlinkdetails );
if( $symlinkdetails =~ /^(rtlsdr-ogn-[0-9.]+)/ ) {
$archiveversion = $1;
print "Archive version: $archiveversion\n";
}
else {
# error on invalid files and abort
status("invalid,$download,$!,$symlinkdetails,$?");
print "Unable to identify archive version or archive missing symlink for rtlsdr-ogn\n";
exit;
}
# make sure that the downloaded version has the correct checksum, if it doesn't then don't
# do anything with it
if( qx( /usr/bin/md5sum $installdirectory/$filename ) =~ /^([0-9a-f]+) / ) {
my $currentchecksum = $1;
if( $currentchecksum ne $expectedchecksum ) {
status("invalidcsum,$download,$currentchecksum,$expectedchecksum");
print "Downloaded file does not match the published checksum, aborting\n";
exit;
}
}
print "\n";
# if they are then we are upgrading
if( $lasttime != $currenttime || $archiveversion ne ($existingversion||'') ) {
print "Upgrade from ".($existingversion||'no symlink found')." to $archiveversion found. installing\n";
print "$lasttime != $currenttime\n";
status( "upgrading/$archiveversion" );
}
else {
status( "up2date$ARGV[0]" );
print "Up to date. (version $existingversion)\n";
# if we have been asked to reboot then do it upon completion
if( $ARGV[0] eq '-r' ) {
qx( /sbin/reboot );
}
exit;
}
# perform the upgrade, first stop the service so we don't get any conflicts
print "Stopping ogn service: ";
qx( /usr/sbin/service rtlsdr-ogn stop );
print "done.\n";
# then uncompress it
qx( cd $installdirectory ; /bin/tar xzf $filename );
qx( cd $installdirectory ; /bin/rm rtlsdr-ogn; /bin/ln -fs $archiveversion rtlsdr-ogn );
# then make sure it is executable and can run as root
qx( cd $installdirectory/rtlsdr-ogn ; /bin/chown ogn:ogn *; /bin/chown root gsm_scan ogn-rf; /bin/chmod a+s gsm_scan ogn-rf; /usr/bin/mkfifo ogn-rf.fifo; /bin/chown ogn:ogn ogn-rf.fifo );
# if it is a pi then make the gpu_dev
if( $dist eq 'RPI-GPU' ) {
if( ($osv+0) >= 4.1 ) {
qx( cd $installdirectory/rtlsdr-ogn; /bin/mknod gpu_dev c 249 0; /bin/chown ogn:ogn gpu_dev );
}
else {
qx( cd $installdirectory/rtlsdr-ogn; /bin/mknod gpu_dev c 100 0; /bin/chown ogn:ogn gpu_dev );
}
}
###################
# make sure we have the configuration file in the right directory
chdir( $installeddirectory );
my $newexpandedconfigfile = Cwd::abs_path( $configfile );
# check if anything has changed... if it has then we need to copy the file
if( $newexpandedconfigfile ne $expandedconfigfile ) {
if( ! copy( '/tmp/rtlsdr-ogn.site.conf', "$newexpandedconfigfile" ) ) {
print "unable to copy $!\n";
}
status("mvconfig,f,$expandedconfigfile" );
status("mvconfig,t,$newexpandedconfigfile" );
print "Copied configuration file to $configfile ($newexpandedconfigfile)\n";
}
else {
status("config,$expandedconfigfile");
print "Configuration file path has not changed, not copying. Backup in /tmp/rtlsdr-ogn.site.conf if needed\n";
}
# and if we are allowed to start the ogn service
if( $ARGV[0] ne '-i' && $ARGV[0] ne '-r' ) {
print "Restarting ogn service: ";
qx( /usr/sbin/service rtlsdr-ogn start );
print "done.\n";
}
$existingversion = readlink( $installdirectory."/rtlsdr-ogn" );
status( "done/$existingversion/$ARGV[0]" );
print "Upgrade completed ($existingversion)\n";
# if we have been asked to reboot then do it upon completion
if( $ARGV[0] eq '-r' ) {
qx( /sbin/reboot );
}
}
sub read_config {
my @sections;
# read it into the hash
open( my $fh, '<', "/tmp/rtlsdr-ogn.site.conf" ) || return;
while( <$fh> ) {
my $line = $_;
chomp $line;
if( $line =~ /^\s*([A-Za-z]+):/ ) {
push @sections, $1;
push @config_order, "+$1";
}
if( $line =~ /^\s*}/ ) {
pop @sections;
push @config_order, "-$1";
}
if( $line =~ /([A-Za-z]+)\s*=\s*([^;]+)(.*)/ ) {
my $key = join('_',@sections,$1);
$config{$key} = $2;
$config_description{$key} = $3;
push @config_order, "=$key,$1"; # so we know what order to write in
}
}
close ($fh);
}
sub status {
my ($status) = @_;
print $status."\n";
qx( /usr/bin/curl -s https://ognconfig.onglide.com/perl/startupgrade.pl?token=$token/v$version\\&status=$status\\&call=$aprscall );
}
sub date {
my @t = gmtime($_[0]);
return sprintf( "%04d-%02d-%02dT%02d-%02d-%02d", ($t[5]+1900),($t[4]+1),$t[3],$t[2],$t[1],$t[0]);
}