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
19a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski#include <cstdio>
201ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include <memory>
211ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include <string>
221ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include <vector>
231ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
2406460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski#include "android-base/errors.h"
25ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "android-base/macros.h"
26d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski#include "androidfw/StringPiece.h"
27ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "ziparchive/zip_writer.h"
28ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
29ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "util/Files.h"
30d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski
31d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinskiusing android::StringPiece;
32ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
331ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskinamespace aapt {
341ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
351ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskinamespace {
361ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
37ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiclass DirectoryWriter : public IArchiveWriter {
38ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski public:
39ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  DirectoryWriter() = default;
40cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
4106460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski  bool Open(const StringPiece& out_dir) {
42d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski    dir_ = out_dir.to_string();
43ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    file::FileType type = file::GetFileType(dir_);
44cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (type == file::FileType::kNonexistant) {
4506460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski      error_ = "directory does not exist";
46cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
47cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    } else if (type != file::FileType::kDirectory) {
4806460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski      error_ = "not a directory";
49cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
50cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
51cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
52cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
53cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
54ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool StartEntry(const StringPiece& path, uint32_t flags) override {
55ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (file_) {
56cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
57cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
58cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
59ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::string full_path = dir_;
60ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    file::AppendPath(&full_path, path);
61ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    file::mkdirs(file::GetStem(full_path));
62cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
63ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    file_ = {fopen(full_path.data(), "wb"), fclose};
64ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!file_) {
6506460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski      error_ = android::base::SystemErrorCodeToString(errno);
66cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
67cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
68cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
69cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
70cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
7106460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski  bool Write(const void* data, int len) override {
72ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!file_) {
73cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
74cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
75cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
7606460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski    if (fwrite(data, 1, len, file_.get()) != static_cast<size_t>(len)) {
7706460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski      error_ = android::base::SystemErrorCodeToString(errno);
78ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      file_.reset(nullptr);
79cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
80cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
81cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
82cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
83cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
84ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool FinishEntry() override {
85ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!file_) {
86cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
871ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
88ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    file_.reset(nullptr);
89cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
90cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
91ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
9206460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski  bool WriteFile(const StringPiece& path, uint32_t flags, io::InputStream* in) override {
9306460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski    if (!StartEntry(path, flags)) {
9406460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski      return false;
9506460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski    }
9606460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski
9706460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski    const void* data = nullptr;
9806460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski    size_t len = 0;
9906460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski    while (in->Next(&data, &len)) {
10006460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski      if (!Write(data, static_cast<int>(len))) {
10106460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski        return false;
10206460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski      }
10306460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski    }
10406460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski    return !in->HadError();
10506460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski  }
10606460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski
10706460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski  bool HadError() const override { return !error_.empty(); }
10806460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski
10906460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski  std::string GetError() const override { return error_; }
11006460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski
111ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski private:
112ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  DISALLOW_COPY_AND_ASSIGN(DirectoryWriter);
113ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
114ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::string dir_;
115ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<FILE, decltype(fclose)*> file_ = {nullptr, fclose};
11606460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski  std::string error_;
1171ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski};
1181ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
119ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiclass ZipFileWriter : public IArchiveWriter {
120ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski public:
121ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ZipFileWriter() = default;
122cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
12306460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski  bool Open(const StringPiece& path) {
124ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    file_ = {fopen(path.data(), "w+b"), fclose};
125ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!file_) {
12606460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski      error_ = android::base::SystemErrorCodeToString(errno);
127cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1281ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
129ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    writer_ = util::make_unique<ZipWriter>(file_.get());
130cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
131cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1321ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
133ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool StartEntry(const StringPiece& path, uint32_t flags) override {
134ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!writer_) {
135cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
136cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
138ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    size_t zip_flags = 0;
139cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (flags & ArchiveEntry::kCompress) {
140ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      zip_flags |= ZipWriter::kCompress;
141cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
142a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski
143cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (flags & ArchiveEntry::kAlign) {
144ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      zip_flags |= ZipWriter::kAlign32;
145a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski    }
1461ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
147ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    int32_t result = writer_->StartEntry(path.data(), zip_flags);
148cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (result != 0) {
14906460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski      error_ = ZipWriter::ErrorCodeString(result);
150cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
151cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
152cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
153cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
154cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
15506460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski  bool Write(const void* data, int len) override {
156ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    int32_t result = writer_->WriteBytes(data, len);
157cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (result != 0) {
15806460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski      error_ = ZipWriter::ErrorCodeString(result);
159cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
160cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
161cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
162cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
163cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
164ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool FinishEntry() override {
165ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    int32_t result = writer_->FinishEntry();
166cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (result != 0) {
16706460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski      error_ = ZipWriter::ErrorCodeString(result);
168cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
169a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski    }
170cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
171cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
172cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
17306460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski  bool WriteFile(const StringPiece& path, uint32_t flags, io::InputStream* in) override {
17406460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski    while (true) {
17506460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski      if (!StartEntry(path, flags)) {
17606460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski        return false;
17706460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski      }
17806460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski
17906460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski      const void* data = nullptr;
18006460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski      size_t len = 0;
18106460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski      while (in->Next(&data, &len)) {
18206460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski        if (!Write(data, static_cast<int>(len))) {
18306460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski          return false;
18406460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski        }
18506460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski      }
18606460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski
18706460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski      if (in->HadError()) {
18806460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski        return false;
18906460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski      }
19006460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski
19106460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski      if (!FinishEntry()) {
19206460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski        return false;
19306460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski      }
19406460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski
19506460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski      // Check to see if the file was compressed enough. This is preserving behavior of AAPT.
19606460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski      if ((flags & ArchiveEntry::kCompress) != 0 && in->CanRewind()) {
19706460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski        ZipWriter::FileEntry last_entry;
19806460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski        int32_t result = writer_->GetLastEntry(&last_entry);
19906460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski        CHECK(result == 0);
20006460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski        if (last_entry.compressed_size + (last_entry.compressed_size / 10) >
20106460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski            last_entry.uncompressed_size) {
20206460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski          // The file was not compressed enough, rewind and store it uncompressed.
20306460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski          if (!in->Rewind()) {
20406460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski            // Well we tried, may as well keep what we had.
20506460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski            return true;
20606460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski          }
20706460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski
20806460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski          int32_t result = writer_->DiscardLastEntry();
20906460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski          if (result != 0) {
21006460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski            error_ = ZipWriter::ErrorCodeString(result);
21106460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski            return false;
21206460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski          }
21306460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski          flags &= ~ArchiveEntry::kCompress;
21406460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski
21506460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski          continue;
21606460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski        }
21706460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski      }
21806460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski      return true;
21906460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski    }
22006460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski  }
22106460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski
22206460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski  bool HadError() const override { return !error_.empty(); }
22306460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski
22406460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski  std::string GetError() const override { return error_; }
22506460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski
226cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  virtual ~ZipFileWriter() {
227ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (writer_) {
228ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      writer_->Finish();
229cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
230cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
231ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
232ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski private:
233ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  DISALLOW_COPY_AND_ASSIGN(ZipFileWriter);
234ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
235ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<FILE, decltype(fclose)*> file_ = {nullptr, fclose};
236ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<ZipWriter> writer_;
23706460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski  std::string error_;
238cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski};
239cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
240cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski}  // namespace
241cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
24206460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinskistd::unique_ptr<IArchiveWriter> CreateDirectoryArchiveWriter(IDiagnostics* diag,
24306460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski                                                             const StringPiece& path) {
24406460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski  std::unique_ptr<DirectoryWriter> writer = util::make_unique<DirectoryWriter>();
24506460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski  if (!writer->Open(path)) {
24606460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski    diag->Error(DiagMessage(path) << writer->GetError());
247cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return {};
248cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
249cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  return std::move(writer);
250cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski}
251cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
25206460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinskistd::unique_ptr<IArchiveWriter> CreateZipFileArchiveWriter(IDiagnostics* diag,
25306460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski                                                           const StringPiece& path) {
254cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  std::unique_ptr<ZipFileWriter> writer = util::make_unique<ZipFileWriter>();
25506460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski  if (!writer->Open(path)) {
25606460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski    diag->Error(DiagMessage(path) << writer->GetError());
257cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return {};
258cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
259cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  return std::move(writer);
2601ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski}
2611ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
262cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski}  // namespace aapt
263