1*d57664e9SAndroid Build Coastguard Worker /*
2*d57664e9SAndroid Build Coastguard Worker * Copyright (C) 2017 The Android Open Source Project
3*d57664e9SAndroid Build Coastguard Worker *
4*d57664e9SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*d57664e9SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*d57664e9SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*d57664e9SAndroid Build Coastguard Worker *
8*d57664e9SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*d57664e9SAndroid Build Coastguard Worker *
10*d57664e9SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*d57664e9SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*d57664e9SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*d57664e9SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*d57664e9SAndroid Build Coastguard Worker * limitations under the License.
15*d57664e9SAndroid Build Coastguard Worker */
16*d57664e9SAndroid Build Coastguard Worker
17*d57664e9SAndroid Build Coastguard Worker #include "io/Util.h"
18*d57664e9SAndroid Build Coastguard Worker
19*d57664e9SAndroid Build Coastguard Worker #include "google/protobuf/io/zero_copy_stream_impl_lite.h"
20*d57664e9SAndroid Build Coastguard Worker
21*d57664e9SAndroid Build Coastguard Worker #include "trace/TraceBuffer.h"
22*d57664e9SAndroid Build Coastguard Worker
23*d57664e9SAndroid Build Coastguard Worker using ::android::StringPiece;
24*d57664e9SAndroid Build Coastguard Worker using ::google::protobuf::io::ZeroCopyOutputStream;
25*d57664e9SAndroid Build Coastguard Worker
26*d57664e9SAndroid Build Coastguard Worker namespace aapt {
27*d57664e9SAndroid Build Coastguard Worker namespace io {
28*d57664e9SAndroid Build Coastguard Worker
CopyInputStreamToArchive(IAaptContext * context,android::InputStream * in,std::string_view out_path,uint32_t compression_flags,IArchiveWriter * writer)29*d57664e9SAndroid Build Coastguard Worker bool CopyInputStreamToArchive(IAaptContext* context, android::InputStream* in,
30*d57664e9SAndroid Build Coastguard Worker std::string_view out_path, uint32_t compression_flags,
31*d57664e9SAndroid Build Coastguard Worker IArchiveWriter* writer) {
32*d57664e9SAndroid Build Coastguard Worker TRACE_CALL();
33*d57664e9SAndroid Build Coastguard Worker if (context->IsVerbose()) {
34*d57664e9SAndroid Build Coastguard Worker context->GetDiagnostics()->Note(android::DiagMessage()
35*d57664e9SAndroid Build Coastguard Worker << "writing " << out_path << " to archive");
36*d57664e9SAndroid Build Coastguard Worker }
37*d57664e9SAndroid Build Coastguard Worker
38*d57664e9SAndroid Build Coastguard Worker if (!writer->WriteFile(out_path, compression_flags, in)) {
39*d57664e9SAndroid Build Coastguard Worker context->GetDiagnostics()->Error(android::DiagMessage()
40*d57664e9SAndroid Build Coastguard Worker << "failed to write " << out_path
41*d57664e9SAndroid Build Coastguard Worker << " to archive: " << writer->GetError());
42*d57664e9SAndroid Build Coastguard Worker return false;
43*d57664e9SAndroid Build Coastguard Worker }
44*d57664e9SAndroid Build Coastguard Worker return true;
45*d57664e9SAndroid Build Coastguard Worker }
46*d57664e9SAndroid Build Coastguard Worker
CopyFileToArchive(IAaptContext * context,io::IFile * file,std::string_view out_path,uint32_t compression_flags,IArchiveWriter * writer)47*d57664e9SAndroid Build Coastguard Worker bool CopyFileToArchive(IAaptContext* context, io::IFile* file, std::string_view out_path,
48*d57664e9SAndroid Build Coastguard Worker uint32_t compression_flags, IArchiveWriter* writer) {
49*d57664e9SAndroid Build Coastguard Worker TRACE_CALL();
50*d57664e9SAndroid Build Coastguard Worker std::unique_ptr<io::IData> data = file->OpenAsData();
51*d57664e9SAndroid Build Coastguard Worker if (!data) {
52*d57664e9SAndroid Build Coastguard Worker context->GetDiagnostics()->Error(android::DiagMessage(file->GetSource())
53*d57664e9SAndroid Build Coastguard Worker << "failed to open file");
54*d57664e9SAndroid Build Coastguard Worker return false;
55*d57664e9SAndroid Build Coastguard Worker }
56*d57664e9SAndroid Build Coastguard Worker return CopyInputStreamToArchive(context, data.get(), out_path, compression_flags, writer);
57*d57664e9SAndroid Build Coastguard Worker }
58*d57664e9SAndroid Build Coastguard Worker
CopyFileToArchivePreserveCompression(IAaptContext * context,io::IFile * file,std::string_view out_path,IArchiveWriter * writer)59*d57664e9SAndroid Build Coastguard Worker bool CopyFileToArchivePreserveCompression(IAaptContext* context, io::IFile* file,
60*d57664e9SAndroid Build Coastguard Worker std::string_view out_path, IArchiveWriter* writer) {
61*d57664e9SAndroid Build Coastguard Worker uint32_t compression_flags = file->WasCompressed() ? ArchiveEntry::kCompress : 0u;
62*d57664e9SAndroid Build Coastguard Worker return CopyFileToArchive(context, file, out_path, compression_flags, writer);
63*d57664e9SAndroid Build Coastguard Worker }
64*d57664e9SAndroid Build Coastguard Worker
CopyProtoToArchive(IAaptContext * context,::google::protobuf::Message * proto_msg,std::string_view out_path,uint32_t compression_flags,IArchiveWriter * writer)65*d57664e9SAndroid Build Coastguard Worker bool CopyProtoToArchive(IAaptContext* context, ::google::protobuf::Message* proto_msg,
66*d57664e9SAndroid Build Coastguard Worker std::string_view out_path, uint32_t compression_flags,
67*d57664e9SAndroid Build Coastguard Worker IArchiveWriter* writer) {
68*d57664e9SAndroid Build Coastguard Worker TRACE_CALL();
69*d57664e9SAndroid Build Coastguard Worker if (context->IsVerbose()) {
70*d57664e9SAndroid Build Coastguard Worker context->GetDiagnostics()->Note(android::DiagMessage()
71*d57664e9SAndroid Build Coastguard Worker << "writing " << out_path << " to archive");
72*d57664e9SAndroid Build Coastguard Worker }
73*d57664e9SAndroid Build Coastguard Worker
74*d57664e9SAndroid Build Coastguard Worker if (writer->StartEntry(out_path, compression_flags)) {
75*d57664e9SAndroid Build Coastguard Worker // Make sure CopyingOutputStreamAdaptor is deleted before we call writer->FinishEntry().
76*d57664e9SAndroid Build Coastguard Worker {
77*d57664e9SAndroid Build Coastguard Worker // Wrap our IArchiveWriter with an adaptor that implements the ZeroCopyOutputStream interface.
78*d57664e9SAndroid Build Coastguard Worker ::google::protobuf::io::CopyingOutputStreamAdaptor adaptor(writer);
79*d57664e9SAndroid Build Coastguard Worker if (!proto_msg->SerializeToZeroCopyStream(&adaptor)) {
80*d57664e9SAndroid Build Coastguard Worker context->GetDiagnostics()->Error(android::DiagMessage()
81*d57664e9SAndroid Build Coastguard Worker << "failed to write " << out_path << " to archive");
82*d57664e9SAndroid Build Coastguard Worker return false;
83*d57664e9SAndroid Build Coastguard Worker }
84*d57664e9SAndroid Build Coastguard Worker }
85*d57664e9SAndroid Build Coastguard Worker
86*d57664e9SAndroid Build Coastguard Worker if (writer->FinishEntry()) {
87*d57664e9SAndroid Build Coastguard Worker return true;
88*d57664e9SAndroid Build Coastguard Worker }
89*d57664e9SAndroid Build Coastguard Worker }
90*d57664e9SAndroid Build Coastguard Worker context->GetDiagnostics()->Error(android::DiagMessage() << "failed to write " << out_path
91*d57664e9SAndroid Build Coastguard Worker << " to archive: " << writer->GetError());
92*d57664e9SAndroid Build Coastguard Worker return false;
93*d57664e9SAndroid Build Coastguard Worker }
94*d57664e9SAndroid Build Coastguard Worker
Copy(android::OutputStream * out,android::InputStream * in)95*d57664e9SAndroid Build Coastguard Worker bool Copy(android::OutputStream* out, android::InputStream* in) {
96*d57664e9SAndroid Build Coastguard Worker TRACE_CALL();
97*d57664e9SAndroid Build Coastguard Worker const void* in_buffer;
98*d57664e9SAndroid Build Coastguard Worker size_t in_len;
99*d57664e9SAndroid Build Coastguard Worker while (in->Next(&in_buffer, &in_len)) {
100*d57664e9SAndroid Build Coastguard Worker void* out_buffer;
101*d57664e9SAndroid Build Coastguard Worker size_t out_len;
102*d57664e9SAndroid Build Coastguard Worker if (!out->Next(&out_buffer, &out_len)) {
103*d57664e9SAndroid Build Coastguard Worker return !out->HadError();
104*d57664e9SAndroid Build Coastguard Worker }
105*d57664e9SAndroid Build Coastguard Worker
106*d57664e9SAndroid Build Coastguard Worker const size_t bytes_to_copy = in_len < out_len ? in_len : out_len;
107*d57664e9SAndroid Build Coastguard Worker memcpy(out_buffer, in_buffer, bytes_to_copy);
108*d57664e9SAndroid Build Coastguard Worker out->BackUp(out_len - bytes_to_copy);
109*d57664e9SAndroid Build Coastguard Worker in->BackUp(in_len - bytes_to_copy);
110*d57664e9SAndroid Build Coastguard Worker }
111*d57664e9SAndroid Build Coastguard Worker return !in->HadError();
112*d57664e9SAndroid Build Coastguard Worker }
113*d57664e9SAndroid Build Coastguard Worker
Copy(android::OutputStream * out,StringPiece in)114*d57664e9SAndroid Build Coastguard Worker bool Copy(android::OutputStream* out, StringPiece in) {
115*d57664e9SAndroid Build Coastguard Worker const char* in_buffer = in.data();
116*d57664e9SAndroid Build Coastguard Worker size_t in_len = in.size();
117*d57664e9SAndroid Build Coastguard Worker while (in_len != 0) {
118*d57664e9SAndroid Build Coastguard Worker void* out_buffer;
119*d57664e9SAndroid Build Coastguard Worker size_t out_len;
120*d57664e9SAndroid Build Coastguard Worker if (!out->Next(&out_buffer, &out_len)) {
121*d57664e9SAndroid Build Coastguard Worker return false;
122*d57664e9SAndroid Build Coastguard Worker }
123*d57664e9SAndroid Build Coastguard Worker
124*d57664e9SAndroid Build Coastguard Worker const size_t bytes_to_copy = in_len < out_len ? in_len : out_len;
125*d57664e9SAndroid Build Coastguard Worker memcpy(out_buffer, in_buffer, bytes_to_copy);
126*d57664e9SAndroid Build Coastguard Worker out->BackUp(out_len - bytes_to_copy);
127*d57664e9SAndroid Build Coastguard Worker in_buffer += bytes_to_copy;
128*d57664e9SAndroid Build Coastguard Worker in_len -= bytes_to_copy;
129*d57664e9SAndroid Build Coastguard Worker }
130*d57664e9SAndroid Build Coastguard Worker return true;
131*d57664e9SAndroid Build Coastguard Worker }
132*d57664e9SAndroid Build Coastguard Worker
Copy(ZeroCopyOutputStream * out,android::InputStream * in)133*d57664e9SAndroid Build Coastguard Worker bool Copy(ZeroCopyOutputStream* out, android::InputStream* in) {
134*d57664e9SAndroid Build Coastguard Worker OutputStreamAdaptor adaptor(out);
135*d57664e9SAndroid Build Coastguard Worker return Copy(&adaptor, in);
136*d57664e9SAndroid Build Coastguard Worker }
137*d57664e9SAndroid Build Coastguard Worker
138*d57664e9SAndroid Build Coastguard Worker } // namespace io
139*d57664e9SAndroid Build Coastguard Worker } // namespace aapt
140