1 #!/usr/bin/python 2 # Run with no arguments from any directory, with no special setup required. 3 4 import ftplib 5 import hashlib 6 import os 7 import re 8 import shutil 9 import string 10 import subprocess 11 import sys 12 import tarfile 13 import tempfile 14 15 # Find the bionic directory, searching upward from this script. 16 bionic_libc_tools_zoneinfo_dir = os.path.realpath(os.path.dirname(sys.argv[0])) 17 bionic_libc_tools_dir = os.path.dirname(bionic_libc_tools_zoneinfo_dir) 18 bionic_libc_dir = os.path.dirname(bionic_libc_tools_dir) 19 bionic_dir = os.path.dirname(bionic_libc_dir) 20 bionic_libc_zoneinfo_dir = '%s/libc/zoneinfo' % bionic_dir 21 if not os.path.isdir(bionic_libc_tools_zoneinfo_dir) or not os.path.isdir(bionic_libc_zoneinfo_dir): 22 print "Couldn't find bionic/libc/tools/zoneinfo!" 23 sys.exit(1) 24 print 'Found bionic in %s...' % bionic_dir 25 26 27 regions = ['africa', 'antarctica', 'asia', 'australasia', 'backward', 'etcetera', 'europe', 'northamerica', 'southamerica'] 28 29 30 def current_tzdata_version(): 31 return open('%s/zoneinfo.version' % bionic_libc_zoneinfo_dir).readline().rstrip('\n') 32 33 34 def md5_file(filename): 35 md5 = hashlib.md5() 36 f = open(filename, 'rb') 37 while True: 38 data = f.read(8192) 39 if not data: 40 break 41 md5.update(data) 42 return md5.hexdigest() 43 44 45 def upgrade_to(ftp, filename): 46 version = re.search('tzdata(.+)\.tar\.gz', filename).group(1) 47 48 # Switch to a temporary directory. 49 tmp_dir = tempfile.mkdtemp('-tzdata') 50 os.chdir(tmp_dir) 51 print 'Created temporary directory "%s"...' % tmp_dir 52 53 print 'Downloading %s...' % filename 54 ftp.retrbinary('RETR %s' % filename, open(filename, 'wb').write) 55 print 'MD5: %s' % md5_file(filename) 56 57 print 'Extracting...' 58 os.mkdir('extracted') 59 tar = tarfile.open(filename, 'r') 60 tar.extractall('extracted') 61 62 print 'Calling zic(1)...' 63 os.mkdir('data') 64 for region in regions: 65 if region != 'backward': 66 subprocess.check_call(['zic', '-d', 'data', 'extracted/%s' % region]) 67 68 # Collect the data ZoneCompactor needs. 69 links = [] 70 zones = [] 71 for region in regions: 72 for line in open('extracted/%s' % region).readlines(): 73 fields = string.split(line) 74 if len(fields) == 0: 75 continue 76 elif fields[0] == 'Link': 77 links.append('%s %s %s\n' % (fields[0], fields[1], fields[2])) 78 zones.append(fields[2]) 79 elif fields[0] == 'Zone': 80 zones.append(fields[1]) 81 zones.sort() 82 83 # Write it into the "setup" file. 84 setup = open('setup', 'w') 85 for link in links: 86 setup.write(link) 87 for zone in zones: 88 setup.write('%s\n' % zone) 89 setup.close() 90 91 print 'Calling ZoneCompactor...' 92 subprocess.check_call(['javac', '-d', '.', 93 '%s/ZoneCompactor.java' % bionic_libc_tools_zoneinfo_dir, 94 '%s/ZoneInfo.java' % bionic_libc_tools_zoneinfo_dir]) 95 subprocess.check_call(['java', 'ZoneCompactor', 'setup', 'data']) 96 97 print 'Updating bionic from %s to %s...' % (current_tzdata_version(), version) 98 # Move the .dat and .idx files... 99 os.remove('%s/zoneinfo.dat' % bionic_libc_zoneinfo_dir) 100 shutil.move('zoneinfo.dat', bionic_libc_zoneinfo_dir) 101 os.remove('%s/zoneinfo.idx' % bionic_libc_zoneinfo_dir) 102 shutil.move('zoneinfo.idx', bionic_libc_zoneinfo_dir) 103 # Write the .version file... 104 zoneinfo_version = open('%s/zoneinfo.version' % bionic_libc_zoneinfo_dir, 'wb+') 105 zoneinfo_version.write('%s\n' % version) 106 zoneinfo_version.close() 107 108 109 # URL from "Sources for Time Zone and Daylight Saving Time Data" 110 # http://www.twinsun.com/tz/tz-link.htm 111 112 print 'Looking for new tzdata...' 113 ftp = ftplib.FTP('ftp.iana.org') 114 ftp.login() 115 ftp.cwd('tz/releases') 116 tzdata_filenames = [] 117 for filename in ftp.nlst(): 118 if filename.startswith('tzdata20'): 119 tzdata_filenames.append(filename) 120 tzdata_filenames.sort() 121 122 # If you're several releases behind, we'll walk you through the upgrades one by one. 123 current_version = current_tzdata_version() 124 current_filename = 'tzdata%s.tar.gz' % current_version 125 for filename in tzdata_filenames: 126 if filename > current_filename: 127 upgrade_to(ftp, filename) 128 sys.exit(0) 129 130 print 'You already have the latest tzdata (%s)!' % current_version 131 sys.exit(0) 132