1d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// Protocol Buffers - Google's data interchange format
2d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// Copyright 2008 Google Inc.  All rights reserved.
3d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// http://code.google.com/p/protobuf/
4d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville//
5d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// Redistribution and use in source and binary forms, with or without
6d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// modification, are permitted provided that the following conditions are
7d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// met:
8d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville//
9d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville//     * Redistributions of source code must retain the above copyright
10d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// notice, this list of conditions and the following disclaimer.
11d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville//     * Redistributions in binary form must reproduce the above
12d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// copyright notice, this list of conditions and the following disclaimer
13d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// in the documentation and/or other materials provided with the
14d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// distribution.
15d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville//     * Neither the name of Google Inc. nor the names of its
16d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// contributors may be used to endorse or promote products derived from
17d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// this software without specific prior written permission.
18d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville//
19d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
31d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// Author: ambrose@google.com (Ambrose Feinstein),
32d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville//         kenton@google.com (Kenton Varda)
33d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville//
34d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// Based on http://www.pkware.com/documents/casestudies/APPNOTE.TXT
35d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
36d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <google/protobuf/compiler/zip_writer.h>
37d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <google/protobuf/io/coded_stream.h>
38d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
39d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillenamespace google {
40d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillenamespace protobuf {
41d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillenamespace compiler {
42d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
43d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillestatic const uint32 kCRC32Table[256] = {
44d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
45d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
46d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
47d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
48d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
49d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
50d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
51d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
52d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
53d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
54d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
55d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
56d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
57d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
58d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
59d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
60d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
61d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
62d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
63d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
64d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
65d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
66d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
67d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
68d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
69d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
70d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
71d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
72d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
73d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
74d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
75d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
76d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
77d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
78d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
79d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
80d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
81d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
82d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
83d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
84d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
85d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
86d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
87d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville};
88d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
89d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillestatic uint32 ComputeCRC32(const string &buf) {
90d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  uint32 x = ~0U;
91d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  for (int i = 0; i < buf.size(); ++i) {
92d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    unsigned char c = buf[i];
93d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    x = kCRC32Table[(x ^ c) & 0xff] ^ (x >> 8);
94d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
95d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return ~x;
96d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}
97d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
98d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillestatic void WriteShort(io::CodedOutputStream *out, uint16 val) {
99d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  uint8 p[2];
100d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  p[0] = static_cast<uint8>(val);
101d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  p[1] = static_cast<uint8>(val >> 8);
102d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  out->WriteRaw(p, 2);
103d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}
104d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
105d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleZipWriter::ZipWriter(io::ZeroCopyOutputStream* raw_output)
106d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  : raw_output_(raw_output) {}
107d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleZipWriter::~ZipWriter() {}
108d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
109d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillebool ZipWriter::Write(const string& filename, const string& contents) {
110d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  FileInfo info;
111d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
112d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  info.name = filename;
113d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  uint16 filename_size = filename.size();
114d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  info.offset = raw_output_->ByteCount();
115d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  info.size = contents.size();
116d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  info.crc32 = ComputeCRC32(contents);
117d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
118d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  files_.push_back(info);
119d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
120d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // write file header
121d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  io::CodedOutputStream output(raw_output_);
122d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  output.WriteLittleEndian32(0x04034b50);  // magic
123d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  WriteShort(&output, 10);  // version needed to extract
124d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  WriteShort(&output, 0);  // flags
125d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  WriteShort(&output, 0);  // compression method: stored
126d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  WriteShort(&output, 0);  // last modified time
127d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  WriteShort(&output, 0);  // last modified date
128d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  output.WriteLittleEndian32(info.crc32);  // crc-32
129d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  output.WriteLittleEndian32(info.size);  // compressed size
130d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  output.WriteLittleEndian32(info.size);  // uncompressed size
131d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  WriteShort(&output, filename_size);  // file name length
132d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  WriteShort(&output, 0);   // extra field length
133d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  output.WriteString(filename);  // file name
134d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  output.WriteString(contents);  // file data
135d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
136d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return !output.HadError();
137d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}
138d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
139d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillebool ZipWriter::WriteDirectory() {
140d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  uint16 num_entries = files_.size();
141d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  uint32 dir_ofs = raw_output_->ByteCount();
142d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
143d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // write central directory
144d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  io::CodedOutputStream output(raw_output_);
145d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  for (int i = 0; i < num_entries; ++i) {
146d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    const string &filename = files_[i].name;
147d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    uint16 filename_size = filename.size();
148d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    uint32 crc32 = files_[i].crc32;
149d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    uint32 size = files_[i].size;
150d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    uint32 offset = files_[i].offset;
151d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
152d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    output.WriteLittleEndian32(0x02014b50);  // magic
153d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    WriteShort(&output, 10);  // version made by
154d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    WriteShort(&output, 10);  // version needed to extract
155d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    WriteShort(&output, 0);  // flags
156d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    WriteShort(&output, 0);  // compression method: stored
157d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    WriteShort(&output, 0);  // last modified time
158d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    WriteShort(&output, 0);  // last modified date
159d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    output.WriteLittleEndian32(crc32);  // crc-32
160d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    output.WriteLittleEndian32(size);  // compressed size
161d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    output.WriteLittleEndian32(size);  // uncompressed size
162d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    WriteShort(&output, filename_size);  // file name length
163d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    WriteShort(&output, 0);   // extra field length
164d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    WriteShort(&output, 0);   // file comment length
165d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    WriteShort(&output, 0);   // starting disk number
166d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    WriteShort(&output, 0);   // internal file attributes
167d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    output.WriteLittleEndian32(0);  // external file attributes
168d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    output.WriteLittleEndian32(offset);  // local header offset
169d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    output.WriteString(filename);  // file name
170d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
171d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  uint32 dir_len = output.ByteCount();
172d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
173d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // write end of central directory marker
174d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  output.WriteLittleEndian32(0x06054b50);  // magic
175d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  WriteShort(&output, 0);  // disk number
176d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  WriteShort(&output, 0);  // disk with start of central directory
177d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  WriteShort(&output, num_entries);  // central directory entries (this disk)
178d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  WriteShort(&output, num_entries);  // central directory entries (total)
179d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  output.WriteLittleEndian32(dir_len);  // central directory byte size
180d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  output.WriteLittleEndian32(dir_ofs);  // central directory offset
181d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  WriteShort(&output, 0);   // comment length
182d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
183d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return output.HadError();
184d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}
185d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
186d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}  // namespace google
187d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}  // namespace protobuf
188d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}  // namespace compiler
189