1004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski/*
2004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski * Copyright (C) 2017 The Android Open Source Project
3004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski *
4004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
5004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski * you may not use this file except in compliance with the License.
6004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski * You may obtain a copy of the License at
7004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski *
8004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
9004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski *
10004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski * Unless required by applicable law or agreed to in writing, software
11004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
12004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski * See the License for the specific language governing permissions and
14004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski * limitations under the License.
15004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski */
16004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
17004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski#include "format/Container.h"
18004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
19004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski#include "android-base/scopeguard.h"
20004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski#include "android-base/stringprintf.h"
21004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
22004511660671511ae88e0e837a6f92db28eadaefAdam Lesinskiusing ::android::base::StringPrintf;
23004511660671511ae88e0e837a6f92db28eadaefAdam Lesinskiusing ::google::protobuf::io::CodedInputStream;
24004511660671511ae88e0e837a6f92db28eadaefAdam Lesinskiusing ::google::protobuf::io::CodedOutputStream;
25004511660671511ae88e0e837a6f92db28eadaefAdam Lesinskiusing ::google::protobuf::io::ZeroCopyOutputStream;
26004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
27004511660671511ae88e0e837a6f92db28eadaefAdam Lesinskinamespace aapt {
28004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
29004511660671511ae88e0e837a6f92db28eadaefAdam Lesinskiconstexpr const static uint32_t kContainerFormatMagic = 0x54504141u;
30004511660671511ae88e0e837a6f92db28eadaefAdam Lesinskiconstexpr const static uint32_t kContainerFormatVersion = 1u;
31004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
32004511660671511ae88e0e837a6f92db28eadaefAdam LesinskiContainerWriter::ContainerWriter(ZeroCopyOutputStream* out, size_t entry_count)
33004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    : out_(out), total_entry_count_(entry_count), current_entry_count_(0u) {
34004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  CodedOutputStream coded_out(out_);
35004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
36004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  // Write the magic.
37004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  coded_out.WriteLittleEndian32(kContainerFormatMagic);
38004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
39004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  // Write the version.
40004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  coded_out.WriteLittleEndian32(kContainerFormatVersion);
41004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
42004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  // Write the total number of entries.
43004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  coded_out.WriteLittleEndian32(static_cast<uint32_t>(total_entry_count_));
44004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
45004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  if (coded_out.HadError()) {
46004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    error_ = "failed writing container format header";
47004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  }
48004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski}
49004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
50004511660671511ae88e0e837a6f92db28eadaefAdam Lesinskiinline static void WritePadding(int padding, CodedOutputStream* out) {
51004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  if (padding < 4) {
52004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    const uint32_t zero = 0u;
53004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    out->WriteRaw(&zero, padding);
54004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  }
55004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski}
56004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
57004511660671511ae88e0e837a6f92db28eadaefAdam Lesinskibool ContainerWriter::AddResTableEntry(const pb::ResourceTable& table) {
58004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  if (current_entry_count_ >= total_entry_count_) {
59004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    error_ = "too many entries being serialized";
60004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    return false;
61004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  }
62004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  current_entry_count_++;
63004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
64004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  CodedOutputStream coded_out(out_);
65004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
66004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  // Write the type.
67004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  coded_out.WriteLittleEndian32(kResTable);
68004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
69004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  // Write the aligned size.
70004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  const ::google::protobuf::uint64 size = table.ByteSize();
71004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  const int padding = 4 - (size % 4);
72004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  coded_out.WriteLittleEndian64(size);
73004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
74004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  // Write the table.
75004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  table.SerializeWithCachedSizes(&coded_out);
76004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
77004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  // Write the padding.
78004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  WritePadding(padding, &coded_out);
79004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
80004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  if (coded_out.HadError()) {
81004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    error_ = "failed writing to output";
82004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    return false;
83004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  }
84004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  return true;
85004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski}
86004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
87004511660671511ae88e0e837a6f92db28eadaefAdam Lesinskibool ContainerWriter::AddResFileEntry(const pb::internal::CompiledFile& file,
88004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski                                      io::KnownSizeInputStream* in) {
89004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  if (current_entry_count_ >= total_entry_count_) {
90004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    error_ = "too many entries being serialized";
91004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    return false;
92004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  }
93004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  current_entry_count_++;
94004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
95004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  constexpr const static int kResFileEntryHeaderSize = 12;
96004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
97004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  CodedOutputStream coded_out(out_);
98004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
99004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  // Write the type.
100004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  coded_out.WriteLittleEndian32(kResFile);
101004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
102004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  // Write the aligned size.
103004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  const ::google::protobuf::uint32 header_size = file.ByteSize();
104004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  const int header_padding = 4 - (header_size % 4);
105004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  const ::google::protobuf::uint64 data_size = in->TotalSize();
106004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  const int data_padding = 4 - (data_size % 4);
107004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  coded_out.WriteLittleEndian64(kResFileEntryHeaderSize + header_size + header_padding + data_size +
108004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski                                data_padding);
109004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
110004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  // Write the res file header size.
111004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  coded_out.WriteLittleEndian32(header_size);
112004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
113004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  // Write the data payload size.
114004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  coded_out.WriteLittleEndian64(data_size);
115004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
116004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  // Write the header.
117004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  file.SerializeToCodedStream(&coded_out);
118004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
119004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  WritePadding(header_padding, &coded_out);
120004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
121004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  // Write the data payload. We need to call Trim() since we are going to write to the underlying
122004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  // ZeroCopyOutputStream.
123004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  coded_out.Trim();
124004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
125004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  // Check at this point if there were any errors.
126004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  if (coded_out.HadError()) {
127004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    error_ = "failed writing to output";
128004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    return false;
129004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  }
130004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
131004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  if (!io::Copy(out_, in)) {
132004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    if (in->HadError()) {
133004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski      std::ostringstream error;
134004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski      error << "failed reading from input: " << in->GetError();
135004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski      error_ = error.str();
136004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    } else {
137004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski      error_ = "failed writing to output";
138004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    }
139004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    return false;
140004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  }
141004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  WritePadding(data_padding, &coded_out);
142004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
143004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  if (coded_out.HadError()) {
144004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    error_ = "failed writing to output";
145004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    return false;
146004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  }
147004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  return true;
148004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski}
149004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
150004511660671511ae88e0e837a6f92db28eadaefAdam Lesinskibool ContainerWriter::HadError() const {
151004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  return !error_.empty();
152004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski}
153004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
154004511660671511ae88e0e837a6f92db28eadaefAdam Lesinskistd::string ContainerWriter::GetError() const {
155004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  return error_;
156004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski}
157004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
158004511660671511ae88e0e837a6f92db28eadaefAdam Lesinskistatic bool AlignRead(CodedInputStream* in) {
159004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  const int padding = 4 - (in->CurrentPosition() % 4);
160004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  if (padding < 4) {
161004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    return in->Skip(padding);
162004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  }
163004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  return true;
164004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski}
165004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
166004511660671511ae88e0e837a6f92db28eadaefAdam LesinskiContainerReaderEntry::ContainerReaderEntry(ContainerReader* reader) : reader_(reader) {
167004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski}
168004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
169004511660671511ae88e0e837a6f92db28eadaefAdam LesinskiContainerEntryType ContainerReaderEntry::Type() const {
170004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  return type_;
171004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski}
172004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
173004511660671511ae88e0e837a6f92db28eadaefAdam Lesinskibool ContainerReaderEntry::GetResTable(pb::ResourceTable* out_table) {
174004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  CHECK(type_ == ContainerEntryType::kResTable) << "reading a kResTable when the type is kResFile";
175004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  if (length_ > std::numeric_limits<int>::max()) {
176004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    reader_->error_ = StringPrintf("entry length %zu is too large", length_);
177004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    return false;
178004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  }
179004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
180004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  CodedInputStream& coded_in = reader_->coded_in_;
181004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
182004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  const CodedInputStream::Limit limit = coded_in.PushLimit(static_cast<int>(length_));
183004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  auto guard = ::android::base::make_scope_guard([&]() { coded_in.PopLimit(limit); });
184004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
185004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  if (!out_table->ParseFromCodedStream(&coded_in)) {
186004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    reader_->error_ = "failed to parse ResourceTable";
187004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    return false;
188004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  }
189004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  return true;
190004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski}
191004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
192004511660671511ae88e0e837a6f92db28eadaefAdam Lesinskibool ContainerReaderEntry::GetResFileOffsets(pb::internal::CompiledFile* out_file,
193004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski                                             off64_t* out_offset, size_t* out_len) {
194004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  CHECK(type_ == ContainerEntryType::kResFile) << "reading a kResFile when the type is kResTable";
195004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
196004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  CodedInputStream& coded_in = reader_->coded_in_;
197004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
198004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  // Read the ResFile header.
199004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  ::google::protobuf::uint32 header_length;
200004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  if (!coded_in.ReadLittleEndian32(&header_length)) {
201004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    std::ostringstream error;
202004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    error << "failed to read header length from input: " << reader_->in_->GetError();
203004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    reader_->error_ = error.str();
204004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    return false;
205004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  }
206004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
207004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  ::google::protobuf::uint64 data_length;
208004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  if (!coded_in.ReadLittleEndian64(&data_length)) {
209004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    std::ostringstream error;
210004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    error << "failed to read data length from input: " << reader_->in_->GetError();
211004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    reader_->error_ = error.str();
212004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    return false;
213004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  }
214004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
215004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  if (header_length > std::numeric_limits<int>::max()) {
216004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    std::ostringstream error;
217004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    error << "header length " << header_length << " is too large";
218004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    reader_->error_ = error.str();
219004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    return false;
220004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  }
221004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
222004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  if (data_length > std::numeric_limits<size_t>::max()) {
223004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    std::ostringstream error;
224004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    error << "data length " << data_length << " is too large";
225004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    reader_->error_ = error.str();
226004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    return false;
227004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  }
228004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
229004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  {
230004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    const CodedInputStream::Limit limit = coded_in.PushLimit(static_cast<int>(header_length));
231004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    auto guard = ::android::base::make_scope_guard([&]() { coded_in.PopLimit(limit); });
232004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
233004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    if (!out_file->ParseFromCodedStream(&coded_in)) {
234004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski      reader_->error_ = "failed to parse CompiledFile header";
235004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski      return false;
236004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    }
237004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  }
238004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
239004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  AlignRead(&coded_in);
240004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
241004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  *out_offset = coded_in.CurrentPosition();
242004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  *out_len = data_length;
243004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
244004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  coded_in.Skip(static_cast<int>(data_length));
245004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  AlignRead(&coded_in);
246004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  return true;
247004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski}
248004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
249004511660671511ae88e0e837a6f92db28eadaefAdam Lesinskibool ContainerReaderEntry::HadError() const {
250004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  return reader_->HadError();
251004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski}
252004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
253004511660671511ae88e0e837a6f92db28eadaefAdam Lesinskistd::string ContainerReaderEntry::GetError() const {
254004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  return reader_->GetError();
255004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski}
256004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
257004511660671511ae88e0e837a6f92db28eadaefAdam LesinskiContainerReader::ContainerReader(io::InputStream* in)
258004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    : in_(in),
259004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski      adaptor_(in),
260004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski      coded_in_(&adaptor_),
261004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski      total_entry_count_(0u),
262004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski      current_entry_count_(0u),
263004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski      entry_(this) {
264004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  ::google::protobuf::uint32 magic;
265004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  if (!coded_in_.ReadLittleEndian32(&magic)) {
266004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    std::ostringstream error;
267004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    error << "failed to read magic from input: " << in_->GetError();
268004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    error_ = error.str();
269004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    return;
270004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  }
271004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
272004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  if (magic != kContainerFormatMagic) {
273004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    error_ = "magic value doesn't match AAPT";
274004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    return;
275004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  }
276004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
277004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  ::google::protobuf::uint32 version;
278004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  if (!coded_in_.ReadLittleEndian32(&version)) {
279004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    std::ostringstream error;
280004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    error << "failed to read version from input: " << in_->GetError();
281004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    error_ = error.str();
282004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    return;
283004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  }
284004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
285004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  if (version != kContainerFormatVersion) {
286004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    error_ = StringPrintf("container version is 0x%08x but AAPT expects version 0x%08x", version,
287004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski                          kContainerFormatVersion);
288004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    return;
289004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  }
290004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
291004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  ::google::protobuf::uint32 total_entry_count;
292004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  if (!coded_in_.ReadLittleEndian32(&total_entry_count)) {
293004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    std::ostringstream error;
294004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    error << "failed to read entry count from input: " << in_->GetError();
295004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    error_ = error.str();
296004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    return;
297004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  }
298004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
299004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  total_entry_count_ = total_entry_count;
300004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski}
301004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
302004511660671511ae88e0e837a6f92db28eadaefAdam LesinskiContainerReaderEntry* ContainerReader::Next() {
303004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  if (current_entry_count_ >= total_entry_count_) {
304004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    return nullptr;
305004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  }
306004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  current_entry_count_++;
307004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
308004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  // Ensure the next read is aligned.
309004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  AlignRead(&coded_in_);
310004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
311004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  ::google::protobuf::uint32 entry_type;
312004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  if (!coded_in_.ReadLittleEndian32(&entry_type)) {
313004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    std::ostringstream error;
314004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    error << "failed reading entry type from input: " << in_->GetError();
315004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    error_ = error.str();
316004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    return nullptr;
317004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  }
318004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
319004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  ::google::protobuf::uint64 entry_length;
320004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  if (!coded_in_.ReadLittleEndian64(&entry_length)) {
321004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    std::ostringstream error;
322004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    error << "failed reading entry length from input: " << in_->GetError();
323004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    error_ = error.str();
324004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    return nullptr;
325004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  }
326004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
327004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  if (entry_type == ContainerEntryType::kResFile || entry_type == ContainerEntryType::kResTable) {
328004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    entry_.type_ = static_cast<ContainerEntryType>(entry_type);
329004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  } else {
330004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    error_ = StringPrintf("entry type 0x%08x is invalid", entry_type);
331004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    return nullptr;
332004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  }
333004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
334004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  if (entry_length > std::numeric_limits<size_t>::max()) {
335004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    std::ostringstream error;
336004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    error << "entry length " << entry_length << " is too large";
337004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    error_ = error.str();
338004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    return nullptr;
339004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  }
340004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
341004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  entry_.length_ = entry_length;
342004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  return &entry_;
343004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski}
344004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
345004511660671511ae88e0e837a6f92db28eadaefAdam Lesinskibool ContainerReader::HadError() const {
346004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  return !error_.empty();
347004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski}
348004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
349004511660671511ae88e0e837a6f92db28eadaefAdam Lesinskistd::string ContainerReader::GetError() const {
350004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  return error_;
351004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski}
352004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
353004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski}  // namespace aapt
354