Home | History | Annotate | Download | only in zoneinfo
      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