diff --git a/libc/tools/zoneinfo/ZoneCompactor.java b/libc/tools/zoneinfo/ZoneCompactor.java
index 9fb9cec..6ce24cf 100644
--- a/libc/tools/zoneinfo/ZoneCompactor.java
+++ b/libc/tools/zoneinfo/ZoneCompactor.java
@@ -7,8 +7,7 @@
 
 // usage: java ZoneCompiler <setup file> <data directory> <output directory> <tzdata version>
 //
-// Compile a set of tzfile-formatted files into a single file plus
-// an index file.
+// Compile a set of tzfile-formatted files into a single file containing an index.
 //
 // The compilation is controlled by a setup file, which is provided as a
 // command-line argument.  The setup file has the form:
@@ -18,195 +17,219 @@
 // <zone filename>
 // ...
 //
-// Note that the links must be declared prior to the zone names.  A
-// zone name is a filename relative to the source directory such as
+// Note that the links must be declared prior to the zone names.
+// A zone name is a filename relative to the source directory such as
 // 'GMT', 'Africa/Dakar', or 'America/Argentina/Jujuy'.
 //
 // Use the 'zic' command-line tool to convert from flat files
-// (e.g., 'africa', 'northamerica') into a suitable source directory
-// hierarchy for this tool (e.g., 'data/Africa/Abidjan').
+// (such as 'africa' or 'northamerica') to a directory
+// hierarchy suitable for this tool (containing files such as 'data/Africa/Abidjan').
 //
