15d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes#!/usr/bin/python
2d40e63ee47e4a7f072a9d9a20e09c26f0090b02cElliott Hughes# Run with no arguments from any directory, with no special setup required.
3d40e63ee47e4a7f072a9d9a20e09c26f0090b02cElliott Hughes
45d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesimport ftplib
55d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesimport hashlib
65d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesimport os
75d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesimport re
85d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesimport shutil
95d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesimport string
105d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesimport subprocess
115d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesimport sys
125d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesimport tarfile
135d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesimport tempfile
145d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes
155d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes# Find the bionic directory, searching upward from this script.
165d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesbionic_libc_tools_zoneinfo_dir = os.path.realpath(os.path.dirname(sys.argv[0]))
175d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesbionic_libc_tools_dir = os.path.dirname(bionic_libc_tools_zoneinfo_dir)
185d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesbionic_libc_dir = os.path.dirname(bionic_libc_tools_dir)
195d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesbionic_dir = os.path.dirname(bionic_libc_dir)
205d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesbionic_libc_zoneinfo_dir = '%s/libc/zoneinfo' % bionic_dir
215d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesif not os.path.isdir(bionic_libc_tools_zoneinfo_dir) or not os.path.isdir(bionic_libc_zoneinfo_dir):
225d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  print "Couldn't find bionic/libc/tools/zoneinfo!"
235d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  sys.exit(1)
245d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesprint 'Found bionic in %s...' % bionic_dir
255d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes
265d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes
27541c2253206785c7b225252403f6f54723231317Elliott Hughesregions = ['africa', 'antarctica', 'asia', 'australasia', 'backward', 'etcetera', 'europe', 'northamerica', 'southamerica']
285d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes
295d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes
305d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesdef current_tzdata_version():
315d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  return open('%s/zoneinfo.version' % bionic_libc_zoneinfo_dir).readline().rstrip('\n')
325d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes
335d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes
345d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesdef md5_file(filename):
355d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  md5 = hashlib.md5()
365d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  f = open(filename, 'rb')
375d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  while True:
385d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes    data = f.read(8192)
395d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes    if not data:
405d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes      break
415d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes    md5.update(data)
425d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  return md5.hexdigest()
435d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes
445d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes
455d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesdef upgrade_to(ftp, filename):
465d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  version = re.search('tzdata(.+)\.tar\.gz', filename).group(1)
475d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes
485d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  # Switch to a temporary directory.
495d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  tmp_dir = tempfile.mkdtemp('-tzdata')
505d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  os.chdir(tmp_dir)
515d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  print 'Created temporary directory "%s"...' % tmp_dir
525d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes
535d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  print 'Downloading %s...' % filename
545d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  ftp.retrbinary('RETR %s' % filename, open(filename, 'wb').write)
555d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  print 'MD5: %s' % md5_file(filename)
565d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes
575d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  print 'Extracting...'
585d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  os.mkdir('extracted')
595d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  tar = tarfile.open(filename, 'r')
605d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  tar.extractall('extracted')
615d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes
625d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  print 'Calling zic(1)...'
635d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  os.mkdir('data')
645d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  for region in regions:
655d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes    if region != 'backward':
665d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes      subprocess.check_call(['zic', '-d', 'data', 'extracted/%s' % region])
675d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes
685d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  # Collect the data ZoneCompactor needs.
695d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  links = []
705d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  zones = []
715d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  for region in regions:
725d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes    for line in open('extracted/%s' % region).readlines():
735d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes      fields = string.split(line)
745d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes      if len(fields) == 0:
755d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes        continue
765d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes      elif fields[0] == 'Link':
775d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes        links.append('%s %s %s\n' % (fields[0], fields[1], fields[2]))
785d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes        zones.append(fields[2])
795d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes      elif fields[0] == 'Zone':
805d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes        zones.append(fields[1])
815d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  zones.sort()
825d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes
835d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  # Write it into the "setup" file.
845d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  setup = open('setup', 'w')
855d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  for link in links:
865d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes    setup.write(link)
875d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  for zone in zones:
885d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes    setup.write('%s\n' % zone)
895d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  setup.close()
905d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes
915d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  print 'Calling ZoneCompactor...'
925d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  subprocess.check_call(['javac', '-d', '.',
935d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes                         '%s/ZoneCompactor.java' % bionic_libc_tools_zoneinfo_dir,
945d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes                         '%s/ZoneInfo.java' % bionic_libc_tools_zoneinfo_dir])
955d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  subprocess.check_call(['java', 'ZoneCompactor', 'setup', 'data'])
965d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes
975d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  print 'Updating bionic from %s to %s...' % (current_tzdata_version(), version)
985d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  # Move the .dat and .idx files...
995d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  os.remove('%s/zoneinfo.dat' % bionic_libc_zoneinfo_dir)
1005d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  shutil.move('zoneinfo.dat', bionic_libc_zoneinfo_dir)
1015d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  os.remove('%s/zoneinfo.idx' % bionic_libc_zoneinfo_dir)
1025d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  shutil.move('zoneinfo.idx', bionic_libc_zoneinfo_dir)
1035d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  # Write the .version file...
1045d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  zoneinfo_version = open('%s/zoneinfo.version' % bionic_libc_zoneinfo_dir, 'wb+')
1055d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  zoneinfo_version.write('%s\n' % version)
1065d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  zoneinfo_version.close()
1075d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes
108d40e63ee47e4a7f072a9d9a20e09c26f0090b02cElliott Hughes
109d40e63ee47e4a7f072a9d9a20e09c26f0090b02cElliott Hughes# URL from "Sources for Time Zone and Daylight Saving Time Data"
110d40e63ee47e4a7f072a9d9a20e09c26f0090b02cElliott Hughes# http://www.twinsun.com/tz/tz-link.htm
1115d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes
1125d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesprint 'Looking for new tzdata...'
1135d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesftp = ftplib.FTP('ftp.iana.org')
1145d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesftp.login()
1155d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesftp.cwd('tz/releases')
1165d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughestzdata_filenames = []
1175d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesfor filename in ftp.nlst():
1185d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  if filename.startswith('tzdata20'):
1195d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes    tzdata_filenames.append(filename)
1205d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughestzdata_filenames.sort()
1215d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes
1225d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes# If you're several releases behind, we'll walk you through the upgrades one by one.
1235d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughescurrent_version = current_tzdata_version()
1245d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughescurrent_filename = 'tzdata%s.tar.gz' % current_version
1255d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesfor filename in tzdata_filenames:
1265d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes  if filename > current_filename:
1275d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes    upgrade_to(ftp, filename)
1285d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes    sys.exit(0)
1295d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes
1305d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesprint 'You already have the latest tzdata (%s)!' % current_version
1315d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughessys.exit(0)
132