AAPT2: Move all file output to FileOutputStream
FileOutputStream is safe to use on Windows, as it opens
files using our compatibility API.
Bug: 68262818
Test: make aapt2_tests
Change-Id: Ib0b27e93edd609b49b1327db7d9867a002198ebb
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index 66b5a7a..e94c0b4 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -16,7 +16,6 @@
#include <sys/stat.h>
-#include <fstream>
#include <queue>
#include <unordered_map>
#include <vector>
@@ -212,6 +211,8 @@
// This delegate will attempt to masquerade any '@id/' references with ID 0xPPTTEEEE,
// where PP > 7f, as 0x7fPPEEEE. Any potential overlapping is verified and an error occurs if such
// an overlap exists.
+//
+// See b/37498913.
class FeatureSplitSymbolTableDelegate : public DefaultSymbolTableDelegate {
public:
FeatureSplitSymbolTableDelegate(IAaptContext* context) : context_(context) {
@@ -652,24 +653,26 @@
static bool WriteStableIdMapToPath(IDiagnostics* diag,
const std::unordered_map<ResourceName, ResourceId>& id_map,
const std::string& id_map_path) {
- std::ofstream fout(id_map_path, std::ofstream::binary);
- if (!fout) {
- diag->Error(DiagMessage(id_map_path) << strerror(errno));
+ io::FileOutputStream fout(id_map_path);
+ if (fout.HadError()) {
+ diag->Error(DiagMessage(id_map_path) << "failed to open: " << fout.GetError());
return false;
}
+ text::Printer printer(&fout);
for (const auto& entry : id_map) {
const ResourceName& name = entry.first;
const ResourceId& id = entry.second;
- fout << name << " = " << id << "\n";
+ printer.Print(name.to_string());
+ printer.Print(" = ");
+ printer.Println(id.to_string());
}
+ fout.Flush();
- if (!fout) {
- diag->Error(DiagMessage(id_map_path) << "failed writing to file: "
- << android::base::SystemErrorCodeToString(errno));
+ if (fout.HadError()) {
+ diag->Error(DiagMessage(id_map_path) << "failed writing to file: " << fout.GetError());
return false;
}
-
return true;
}
@@ -985,36 +988,35 @@
file::AppendPath(&out_path, "R.java");
- std::ofstream fout(out_path, std::ofstream::binary);
- if (!fout) {
- context_->GetDiagnostics()->Error(DiagMessage()
- << "failed writing to '" << out_path
- << "': " << android::base::SystemErrorCodeToString(errno));
+ io::FileOutputStream fout(out_path);
+ if (fout.HadError()) {
+ context_->GetDiagnostics()->Error(DiagMessage() << "failed writing to '" << out_path
+ << "': " << fout.GetError());
return false;
}
- std::unique_ptr<std::ofstream> fout_text;
+ std::unique_ptr<io::FileOutputStream> fout_text;
if (out_text_symbols_path) {
- fout_text =
- util::make_unique<std::ofstream>(out_text_symbols_path.value(), std::ofstream::binary);
- if (!*fout_text) {
- context_->GetDiagnostics()->Error(
- DiagMessage() << "failed writing to '" << out_text_symbols_path.value()
- << "': " << android::base::SystemErrorCodeToString(errno));
+ fout_text = util::make_unique<io::FileOutputStream>(out_text_symbols_path.value());
+ if (fout_text->HadError()) {
+ context_->GetDiagnostics()->Error(DiagMessage()
+ << "failed writing to '" << out_text_symbols_path.value()
+ << "': " << fout_text->GetError());
return false;
}
}
JavaClassGenerator generator(context_, table, java_options);
if (!generator.Generate(package_name_to_generate, out_package, &fout, fout_text.get())) {
- context_->GetDiagnostics()->Error(DiagMessage(out_path) << generator.getError());
+ context_->GetDiagnostics()->Error(DiagMessage(out_path) << generator.GetError());
return false;
}
- if (!fout) {
- context_->GetDiagnostics()->Error(DiagMessage()
- << "failed writing to '" << out_path
- << "': " << android::base::SystemErrorCodeToString(errno));
+ fout.Flush();
+
+ if (fout.HadError()) {
+ context_->GetDiagnostics()->Error(DiagMessage() << "failed writing to '" << out_path
+ << "': " << fout.GetError());
return false;
}
return true;
@@ -1142,18 +1144,19 @@
file::AppendPath(&out_path, "Manifest.java");
- std::ofstream fout(out_path, std::ofstream::binary);
- if (!fout) {
- context_->GetDiagnostics()->Error(DiagMessage()
- << "failed writing to '" << out_path
- << "': " << android::base::SystemErrorCodeToString(errno));
+ io::FileOutputStream fout(out_path);
+ if (fout.HadError()) {
+ context_->GetDiagnostics()->Error(DiagMessage() << "failed to open '" << out_path
+ << "': " << fout.GetError());
return false;
}
- if (!ClassDefinition::WriteJavaFile(manifest_class.get(), package_utf8, true, &fout)) {
- context_->GetDiagnostics()->Error(DiagMessage()
- << "failed writing to '" << out_path
- << "': " << android::base::SystemErrorCodeToString(errno));
+ ClassDefinition::WriteJavaFile(manifest_class.get(), package_utf8, true, &fout);
+ fout.Flush();
+
+ if (fout.HadError()) {
+ context_->GetDiagnostics()->Error(DiagMessage() << "failed writing to '" << out_path
+ << "': " << fout.GetError());
return false;
}
return true;
@@ -1165,19 +1168,19 @@
}
const std::string& out_path = out.value();
- std::ofstream fout(out_path, std::ofstream::binary);
- if (!fout) {
- context_->GetDiagnostics()->Error(DiagMessage()
- << "failed to open '" << out_path
- << "': " << android::base::SystemErrorCodeToString(errno));
+ io::FileOutputStream fout(out_path);
+ if (fout.HadError()) {
+ context_->GetDiagnostics()->Error(DiagMessage() << "failed to open '" << out_path
+ << "': " << fout.GetError());
return false;
}
- proguard::WriteKeepSet(&fout, keep_set);
- if (!fout) {
- context_->GetDiagnostics()->Error(DiagMessage()
- << "failed writing to '" << out_path
- << "': " << android::base::SystemErrorCodeToString(errno));
+ proguard::WriteKeepSet(keep_set, &fout);
+ fout.Flush();
+
+ if (fout.HadError()) {
+ context_->GetDiagnostics()->Error(DiagMessage() << "failed writing to '" << out_path
+ << "': " << fout.GetError());
return false;
}
return true;