blob: 4a3ee8d84f7c5e5ceead8b2c50cdc1bb209138c9 [file] [log] [blame]
//
// Copyright (C) 2019 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "install_zip.h"
#include <stdlib.h>
#include <string>
#include <vector>
#include <android-base/strings.h>
#include <glog/logging.h>
#include "common/libs/utils/archive.h"
#include "common/libs/utils/subprocess.h"
std::vector<std::string> ExtractImages(const std::string& archive_file,
const std::string& target_directory,
const std::vector<std::string>& images) {
cvd::Archive archive(archive_file);
bool extracted =
images.size() > 0
? archive.ExtractFiles(images, target_directory)
: archive.ExtractAll(target_directory);
if (!extracted) {
LOG(ERROR) << "Unable to extract images.";
return {};
}
bool extraction_success = true;
std::vector<std::string> files =
images.size() > 0 ? images : archive.Contents();
for (auto it = files.begin(); it != files.end();) {
it = (*it == "" || android::base::EndsWith(*it, "/")) ? files.erase(it) : ++it;
}
for (const auto& file : files) {
if (file.find(".img") == std::string::npos) {
continue;
}
std::string extracted_file = target_directory + "/" + file;
std::string file_input, file_output;
cvd::Command file_cmd("/usr/bin/file");
file_cmd.AddParameter(extracted_file);
auto file_ret = cvd::RunWithManagedStdio(std::move(file_cmd), &file_input,
&file_output, nullptr);
if (file_ret != 0) {
LOG(ERROR) << "Unable to run file on " << file << ", returned" << file_ret;
extraction_success = false;
continue;
}
if (file_output.find("Android sparse image,") == std::string::npos) {
continue;
}
std::string inflated_file = extracted_file + ".inflated";
cvd::Command simg_cmd("/usr/bin/simg2img");
simg_cmd.AddParameter(extracted_file);
simg_cmd.AddParameter(inflated_file);
simg_cmd.RedirectStdIO(cvd::Subprocess::StdIOChannel::kStdOut,
cvd::Subprocess::StdIOChannel::kStdErr);
if (simg_cmd.Start().Wait() != 0) {
LOG(ERROR) << "Unable to run simg2img on " << file;
extraction_success = false;
continue;
}
auto rename_ret = rename(inflated_file.c_str(), extracted_file.c_str());
if (rename_ret != 0) {
LOG(ERROR) << "Unable to rename deflated version of " << file;
extraction_success = false;
}
}
return extraction_success ? files : std::vector<std::string>{};
}