11ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski/* 21ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Copyright (C) 2015 The Android Open Source Project 31ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * 41ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 51ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * you may not use this file except in compliance with the License. 61ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * You may obtain a copy of the License at 71ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * 81ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 91ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * 101ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Unless required by applicable law or agreed to in writing, software 111ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 121ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * See the License for the specific language governing permissions and 141ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * limitations under the License. 151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski */ 161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 171ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "flatten/Archive.h" 181ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "util/Files.h" 191ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "util/StringPiece.h" 201ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 21a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski#include <cstdio> 221ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include <memory> 231ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include <string> 241ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include <vector> 251ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include <ziparchive/zip_writer.h> 261ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 271ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskinamespace aapt { 281ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 291ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskinamespace { 301ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 311ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskistruct DirectoryWriter : public IArchiveWriter { 321ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski std::string mOutDir; 33a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski std::unique_ptr<FILE, decltype(fclose)*> mFile = { nullptr, fclose }; 34a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski 35a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski bool open(IDiagnostics* diag, const StringPiece& outDir) { 36a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski mOutDir = outDir.toString(); 37a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski file::FileType type = file::getFileType(mOutDir); 38a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski if (type == file::FileType::kNonexistant) { 39a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski diag->error(DiagMessage() << "directory " << mOutDir << " does not exist"); 40a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski return false; 41a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski } else if (type != file::FileType::kDirectory) { 42a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski diag->error(DiagMessage() << mOutDir << " is not a directory"); 43a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski return false; 44a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski } 45a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski return true; 461ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 471ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 48a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski bool startEntry(const StringPiece& path, uint32_t flags) override { 49a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski if (mFile) { 50a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski return false; 511ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 521ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 531ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski std::string fullPath = mOutDir; 541ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski file::appendPath(&fullPath, path); 551ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski file::mkdirs(file::getStem(fullPath)); 561ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 57a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski mFile = { fopen(fullPath.data(), "wb"), fclose }; 58a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski if (!mFile) { 59a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski return false; 601ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 61a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski return true; 62a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski } 631ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 64a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski bool writeEntry(const BigBuffer& buffer) override { 65a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski if (!mFile) { 66a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski return false; 671ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 681ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 69a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski for (const BigBuffer::Block& b : buffer) { 70a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski if (fwrite(b.buffer.get(), 1, b.size, mFile.get()) != b.size) { 71a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski mFile.reset(nullptr); 72a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski return false; 73a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski } 74a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski } 75a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski return true; 761ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 771ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 78a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski bool writeEntry(const void* data, size_t len) override { 79a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski if (fwrite(data, 1, len, mFile.get()) != len) { 80a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski mFile.reset(nullptr); 81a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski return false; 82a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski } 83a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski return true; 84a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski } 851ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 86a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski bool finishEntry() override { 87a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski if (!mFile) { 88a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski return false; 89a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski } 90a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski mFile.reset(nullptr); 91a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski return true; 921ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 931ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski}; 941ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 951ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskistruct ZipFileWriter : public IArchiveWriter { 96a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski std::unique_ptr<FILE, decltype(fclose)*> mFile = { nullptr, fclose }; 971ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski std::unique_ptr<ZipWriter> mWriter; 981ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 99a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski bool open(IDiagnostics* diag, const StringPiece& path) { 100a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski mFile = { fopen(path.data(), "w+b"), fclose }; 101a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski if (!mFile) { 102a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski diag->error(DiagMessage() << "failed to open " << path << ": " << strerror(errno)); 103a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski return false; 1041ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 105a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski mWriter = util::make_unique<ZipWriter>(mFile.get()); 106a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski return true; 1071ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1081ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 109a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski bool startEntry(const StringPiece& path, uint32_t flags) override { 1101ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (!mWriter) { 111a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski return false; 1121ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1131ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1141ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski size_t zipFlags = 0; 1151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (flags & ArchiveEntry::kCompress) { 1161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski zipFlags |= ZipWriter::kCompress; 1171ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1181ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1191ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (flags & ArchiveEntry::kAlign) { 1201ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski zipFlags |= ZipWriter::kAlign32; 1211ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1221ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1231ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski int32_t result = mWriter->StartEntry(path.data(), zipFlags); 1241ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (result != 0) { 125a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski return false; 1261ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 127a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski return true; 1281ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1291ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 130a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski bool writeEntry(const void* data, size_t len) override { 131a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski int32_t result = mWriter->WriteBytes(data, len); 1321ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (result != 0) { 133a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski return false; 1341ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 135a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski return true; 136a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski } 1371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 138a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski bool writeEntry(const BigBuffer& buffer) override { 139a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski for (const BigBuffer::Block& b : buffer) { 140a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski int32_t result = mWriter->WriteBytes(b.buffer.get(), b.size); 141a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski if (result != 0) { 142a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski return false; 143a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski } 1441ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 145a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski return true; 146a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski } 1471ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 148a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski bool finishEntry() override { 149a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski int32_t result = mWriter->FinishEntry(); 1501ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (result != 0) { 151a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski return false; 1521ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 153a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski return true; 1541ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1551ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1561ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski virtual ~ZipFileWriter() { 1571ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (mWriter) { 1581ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski mWriter->Finish(); 1591ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1601ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1611ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski}; 1621ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1631ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} // namespace 1641ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 165a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinskistd::unique_ptr<IArchiveWriter> createDirectoryArchiveWriter(IDiagnostics* diag, 166a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski const StringPiece& path) { 167a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski 168a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski std::unique_ptr<DirectoryWriter> writer = util::make_unique<DirectoryWriter>(); 169a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski if (!writer->open(diag, path)) { 170a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski return {}; 171a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski } 172a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski return std::move(writer); 1731ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 1741ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 175a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinskistd::unique_ptr<IArchiveWriter> createZipFileArchiveWriter(IDiagnostics* diag, 176a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski const StringPiece& path) { 177a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski std::unique_ptr<ZipFileWriter> writer = util::make_unique<ZipFileWriter>(); 178a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski if (!writer->open(diag, path)) { 179a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski return {}; 180a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski } 181a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski return std::move(writer); 1821ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 1831ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1841ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} // namespace aapt 185