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