-// Example:
-//     zic -d data tz2007h
-//     javac ZoneCompactor.java
-//     java ZoneCompactor setup data
-//     <produces zoneinfo.dat and zoneinfo.idx>
 
 public class ZoneCompactor {
-    public static class ByteArrayBufferIteratorBE extends BufferIterator {
-        private final byte[] bytes;
-        private int offset = 0;
+  public static class ByteArrayBufferIteratorBE extends BufferIterator {
+    private final byte[] bytes;
+    private int offset = 0;
 
-        public ByteArrayBufferIteratorBE(byte[] bytes) {
-            this.bytes = bytes;
-            this.offset = 0;
-        }
-
-        public void seek(int offset) {
-            this.offset = offset;
-        }
-
-        public void skip(int byteCount) {
-            this.offset += byteCount;
-        }
-
-        public void readByteArray(byte[] dst, int dstOffset, int byteCount) {
-            System.arraycopy(bytes, offset, dst, dstOffset, byteCount);
-            offset += byteCount;
-        }
-
-        public byte readByte() {
-            return bytes[offset++];
-        }
-
-        public int readInt() {
-            return ((readByte() & 0xff) << 24) | ((readByte() & 0xff) << 16) | ((readByte() & 0xff) << 8) | (readByte() & 0xff);
-        }
-
-        public void readIntArray(int[] dst, int dstOffset, int intCount) {
-            for (int i = 0; i < intCount; ++i) {
-                dst[dstOffset++] = readInt();
-            }
-        }
-
-        public short readShort() {
-            throw new UnsupportedOperationException();
-        }
+    public ByteArrayBufferIteratorBE(byte[] bytes) {
+      this.bytes = bytes;
+      this.offset = 0;
     }
 
-    // Maximum number of characters in a zone name, including '\0' terminator
-    private static final int MAXNAME = 40;
-
-    // Zone name synonyms
-    private Map<String,String> links = new HashMap<String,String>();
-
-    // File starting bytes by zone name
-    private Map<String,Integer> starts = new HashMap<String,Integer>();
-
-    // File lengths by zone name
-    private Map<String,Integer> lengths = new HashMap<String,Integer>();
-
-    // Raw GMT offsets by zone name
-    private Map<String,Integer> offsets = new HashMap<String,Integer>();
-    private int start = 0;
-
-    // Concatenate the contents of 'inFile' onto 'out'
-    // and return the contents as a byte array.
-    private static byte[] copyFile(File inFile, OutputStream out) throws Exception {
-        byte[] ret = new byte[0];
-
-        InputStream in = new FileInputStream(inFile);
-        byte[] buf = new byte[8192];
-        while (true) {
-            int nbytes = in.read(buf);
-            if (nbytes == -1) {
-                break;
-            }
-            out.write(buf, 0, nbytes);
-
-            byte[] nret = new byte[ret.length + nbytes];
-            System.arraycopy(ret, 0, nret, 0, ret.length);
-            System.arraycopy(buf, 0, nret, ret.length, nbytes);
-            ret = nret;
-        }
-        out.flush();
-        return ret;
+    public void seek(int offset) {
+      this.offset = offset;
     }
 
-    // Write a 32-bit integer in network byte order
-    private void writeInt(OutputStream os, int x) throws IOException {
-        os.write((x >> 24) & 0xff);
-        os.write((x >> 16) & 0xff);
-        os.write((x >>  8) & 0xff);
-        os.write( x        & 0xff);
+    public void skip(int byteCount) {
+      this.offset += byteCount;
     }
 
-    public ZoneCompactor(String setupFile, String dataDirectory, String outputDirectory, String version) throws Exception {
-        File zoneInfoFile = new File(outputDirectory, "zoneinfo.dat");
-        zoneInfoFile.delete();
-        OutputStream zoneInfo = new FileOutputStream(zoneInfoFile);
-
-        BufferedReader rdr = new BufferedReader(new FileReader(setupFile));
-
-        String s;
-        while ((s = rdr.readLine()) != null) {
-            s = s.trim();
-            if (s.startsWith("Link")) {
-                StringTokenizer st = new StringTokenizer(s);
-                st.nextToken();
-                String to = st.nextToken();
-                String from = st.nextToken();
-                links.put(from, to);
-            } else {
-                String link = links.get(s);
-                if (link == null) {
-                    File f = new File(dataDirectory, s);
-                    long length = f.length();
-                    starts.put(s, new Integer(start));
-                    lengths.put(s, new Integer((int)length));
-
-                    start += length;
-                    byte[] data = copyFile(f, zoneInfo);
-
-                    BufferIterator it = new ByteArrayBufferIteratorBE(data);
-                    TimeZone tz = ZoneInfo.makeTimeZone(s, it);
-                    int gmtOffset = tz.getRawOffset();
-                    offsets.put(s, new Integer(gmtOffset));
-                }
-            }
-        }
-        zoneInfo.close();
-
-        // Fill in fields for links
-        Iterator<String> iter = links.keySet().iterator();
-        while (iter.hasNext()) {
-            String from = iter.next();
-            String to = links.get(from);
-
-            starts.put(from, starts.get(to));
-            lengths.put(from, lengths.get(to));
-            offsets.put(from, offsets.get(to));
-        }
-
-        File idxFile = new File(outputDirectory, "zoneinfo.idx");
-        idxFile.delete();
-        FileOutputStream idx = new FileOutputStream(idxFile);
-
-        ArrayList<String> l = new ArrayList<String>();
-        l.addAll(starts.keySet());
-        Collections.sort(l);
-        Iterator<String> ziter = l.iterator();
-        while (ziter.hasNext()) {
-            String zname = ziter.next();
-            if (zname.length() >= MAXNAME) {
-                System.err.println("Error - zone filename exceeds " +
-                                   (MAXNAME - 1) + " characters!");
-            }
-
-            byte[] znameBuf = new byte[MAXNAME];
-            for (int i = 0; i < zname.length(); i++) {
-                znameBuf[i] = (byte)zname.charAt(i);
-            }
-            idx.write(znameBuf);
-            writeInt(idx, starts.get(zname).intValue());
-            writeInt(idx, lengths.get(zname).intValue());
-            writeInt(idx, offsets.get(zname).intValue());
-        }
-        idx.close();
-
-        OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(new File(outputDirectory, "zoneinfo.version")), "US-ASCII");
-        writer.write(version);
-        writer.write('\n');
-        writer.close();
-
-        // System.out.println("maxLength = " + maxLength);
+    public void readByteArray(byte[] dst, int dstOffset, int byteCount) {
+      System.arraycopy(bytes, offset, dst, dstOffset, byteCount);
+      offset += byteCount;
     }
 
-    public static void main(String[] args) throws Exception {
-        if (args.length != 4) {
-            System.err.println("usage: java ZoneCompactor <setup file> <data directory> <output directory> <tzdata version>");
-            System.exit(0);
-        }
-        new ZoneCompactor(args[0], args[1], args[2], args[3]);
+    public byte readByte() {
+      return bytes[offset++];
     }
+
+    public int readInt() {
+      return ((readByte() & 0xff) << 24) | ((readByte() & 0xff) << 16) | ((readByte() & 0xff) << 8) | (readByte() & 0xff);
+    }
+
+    public void readIntArray(int[] dst, int dstOffset, int intCount) {
+      for (int i = 0; i < intCount; ++i) {
+        dst[dstOffset++] = readInt();
+      }
+    }
+
+    public short readShort() {
+      throw new UnsupportedOperationException();
+    }
+  }
+
+  // Maximum number of characters in a zone name, including '\0' terminator
+  private static final int MAXNAME = 40;
+
+  // Zone name synonyms
+  private Map<String,String> links = new HashMap<String,String>();
+
+  // File starting bytes by zone name
+  private Map<String,Integer> starts = new HashMap<String,Integer>();
+
+  // File lengths by zone name
+  private Map<String,Integer> lengths = new HashMap<String,Integer>();
+
+  // Raw GMT offsets by zone name
+  private Map<String,Integer> offsets = new HashMap<String,Integer>();
+  private int start = 0;
+
+  // Concatenate the contents of 'inFile' onto 'out'
+  // and return the contents as a byte array.
+  private static byte[] copyFile(File inFile, OutputStream out) throws Exception {
+    byte[] ret = new byte[0];
+
+    InputStream in = new FileInputStream(inFile);
+    byte[] buf = new byte[8192];
+    while (true) {
+      int nbytes = in.read(buf);
+      if (nbytes == -1) {
+        break;
+      }
+      out.write(buf, 0, nbytes);
+
+      byte[] nret = new byte[ret.length + nbytes];
+      System.arraycopy(ret, 0, nret, 0, ret.length);
+      System.arraycopy(buf, 0, nret, ret.length, nbytes);
+      ret = nret;
+    }
+    out.flush();
+    return ret;
+  }
+
+  public ZoneCompactor(String setupFile, String dataDirectory, String outputDirectory, String version) throws Exception {
+    // Read the setup file, and concatenate all the data.
+    ByteArrayOutputStream allData = new ByteArrayOutputStream();
+    BufferedReader reader = new BufferedReader(new FileReader(setupFile));
+    String s;
+    while ((s = reader.readLine()) != null) {
+      s = s.trim();
+      if (s.startsWith("Link")) {
+        StringTokenizer st = new StringTokenizer(s);
+        st.nextToken();
+        String to = st.nextToken();
+        String from = st.nextToken();
+        links.put(from, to);
+      } else {
+        String link = links.get(s);
+        if (link == null) {
+          File sourceFile = new File(dataDirectory, s);
+          long length = sourceFile.length();
+          starts.put(s, start);
+          lengths.put(s, (int) length);
+
+          start += length;
+          byte[] data = copyFile(sourceFile, allData);
+
+          BufferIterator it = new ByteArrayBufferIteratorBE(data);
+          TimeZone tz = ZoneInfo.makeTimeZone(s, it);
+          int gmtOffset = tz.getRawOffset();
+          offsets.put(s, gmtOffset);
+        }
+      }
+    }
+
+    // Fill in fields for links.
+    Iterator<String> it = links.keySet().iterator();
+    while (it.hasNext()) {
+      String from = it.next();
+      String to = links.get(from);
+
+      starts.put(from, starts.get(to));
+      lengths.put(from, lengths.get(to));
+      offsets.put(from, offsets.get(to));
+    }
+
+    // Create/truncate the destination file.
+    RandomAccessFile f = new RandomAccessFile(new File(outputDirectory, "tzdata"), "rw");
+    f.setLength(0);
+
+    // Write the header.
+
+    // byte[12] tzdata_version          -- 'tzdata2012f\0'
+    // int file_format_version          -- probably won't need this, but just in case
+    // int index_offset                 -- likewise
+    // int data_offset
+    // int zonetab_offset
+
+    // tzdata_version
+    f.write(toAscii(new byte[12], version));
+
+    // file_format_version
+    f.writeInt(1);
+
+    // Write dummy values for the three offsets, and remember where we need to seek back to later
+    // when we have the real values.
+    int index_offset_offset = (int) f.getFilePointer();
+    f.writeInt(0);
+    int data_offset_offset = (int) f.getFilePointer();
+    f.writeInt(0);
+    int zonetab_offset_offset = (int) f.getFilePointer();
+    f.writeInt(0);
+
+    int index_offset = (int) f.getFilePointer();
+
+    // Write the index.
+    ArrayList<String> sortedOlsonIds = new ArrayList<String>();
+    sortedOlsonIds.addAll(starts.keySet());
+    Collections.sort(sortedOlsonIds);
+    it = sortedOlsonIds.iterator();
+    while (it.hasNext()) {
+      String zoneName = it.next();
+      if (zoneName.length() >= MAXNAME) {
+        throw new RuntimeException("zone filename too long: " + zoneName.length());
+      }
+
+      f.write(toAscii(new byte[MAXNAME], zoneName));
+      f.writeInt(starts.get(zoneName));
+      f.writeInt(lengths.get(zoneName));
+      f.writeInt(offsets.get(zoneName));
+    }
+
+    int data_offset = (int) f.getFilePointer();
+
+    // Write the data.
+    f.write(allData.toByteArray());
+
+    // TODO: append the zonetab.
+    int zonetab_offset = 0;
+
+    // Go back and fix up the offsets in the header.
+    f.seek(index_offset_offset);
+    f.writeInt(index_offset);
+    f.seek(data_offset_offset);
+    f.writeInt(data_offset);
+    f.seek(zonetab_offset_offset);
+    f.writeInt(zonetab_offset);
+
+    f.close();
+  }
+
+  private static byte[] toAscii(byte[] dst, String src) {
+    for (int i = 0; i < src.length(); ++i) {
+      if (src.charAt(i) > '~') {
+        throw new RuntimeException("non-ASCII string: " + src);
+      }
+      dst[i] = (byte) src.charAt(i);
+    }
+    return dst;
+  }
+
+  public static void main(String[] args) throws Exception {
+    if (args.length != 4) {
+      System.err.println("usage: java ZoneCompactor <setup file> <data directory> <output directory> <tzdata version>");
+      System.exit(0);
+    }
+    new ZoneCompactor(args[0], args[1], args[2], args[3]);
+  }
 }
