Upgrade to tzdata2012d.

This upgrade involved rewriting the script; the data has moved to ftp.iana.org,
where it's slightly less convenient to access, so it's time to use something
that can talk FTP...

As for tzdata2012d, it's just updating Morocco for this weekend's changes, now
they've been decided at the last minute (as usual).

Change-Id: I772df57a6e09b3bf3d9541bfc08930d6f18633b4
diff --git a/libc/tools/zoneinfo/generate b/libc/tools/zoneinfo/generate
index 3e21d0b..2059abd 100755
--- a/libc/tools/zoneinfo/generate
+++ b/libc/tools/zoneinfo/generate
@@ -1,82 +1,131 @@
-#!/bin/bash
+#!/usr/bin/python
 # Run with no arguments from any directory, with no special setup required.
 
-# Abort if any command returns an error exit status, or if an undefined
-# variable is used.
-set -e
-set -u
+import ftplib
+import hashlib
+import os
+import re
+import shutil
+import string
+import subprocess
+import sys
+import tarfile
+import tempfile
 
-echo "Looking for bionic..."
-bionic_dir=$(cd $(dirname $0)/../../.. && pwd)
-bionic_zoneinfo_dir=$bionic_dir/libc/zoneinfo
-bionic_zoneinfo_tools_dir=$bionic_dir/libc/tools/zoneinfo
-if [[ ! -d "$bionic_zoneinfo_dir" || ! -d "$bionic_zoneinfo_tools_dir" ]]; then
-  echo "Can't find bionic's zoneinfo directories!"
-  exit 1
-fi
+# Find the bionic directory, searching upward from this script.
+bionic_libc_tools_zoneinfo_dir = os.path.realpath(os.path.dirname(sys.argv[0]))
+bionic_libc_tools_dir = os.path.dirname(bionic_libc_tools_zoneinfo_dir)
+bionic_libc_dir = os.path.dirname(bionic_libc_tools_dir)
+bionic_dir = os.path.dirname(bionic_libc_dir)
+bionic_libc_zoneinfo_dir = '%s/libc/zoneinfo' % bionic_dir
+if not os.path.isdir(bionic_libc_tools_zoneinfo_dir) or not os.path.isdir(bionic_libc_zoneinfo_dir):
+  print "Couldn't find bionic/libc/tools/zoneinfo!"
+  sys.exit(1)
+print 'Found bionic in %s...' % bionic_dir
 
-echo "Switching to temporary directory..."
-temp_dir=`mktemp -d`
-cd $temp_dir
-trap "rm -rf $temp_dir; exit" INT TERM EXIT
+
+regions = ['africa', 'antarctica', 'asia', 'australasia', 'backward', 'etcetera', 'europe', 'factory', 'northamerica', 'southamerica']
+
+
+def current_tzdata_version():
+  return open('%s/zoneinfo.version' % bionic_libc_zoneinfo_dir).readline().rstrip('\n')
+
+
+def md5_file(filename):
+  md5 = hashlib.md5()
+  f = open(filename, 'rb')
+  while True:
+    data = f.read(8192)
+    if not data:
+      break
+    md5.update(data)
+  return md5.hexdigest()
+
+
+def upgrade_to(ftp, filename):
+  version = re.search('tzdata(.+)\.tar\.gz', filename).group(1)
+
+  # Switch to a temporary directory.
+  tmp_dir = tempfile.mkdtemp('-tzdata')
+  os.chdir(tmp_dir)
+  print 'Created temporary directory "%s"...' % tmp_dir
+
+  print 'Downloading %s...' % filename
+  ftp.retrbinary('RETR %s' % filename, open(filename, 'wb').write)
+  print 'MD5: %s' % md5_file(filename)
+
+  print 'Extracting...'
+  os.mkdir('extracted')
+  tar = tarfile.open(filename, 'r')
+  tar.extractall('extracted')
+
+  print 'Calling zic(1)...'
+  os.mkdir('data')
+  for region in regions:
+    if region != 'backward':
+      subprocess.check_call(['zic', '-d', 'data', 'extracted/%s' % region])
+
+  # Collect the data ZoneCompactor needs.
+  links = []
+  zones = []
+  for region in regions:
+    for line in open('extracted/%s' % region).readlines():
+      fields = string.split(line)
+      if len(fields) == 0:
+        continue
+      elif fields[0] == 'Link':
+        links.append('%s %s %s\n' % (fields[0], fields[1], fields[2]))
+        zones.append(fields[2])
+      elif fields[0] == 'Zone':
+        zones.append(fields[1])
+  zones.sort()
+
+  # Write it into the "setup" file.
+  setup = open('setup', 'w')
+  for link in links:
+    setup.write(link)
+  for zone in zones:
+    setup.write('%s\n' % zone)
+  setup.close()
+
+  print 'Calling ZoneCompactor...'
+  subprocess.check_call(['javac', '-d', '.',
+                         '%s/ZoneCompactor.java' % bionic_libc_tools_zoneinfo_dir,
+                         '%s/ZoneInfo.java' % bionic_libc_tools_zoneinfo_dir])
+  subprocess.check_call(['java', 'ZoneCompactor', 'setup', 'data'])
+
+  print 'Updating bionic from %s to %s...' % (current_tzdata_version(), version)
+  # Move the .dat and .idx files...
+  os.remove('%s/zoneinfo.dat' % bionic_libc_zoneinfo_dir)
+  shutil.move('zoneinfo.dat', bionic_libc_zoneinfo_dir)
+  os.remove('%s/zoneinfo.idx' % bionic_libc_zoneinfo_dir)
+  shutil.move('zoneinfo.idx', bionic_libc_zoneinfo_dir)
+  # Write the .version file...
+  zoneinfo_version = open('%s/zoneinfo.version' % bionic_libc_zoneinfo_dir, 'wb+')
+  zoneinfo_version.write('%s\n' % version)
+  zoneinfo_version.close()
+
 
 # URL from "Sources for Time Zone and Daylight Saving Time Data"
 # http://www.twinsun.com/tz/tz-link.htm
