#!/usr/bin/perl -w # Written by Alain Thivillon # Licence http://sam.zoy.org/wtfpl/ use strict; use LWP::UserAgent; use HTTP::Response; use Digest::SHA1; use Cwd; my $debug = 0 || $ENV{'DEBUG'}; my $urliana = 'http://www.iana.org/time-zones/repository/data/leapseconds'; my $fileleap = './leapseconds_iana'; my $zonefile = './tai'; my $compiled_zonefilename = "Etc/TAI"; my $zonename = "TAI"; my $offset = 10; #my $cmdcompile = ''; my $cmdcompile = "zic -d . %s"; my $digleap_file=''; # check if leapfile exists and do sha1sum if (open LEAPH,"<$fileleap") { my $sha1 = Digest::SHA1->new; $sha1->addfile(*LEAPH); $digleap_file = $sha1->digest; close LEAPH; if ($debug) { printf STDERR "%s SHA1sum : %s\n", $fileleap, $sha1->hexdigest }; } else { warn "Can not open $fileleap : $!"; } # Grab IANA file my $ua = new LWP::UserAgent; if ($debug) { $ua->add_handler("request_send", sub { shift->dump; return }); $ua->add_handler("response_done", sub { shift->dump; return }); } my $answer = $ua->get($urliana); if ($answer->code != 200) { warn "Error requesting $urliana : " . $answer->code . " " . $answer->status_line; exit 2; } # check SHA1 of received file my $sha1online = Digest::SHA1->new; $sha1online->add($answer->content); if ($sha1online->digest eq $digleap_file) { if ($debug) { printf STDERR "%s SHA1sum : %s\n", $urliana, $sha1online->hexdigest; printf STDERR "No changes detected between %s and %s\n",$urliana,$fileleap; } exit 0; } my $nbleap = 0; # # Leap YEAR MONTH DAY HH:MM:SS CORR R/S # Leap 1972 Jun 30 23:59:60 + S # Leap 1972 Dec 31 23:59:60 + S # Leap 1976 Dec 31 23:59:60 + S # ... # verify received file for coherence foreach my $line (split /\n/,$answer->content) { next unless $line =~ /^Leap\s+(\d+)\s+(\w+)\s+(\d+)\s+(\d+:\d+:\d+)\s+([\+\-])\s+/; $nbleap++; } if ($nbleap < 25) { warn "Outdated leapfile contains $nbleap leap seconds (<25 !)"; exit 2; } if ($debug) { print STDERR "$nbleap leap seconds found\n" }; # write file for zic if (!open TAIFILE,">$zonefile") { warn "can not open $zonefile for writing $!"; exit 2; } print TAIFILE "Zone\t$compiled_zonefilename\t"; if ($debug) { print STDERR "Zone\t$compiled_zonefilename\t"; } foreach my $line (split /\n/,$answer->content) { next unless $line =~ /^Leap\s+(\d+)\s+(\w+)\s+(\d+)\s+(\d+:\d+:\d+)\s+([\+\-])\s+/; printf TAIFILE "0:00:%02d - %s %4d %s %d %s\n\t\t",$offset,$zonename,$1,$2,$3,$4; if ($debug) { printf STDERR "0:00:%02d - %s %4d %s %d %s\n\t\t",$offset,$zonename,$1,$2,$3,$4; } $offset += ($5 eq '+' ? 1 : -1); } printf TAIFILE "0:00:%02d - %s\n",$offset,$zonename; if ($debug) { printf STDERR "0:00:%02d - %s\n",$offset,$zonename; } close TAIFILE; printf STDERR "Zonefile %s generated\n", $zonefile; # Execute zic if requested if ($cmdcompile ne '') { my $cmdline = sprintf $cmdcompile,$zonefile; if ($debug) { printf STDERR "Execution $cmdline\n"; } if (system($cmdline)) { warn "Error executing \"$cmdline\" : $!"; exit 2; } printf STDERR "Zonefile %s compiled in %s\n", $zonefile,$compiled_zonefilename; printf STDERR "You can check with \"TZDIR=%s TZ=%s date && TZ=UTC date\"\n", cwd(), $compiled_zonefilename; } # write received file if everything ok if (!(open LEAPH, ">$fileleap")) { warn "Can not open $fileleap for writing : $!"; exit 2; } print LEAPH $answer->content; close LEAPH; printf STDERR "Leapsecond file %s saved\n", $fileleap; exit 0;