Add a singleton CacheLocation to replace the hard coded locations
This class allows us to set the following locations dynamically: cache_temp_source, last_command_file, stash_directory_base. In the updater's main function, we reset the values of these variables to their default locations in /cache; while we can set them to temp files in unit tests or host simulation. Test: unit tests pass Change-Id: I528652650caa41373617ab055d41b1f1a4ec0f87
This commit is contained in:
parent
ac4818d6af
commit
3bbb20f557
11 changed files with 139 additions and 27 deletions
|
@ -40,10 +40,9 @@
|
|||
|
||||
#include "edify/expr.h"
|
||||
#include "otafault/ota_io.h"
|
||||
#include "otautil/cache_location.h"
|
||||
#include "otautil/print_sha1.h"
|
||||
|
||||
std::string cache_temp_source = "/cache/saved.file";
|
||||
|
||||
static int LoadPartitionContents(const std::string& filename, FileContents* file);
|
||||
static size_t FileSink(const unsigned char* data, size_t len, int fd);
|
||||
static int GenerateTarget(const FileContents& source_file, const std::unique_ptr<Value>& patch,
|
||||
|
@ -404,7 +403,7 @@ int applypatch_check(const char* filename, const std::vector<std::string>& patch
|
|||
// If the source file is missing or corrupted, it might be because we were killed in the middle
|
||||
// of patching it. A copy of it should have been made in cache_temp_source. If that file
|
||||
// exists and matches the sha1 we're looking for, the check still passes.
|
||||
if (LoadFileContents(cache_temp_source.c_str(), &file) != 0) {
|
||||
if (LoadFileContents(CacheLocation::location().cache_temp_source().c_str(), &file) != 0) {
|
||||
printf("failed to load cache file\n");
|
||||
return 1;
|
||||
}
|
||||
|
@ -526,7 +525,7 @@ int applypatch(const char* source_filename, const char* target_filename,
|
|||
printf("source file is bad; trying copy\n");
|
||||
|
||||
FileContents copy_file;
|
||||
if (LoadFileContents(cache_temp_source.c_str(), ©_file) < 0) {
|
||||
if (LoadFileContents(CacheLocation::location().cache_temp_source().c_str(), ©_file) < 0) {
|
||||
printf("failed to read copy file\n");
|
||||
return 1;
|
||||
}
|
||||
|
@ -621,7 +620,7 @@ static int GenerateTarget(const FileContents& source_file, const std::unique_ptr
|
|||
printf("not enough free space on /cache\n");
|
||||
return 1;
|
||||
}
|
||||
if (SaveFileContents(cache_temp_source.c_str(), &source_file) < 0) {
|
||||
if (SaveFileContents(CacheLocation::location().cache_temp_source().c_str(), &source_file) < 0) {
|
||||
printf("failed to back up source file\n");
|
||||
return 1;
|
||||
}
|
||||
|
@ -667,7 +666,7 @@ static int GenerateTarget(const FileContents& source_file, const std::unique_ptr
|
|||
}
|
||||
|
||||
// Delete the backup copy of the source.
|
||||
unlink(cache_temp_source.c_str());
|
||||
unlink(CacheLocation::location().cache_temp_source().c_str());
|
||||
|
||||
// Success!
|
||||
return 0;
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <android-base/stringprintf.h>
|
||||
|
||||
#include "applypatch/applypatch.h"
|
||||
#include "otautil/cache_location.h"
|
||||
|
||||
static int EliminateOpenFiles(std::set<std::string>* files) {
|
||||
std::unique_ptr<DIR, decltype(&closedir)> d(opendir("/proc"), closedir);
|
||||
|
@ -92,7 +93,7 @@ static std::set<std::string> FindExpendableFiles() {
|
|||
|
||||
// We can't delete cache_temp_source; if it's there we might have restarted during
|
||||
// installation and could be depending on it to be there.
|
||||
if (path == cache_temp_source) {
|
||||
if (path == CacheLocation::location().cache_temp_source()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,12 +34,6 @@ struct FileContents {
|
|||
std::vector<unsigned char> data;
|
||||
};
|
||||
|
||||
// When there isn't enough room on the target filesystem to hold the patched version of the file,
|
||||
// we copy the original here and delete it to free up space. If the expected source file doesn't
|
||||
// exist, or is corrupted, we look to see if the cached file contains the bits we want and use it as
|
||||
// the source instead. The default location for the cached source is "/cache/saved.file".
|
||||
extern std::string cache_temp_source;
|
||||
|
||||
using SinkFn = std::function<size_t(const unsigned char*, size_t)>;
|
||||
|
||||
// applypatch.cpp
|
||||
|
|
|
@ -21,6 +21,7 @@ cc_library_static {
|
|||
"SysUtil.cpp",
|
||||
"DirUtil.cpp",
|
||||
"ThermalUtil.cpp",
|
||||
"cache_location.cpp",
|
||||
"rangeset.cpp",
|
||||
],
|
||||
|
||||
|
|
32
otautil/cache_location.cpp
Normal file
32
otautil/cache_location.cpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (C) 2018 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 "otautil/cache_location.h"
|
||||
|
||||
constexpr const char kDefaultCacheTempSource[] = "/cache/saved.file";
|
||||
constexpr const char kDefaultLastCommandFile[] = "/cache/recovery/last_command";
|
||||
constexpr const char kDefaultStashDirectoryBase[] = "/cache/recovery";
|
||||
|
||||
CacheLocation& CacheLocation::location() {
|
||||
static CacheLocation cache_location;
|
||||
return cache_location;
|
||||
}
|
||||
|
||||
void CacheLocation::ResetLocations() {
|
||||
cache_temp_source_ = kDefaultCacheTempSource;
|
||||
last_command_file_ = kDefaultLastCommandFile;
|
||||
stash_directory_base_ = kDefaultStashDirectoryBase;
|
||||
}
|
72
otautil/include/otautil/cache_location.h
Normal file
72
otautil/include/otautil/cache_location.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (C) 2018 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.
|
||||
*/
|
||||
|
||||
#ifndef _OTAUTIL_OTAUTIL_CACHE_LOCATION_H_
|
||||
#define _OTAUTIL_OTAUTIL_CACHE_LOCATION_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "android-base/macros.h"
|
||||
|
||||
// A singleton class to maintain the update related locations. The locations should be only set
|
||||
// once at the start of the program.
|
||||
class CacheLocation {
|
||||
public:
|
||||
static CacheLocation& location();
|
||||
|
||||
// Reset the locations to their default values.
|
||||
void ResetLocations();
|
||||
|
||||
// getter and setter functions.
|
||||
std::string cache_temp_source() const {
|
||||
return cache_temp_source_;
|
||||
}
|
||||
void set_cache_temp_source(const std::string& temp_source) {
|
||||
cache_temp_source_ = temp_source;
|
||||
}
|
||||
|
||||
std::string last_command_file() const {
|
||||
return last_command_file_;
|
||||
}
|
||||
void set_last_command_file(const std::string& last_command) {
|
||||
last_command_file_ = last_command;
|
||||
}
|
||||
|
||||
std::string stash_directory_base() const {
|
||||
return stash_directory_base_;
|
||||
}
|
||||
void set_stash_directory_base(const std::string& base) {
|
||||
stash_directory_base_ = base;
|
||||
}
|
||||
|
||||
private:
|
||||
CacheLocation() {}
|
||||
DISALLOW_COPY_AND_ASSIGN(CacheLocation);
|
||||
|
||||
// When there isn't enough room on the target filesystem to hold the patched version of the file,
|
||||
// we copy the original here and delete it to free up space. If the expected source file doesn't
|
||||
// exist, or is corrupted, we look to see if the cached file contains the bits we want and use it
|
||||
// as the source instead. The default location for the cached source is "/cache/saved.file".
|
||||
std::string cache_temp_source_;
|
||||
|
||||
// Location to save the last command that stashes blocks.
|
||||
std::string last_command_file_;
|
||||
|
||||
// The base directory to write stashes during update.
|
||||
std::string stash_directory_base_;
|
||||
};
|
||||
|
||||
#endif // _OTAUTIL_OTAUTIL_CACHE_LOCATION_H_
|
|
@ -35,6 +35,7 @@
|
|||
#include "applypatch/applypatch.h"
|
||||
#include "applypatch/applypatch_modes.h"
|
||||
#include "common/test_constants.h"
|
||||
#include "otautil/cache_location.h"
|
||||
#include "otautil/print_sha1.h"
|
||||
|
||||
static void sha1sum(const std::string& fname, std::string* sha1, size_t* fsize = nullptr) {
|
||||
|
@ -93,14 +94,14 @@ class ApplyPatchCacheTest : public ApplyPatchTest {
|
|||
protected:
|
||||
void SetUp() override {
|
||||
ApplyPatchTest::SetUp();
|
||||
cache_temp_source = old_file;
|
||||
CacheLocation::location().set_cache_temp_source(old_file);
|
||||
}
|
||||
};
|
||||
|
||||
class ApplyPatchModesTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
cache_temp_source = cache_source.path;
|
||||
CacheLocation::location().set_cache_temp_source(cache_source.path);
|
||||
}
|
||||
|
||||
TemporaryFile cache_source;
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "common/test_constants.h"
|
||||
#include "edify/expr.h"
|
||||
#include "otautil/SysUtil.h"
|
||||
#include "otautil/cache_location.h"
|
||||
#include "otautil/error_code.h"
|
||||
#include "otautil/print_sha1.h"
|
||||
#include "updater/blockimg.h"
|
||||
|
@ -104,7 +105,16 @@ class UpdaterTest : public ::testing::Test {
|
|||
RegisterBuiltins();
|
||||
RegisterInstallFunctions();
|
||||
RegisterBlockImageFunctions();
|
||||
|
||||
// Mock the location of last_command_file.
|
||||
CacheLocation::location().set_cache_temp_source(temp_saved_source_.path);
|
||||
CacheLocation::location().set_last_command_file(temp_last_command_.path);
|
||||
CacheLocation::location().set_stash_directory_base(temp_stash_base_.path);
|
||||
}
|
||||
|
||||
TemporaryFile temp_saved_source_;
|
||||
TemporaryFile temp_last_command_;
|
||||
TemporaryDir temp_stash_base_;
|
||||
};
|
||||
|
||||
TEST_F(UpdaterTest, getprop) {
|
||||
|
@ -542,7 +552,7 @@ TEST_F(UpdaterTest, block_image_update_fail) {
|
|||
expect("", script.c_str(), kNoCause, &updater_info);
|
||||
// Updater generates the stash name based on the input file name.
|
||||
std::string name_digest = get_sha1(update_file.path);
|
||||
std::string stash_base = "/cache/recovery/" + name_digest;
|
||||
std::string stash_base = std::string(temp_stash_base_.path) + "/" + name_digest;
|
||||
ASSERT_EQ(0, access(stash_base.c_str(), F_OK));
|
||||
ASSERT_EQ(-1, access((stash_base + src_hash).c_str(), F_OK));
|
||||
ASSERT_EQ(0, rmdir(stash_base.c_str()));
|
||||
|
@ -709,8 +719,7 @@ TEST_F(UpdaterTest, brotli_new_data) {
|
|||
}
|
||||
|
||||
TEST_F(UpdaterTest, last_command_update) {
|
||||
TemporaryFile temp_file;
|
||||
last_command_file = temp_file.path;
|
||||
std::string last_command_file = CacheLocation::location().last_command_file();
|
||||
|
||||
std::string block1 = std::string(4096, '1');
|
||||
std::string block2 = std::string(4096, '2');
|
||||
|
@ -797,8 +806,7 @@ TEST_F(UpdaterTest, last_command_update) {
|
|||
}
|
||||
|
||||
TEST_F(UpdaterTest, last_command_update_unresumable) {
|
||||
TemporaryFile temp_file;
|
||||
last_command_file = temp_file.path;
|
||||
std::string last_command_file = CacheLocation::location().last_command_file();
|
||||
|
||||
std::string block1 = std::string(4096, '1');
|
||||
std::string block2 = std::string(4096, '2');
|
||||
|
@ -853,8 +861,7 @@ TEST_F(UpdaterTest, last_command_update_unresumable) {
|
|||
}
|
||||
|
||||
TEST_F(UpdaterTest, last_command_verify) {
|
||||
TemporaryFile temp_file;
|
||||
last_command_file = temp_file.path;
|
||||
std::string last_command_file = CacheLocation::location().last_command_file();
|
||||
|
||||
std::string block1 = std::string(4096, '1');
|
||||
std::string block2 = std::string(4096, '2');
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
|
||||
#include "edify/expr.h"
|
||||
#include "otafault/ota_io.h"
|
||||
#include "otautil/cache_location.h"
|
||||
#include "otautil/error_code.h"
|
||||
#include "otautil/print_sha1.h"
|
||||
#include "otautil/rangeset.h"
|
||||
|
@ -65,17 +66,15 @@
|
|||
#define DEBUG_ERASE 0
|
||||
|
||||
static constexpr size_t BLOCKSIZE = 4096;
|
||||
static constexpr const char* STASH_DIRECTORY_BASE = "/cache/recovery";
|
||||
static constexpr mode_t STASH_DIRECTORY_MODE = 0700;
|
||||
static constexpr mode_t STASH_FILE_MODE = 0600;
|
||||
|
||||
std::string last_command_file = "/cache/recovery/last_command";
|
||||
|
||||
static CauseCode failure_type = kNoCause;
|
||||
static bool is_retry = false;
|
||||
static std::unordered_map<std::string, RangeSet> stash_map;
|
||||
|
||||
static void DeleteLastCommandFile() {
|
||||
std::string last_command_file = CacheLocation::location().last_command_file();
|
||||
if (unlink(last_command_file.c_str()) == -1 && errno != ENOENT) {
|
||||
PLOG(ERROR) << "Failed to unlink: " << last_command_file;
|
||||
}
|
||||
|
@ -84,6 +83,7 @@ static void DeleteLastCommandFile() {
|
|||
// Parse the last command index of the last update and save the result to |last_command_index|.
|
||||
// Return true if we successfully read the index.
|
||||
static bool ParseLastCommandFile(int* last_command_index) {
|
||||
std::string last_command_file = CacheLocation::location().last_command_file();
|
||||
android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(last_command_file.c_str(), O_RDONLY)));
|
||||
if (fd == -1) {
|
||||
if (errno != ENOENT) {
|
||||
|
@ -119,6 +119,7 @@ static bool ParseLastCommandFile(int* last_command_index) {
|
|||
// Update the last command index in the last_command_file if the current command writes to the
|
||||
// stash either explicitly or implicitly.
|
||||
static bool UpdateLastCommandIndex(int command_index, const std::string& command_string) {
|
||||
std::string last_command_file = CacheLocation::location().last_command_file();
|
||||
std::string last_command_tmp = last_command_file + ".tmp";
|
||||
std::string content = std::to_string(command_index) + "\n" + command_string;
|
||||
android::base::unique_fd wfd(
|
||||
|
@ -676,7 +677,7 @@ static std::string GetStashFileName(const std::string& base, const std::string&
|
|||
return "";
|
||||
}
|
||||
|
||||
std::string fn(STASH_DIRECTORY_BASE);
|
||||
std::string fn(CacheLocation::location().stash_directory_base());
|
||||
fn += "/" + base + "/" + id + postfix;
|
||||
|
||||
return fn;
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
extern std::string last_command_file;
|
||||
void RegisterBlockImageFunctions();
|
||||
|
||||
#endif
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "otafault/config.h"
|
||||
#include "otautil/DirUtil.h"
|
||||
#include "otautil/SysUtil.h"
|
||||
#include "otautil/cache_location.h"
|
||||
#include "otautil/error_code.h"
|
||||
#include "updater/blockimg.h"
|
||||
#include "updater/install.h"
|
||||
|
@ -168,6 +169,10 @@ int main(int argc, char** argv) {
|
|||
}
|
||||
ota_io_init(za, state.is_retry);
|
||||
|
||||
// Initialize the cache_temp_source, last_command_file and stash_directory_base to their default
|
||||
// locations.
|
||||
CacheLocation::location().ResetLocations();
|
||||
|
||||
std::string result;
|
||||
bool status = Evaluate(&state, root, &result);
|
||||
|
||||
|
|
Loading…
Reference in a new issue