1 #!/usr/bin/python 2 3 """Updates the tzdata file.""" 4 5 import ftplib 6 import os 7 import re 8 import subprocess 9 import sys 10 import tarfile 11 import tempfile 12 13 # Find the bionic directory, searching upward from this script. 14 bionic_libc_tools_zoneinfo_dir = os.path.realpath(os.path.dirname(sys.argv[0])) 15 bionic_libc_tools_dir = os.path.dirname(bionic_libc_tools_zoneinfo_dir) 16 bionic_libc_dir = os.path.dirname(bionic_libc_tools_dir) 17 bionic_dir = os.path.dirname(bionic_libc_dir) 18 bionic_libc_zoneinfo_dir = '%s/libc/zoneinfo' % bionic_dir 19 20 if not os.path.isdir(bionic_libc_tools_zoneinfo_dir): 21 print "Couldn't find bionic/libc/tools/zoneinfo!" 22 sys.exit(1) 23 if not os.path.isdir(bionic_libc_zoneinfo_dir): 24 print "Couldn't find bionic/libc/zoneinfo!" 25 sys.exit(1) 26 27 print 'Found bionic in %s...' % bionic_dir 28 29 30 regions = ['africa', 'antarctica', 'asia', 'australasia', 'backward', 31 'etcetera', 'europe', 'northamerica', 'southamerica'] 32 33 34 def GetCurrentTzDataVersion(): 35 return open('%s/tzdata' % bionic_libc_zoneinfo_dir).read().split('\x00', 1)[0] 36 37 38 def WriteSetupFile(): 39 """Writes the list of zones that ZoneCompactor should process.""" 40 links = [] 41 zones = [] 42 for region in regions: 43 for line in open('extracted/%s' % region): 44 fields = line.split() 45 if fields: 46 if fields[0] == 'Link': 47 links.append('%s %s %s\n' % (fields[0], fields[1], fields[2])) 48 zones.append(fields[2]) 49 elif fields[0] == 'Zone': 50 zones.append(fields[1]) 51 zones.sort() 52 53 setup = open('setup', 'w') 54 for link in links: 55 setup.write(link) 56 for zone in zones: 57 setup.write('%s\n' % zone) 58 setup.close() 59 60 61 def Retrieve(ftp, filename): 62 ftp.retrbinary('RETR %s' % filename, open(filename, 'wb').write) 63 64 65 def UpgradeTo(ftp, data_filename): 66 """Downloads and repackages the given data from the given FTP server.""" 67 68 new_version = re.search('(tzdata.+)\\.tar\\.gz', data_filename).group(1) 69 70 # Switch to a temporary directory. 71 tmp_dir = tempfile.mkdtemp('-tzdata') 72 os.chdir(tmp_dir) 73 print 'Created temporary directory "%s"...' % tmp_dir 74 75 print 'Downloading data...' 76 Retrieve(ftp, data_filename) 77 78 print 'Downloading signature...' 79 signature_filename = '%s.asc' % data_filename 80 Retrieve(ftp, signature_filename) 81 82 print 'Verifying signature...' 83 # If this fails for you, you probably need to import Paul Eggert's public key: 84 # gpg --recv-keys ED97E90E62AA7E34 85 subprocess.check_call(['gpg', '--trusted-key=ED97E90E62AA7E34', '--verify', 86 signature_filename, data_filename]) 87 88 print 'Extracting...' 89 os.mkdir('extracted') 90 tar = tarfile.open(data_filename, 'r') 91 tar.extractall('extracted') 92 93 print 'Calling zic(1)...' 94 os.mkdir('data') 95 for region in regions: 96 if region != 'backward': 97 subprocess.check_call(['zic', '-d', 'data', 'extracted/%s' % region]) 98 99 WriteSetupFile() 100 101 print 'Calling ZoneCompactor to update bionic to %s...' % new_version 102 libcore_src_dir = '%s/../libcore/luni/src/main/java/' % bionic_dir 103 subprocess.check_call(['javac', '-d', '.', 104 '%s/ZoneCompactor.java' % bionic_libc_tools_zoneinfo_dir, 105 '%s/libcore/util/ZoneInfo.java' % libcore_src_dir, 106 '%s/libcore/io/BufferIterator.java' % libcore_src_dir]) 107 subprocess.check_call(['java', 'ZoneCompactor', 108 'setup', 'data', 'extracted/zone.tab', 109 bionic_libc_zoneinfo_dir, new_version]) 110 111 112 # Run with no arguments from any directory, with no special setup required. 113 # See http://www.iana.org/time-zones/ for more about the source of this data. 114 def main(): 115 print 'Looking for new tzdata...' 116 ftp = ftplib.FTP('ftp.iana.org') 117 ftp.login() 118 ftp.cwd('tz/releases') 119 tzdata_filenames = [] 120 for filename in ftp.nlst(): 121 if filename.startswith('tzdata20') and filename.endswith('.tar.gz'): 122 tzdata_filenames.append(filename) 123 tzdata_filenames.sort() 124 125 # If you're several releases behind, we'll walk you through the upgrades 126 # one by one. 127 current_version = GetCurrentTzDataVersion() 128 current_filename = '%s.tar.gz' % current_version 129 for filename in tzdata_filenames: 130 if filename > current_filename: 131 print 'Found new tzdata: %s' % filename 132 UpgradeTo(ftp, filename) 133 sys.exit(0) 134 135 print 'You already have the latest tzdata (%s)!' % current_version 136 sys.exit(0) 137 138 139 if __name__ == '__main__': 140 main() 141