-echo "Looking for new tzdata..."
-wget -N --no-verbose 'ftp://munnari.oz.au/pub/tzdata*.tar.gz'
-zoneinfo_version_file=$bionic_zoneinfo_dir/zoneinfo.version
-if [ -f "$zoneinfo_version_file" ]; then
-  current_version=tzdata`sed s/\n// < $zoneinfo_version_file`
-else
-  current_version=missing
-fi
-latest_archive=`ls -r -v tzdata*.tar.gz | head -n1`
-latest_version=`basename $latest_archive .tar.gz`
-if [ "$current_version" == "$latest_version" ]; then
-  echo "You already have the latest tzdata ($latest_version)!"
-  exit 1
-fi
 
-md5_sum=`md5sum $latest_archive`
-echo "MD5: $md5_sum"
+print 'Looking for new tzdata...'
+ftp = ftplib.FTP('ftp.iana.org')
+ftp.login()
+ftp.cwd('tz/releases')
+tzdata_filenames = []
+for filename in ftp.nlst():
+  if filename.startswith('tzdata20'):
+    tzdata_filenames.append(filename)
+tzdata_filenames.sort()
 
-echo "Extracting $latest_version..."
-mkdir $latest_version
-tar -C $latest_version -zxf $latest_archive
+# If you're several releases behind, we'll walk you through the upgrades one by one.
+current_version = current_tzdata_version()
+current_filename = 'tzdata%s.tar.gz' % current_version
+for filename in tzdata_filenames:
+  if filename > current_filename:
+    upgrade_to(ftp, filename)
+    sys.exit(0)
 
-echo "Compiling $latest_version..."
-mkdir data
-for i in \
-    africa \
-    antarctica \
-    asia \
-    australasia \
-    etcetera \
-    europe \
-    factory \
-    northamerica \
-    solar87 \
-    solar88 \
-    solar89 \
-    southamerica
-do
-    zic -d data $latest_version/$i
-done
-
-echo "Compacting $latest_version..."
-(
-    cat $latest_version/* | grep '^Link' | awk '{print $1, $2, $3}'
-    (
-        cat $latest_version/* | grep '^Zone' | awk '{print $2}'
-        cat $latest_version/* | grep '^Link' | awk '{print $3}'
-    ) | LC_ALL="C" sort
-) | grep -v Riyadh8 > setup
-
-javac -d . \
-    $bionic_zoneinfo_tools_dir/ZoneCompactor.java \
-    $bionic_zoneinfo_tools_dir/ZoneInfo.java
-java ZoneCompactor setup data
-
-echo "Updating bionic to $latest_version..."
-mv zoneinfo.dat zoneinfo.idx $bionic_zoneinfo_dir
-echo $latest_version | sed 's/tzdata//' > $bionic_zoneinfo_dir/zoneinfo.version
+print 'You already have the latest tzdata (%s)!' % current_version
+sys.exit(0)