summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--install.cpp311
-rw-r--r--tests/component/updater_test.cpp50
-rw-r--r--uncrypt/uncrypt.cpp41
-rw-r--r--updater/blockimg.cpp167
4 files changed, 340 insertions, 229 deletions
diff --git a/install.cpp b/install.cpp
index 772d81caf..a35102610 100644
--- a/install.cpp
+++ b/install.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include "install.h"
+
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
@@ -32,6 +34,7 @@
#include <android-base/file.h>
#include <android-base/logging.h>
+#include <android-base/parsedouble.h>
#include <android-base/parseint.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
@@ -40,7 +43,6 @@
#include "common.h"
#include "error_code.h"
-#include "install.h"
#include "minui/minui.h"
#include "otautil/SysUtil.h"
#include "roots.h"
@@ -55,10 +57,10 @@ static constexpr const char* METADATA_PATH = "META-INF/com/android/metadata";
static constexpr const char* UNCRYPT_STATUS = "/cache/recovery/uncrypt_status";
// Default allocation of progress bar segments to operations
-static const int VERIFICATION_PROGRESS_TIME = 60;
-static const float VERIFICATION_PROGRESS_FRACTION = 0.25;
-static const float DEFAULT_FILES_PROGRESS_FRACTION = 0.4;
-static const float DEFAULT_IMAGE_PROGRESS_FRACTION = 0.1;
+static constexpr int VERIFICATION_PROGRESS_TIME = 60;
+static constexpr float VERIFICATION_PROGRESS_FRACTION = 0.25;
+static constexpr float DEFAULT_FILES_PROGRESS_FRACTION = 0.4;
+static constexpr float DEFAULT_IMAGE_PROGRESS_FRACTION = 0.1;
// This function parses and returns the build.version.incremental
static int parse_build_number(const std::string& str) {
@@ -299,149 +301,168 @@ update_binary_command(const char* path, ZipArchiveHandle zip, int retry_count,
#endif // !AB_OTA_UPDATER
// If the package contains an update binary, extract it and run it.
-static int
-try_update_binary(const char* path, ZipArchiveHandle zip, bool* wipe_cache,
- std::vector<std::string>& log_buffer, int retry_count)
-{
- read_source_target_build(zip, log_buffer);
+static int try_update_binary(const char* path, ZipArchiveHandle zip, bool* wipe_cache,
+ std::vector<std::string>& log_buffer, int retry_count) {
+ read_source_target_build(zip, log_buffer);
- int pipefd[2];
- pipe(pipefd);
+ int pipefd[2];
+ pipe(pipefd);
- std::vector<std::string> args;
- int ret = update_binary_command(path, zip, retry_count, pipefd[1], &args);
- if (ret) {
- close(pipefd[0]);
- close(pipefd[1]);
- return ret;
- }
-
- // When executing the update binary contained in the package, the
- // arguments passed are:
- //
- // - the version number for this interface
- //
- // - an fd to which the program can write in order to update the
- // progress bar. The program can write single-line commands:
- //
- // progress <frac> <secs>
- // fill up the next <frac> part of of the progress bar
- // over <secs> seconds. If <secs> is zero, use
- // set_progress commands to manually control the
- // progress of this segment of the bar.
- //
- // set_progress <frac>
- // <frac> should be between 0.0 and 1.0; sets the
- // progress bar within the segment defined by the most
- // recent progress command.
- //
- // ui_print <string>
- // display <string> on the screen.
- //
- // wipe_cache
- // a wipe of cache will be performed following a successful
- // installation.
- //
- // clear_display
- // turn off the text display.
- //
- // enable_reboot
- // packages can explicitly request that they want the user
- // to be able to reboot during installation (useful for
- // debugging packages that don't exit).
- //
- // - the name of the package zip file.
- //
- // - an optional argument "retry" if this update is a retry of a failed
- // update attempt.
- //
-
- // Convert the vector to a NULL-terminated char* array suitable for execv.
- const char* chr_args[args.size() + 1];
- chr_args[args.size()] = NULL;
- for (size_t i = 0; i < args.size(); i++) {
- chr_args[i] = args[i].c_str();
- }
-
- pid_t pid = fork();
-
- if (pid == -1) {
- close(pipefd[0]);
- close(pipefd[1]);
- PLOG(ERROR) << "Failed to fork update binary";
- return INSTALL_ERROR;
- }
-
- if (pid == 0) {
- umask(022);
- close(pipefd[0]);
- execv(chr_args[0], const_cast<char**>(chr_args));
- fprintf(stdout, "E:Can't run %s (%s)\n", chr_args[0], strerror(errno));
- _exit(-1);
- }
+ std::vector<std::string> args;
+ int ret = update_binary_command(path, zip, retry_count, pipefd[1], &args);
+ if (ret) {
+ close(pipefd[0]);
close(pipefd[1]);
-
- *wipe_cache = false;
- bool retry_update = false;
-
- char buffer[1024];
- FILE* from_child = fdopen(pipefd[0], "r");
- while (fgets(buffer, sizeof(buffer), from_child) != NULL) {
- char* command = strtok(buffer, " \n");
- if (command == NULL) {
- continue;
- } else if (strcmp(command, "progress") == 0) {
- char* fraction_s = strtok(NULL, " \n");
- char* seconds_s = strtok(NULL, " \n");
-
- float fraction = strtof(fraction_s, NULL);
- int seconds = strtol(seconds_s, NULL, 10);
-
- ui->ShowProgress(fraction * (1-VERIFICATION_PROGRESS_FRACTION), seconds);
- } else if (strcmp(command, "set_progress") == 0) {
- char* fraction_s = strtok(NULL, " \n");
- float fraction = strtof(fraction_s, NULL);
- ui->SetProgress(fraction);
- } else if (strcmp(command, "ui_print") == 0) {
- char* str = strtok(NULL, "\n");
- if (str) {
- ui->PrintOnScreenOnly("%s", str);
- } else {
- ui->PrintOnScreenOnly("\n");
- }
- fflush(stdout);
- } else if (strcmp(command, "wipe_cache") == 0) {
- *wipe_cache = true;
- } else if (strcmp(command, "clear_display") == 0) {
- ui->SetBackground(RecoveryUI::NONE);
- } else if (strcmp(command, "enable_reboot") == 0) {
- // packages can explicitly request that they want the user
- // to be able to reboot during installation (useful for
- // debugging packages that don't exit).
- ui->SetEnableReboot(true);
- } else if (strcmp(command, "retry_update") == 0) {
- retry_update = true;
- } else if (strcmp(command, "log") == 0) {
- // Save the logging request from updater and write to
- // last_install later.
- log_buffer.push_back(std::string(strtok(NULL, "\n")));
- } else {
- LOG(ERROR) << "unknown command [" << command << "]";
- }
- }
- fclose(from_child);
-
- int status;
- waitpid(pid, &status, 0);
- if (retry_update) {
- return INSTALL_RETRY;
- }
- if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
- LOG(ERROR) << "Error in " << path << " (Status " << WEXITSTATUS(status) << ")";
- return INSTALL_ERROR;
- }
-
- return INSTALL_SUCCESS;
+ return ret;
+ }
+
+ // When executing the update binary contained in the package, the
+ // arguments passed are:
+ //
+ // - the version number for this interface
+ //
+ // - an FD to which the program can write in order to update the
+ // progress bar. The program can write single-line commands:
+ //
+ // progress <frac> <secs>
+ // fill up the next <frac> part of of the progress bar
+ // over <secs> seconds. If <secs> is zero, use
+ // set_progress commands to manually control the
+ // progress of this segment of the bar.
+ //
+ // set_progress <frac>
+ // <frac> should be between 0.0 and 1.0; sets the
+ // progress bar within the segment defined by the most
+ // recent progress command.
+ //
+ // ui_print <string>
+ // display <string> on the screen.
+ //
+ // wipe_cache
+ // a wipe of cache will be performed following a successful
+ // installation.
+ //
+ // clear_display
+ // turn off the text display.
+ //
+ // enable_reboot
+ // packages can explicitly request that they want the user
+ // to be able to reboot during installation (useful for
+ // debugging packages that don't exit).
+ //
+ // retry_update
+ // updater encounters some issue during the update. It requests
+ // a reboot to retry the same package automatically.
+ //
+ // log <string>
+ // updater requests logging the string (e.g. cause of the
+ // failure).
+ //
+ // - the name of the package zip file.
+ //
+ // - an optional argument "retry" if this update is a retry of a failed
+ // update attempt.
+ //
+
+ // Convert the vector to a NULL-terminated char* array suitable for execv.
+ const char* chr_args[args.size() + 1];
+ chr_args[args.size()] = nullptr;
+ for (size_t i = 0; i < args.size(); i++) {
+ chr_args[i] = args[i].c_str();
+ }
+
+ pid_t pid = fork();
+
+ if (pid == -1) {
+ close(pipefd[0]);
+ close(pipefd[1]);
+ PLOG(ERROR) << "Failed to fork update binary";
+ return INSTALL_ERROR;
+ }
+
+ if (pid == 0) {
+ umask(022);
+ close(pipefd[0]);
+ execv(chr_args[0], const_cast<char**>(chr_args));
+ PLOG(ERROR) << "Can't run " << chr_args[0];
+ _exit(-1);
+ }
+ close(pipefd[1]);
+
+ *wipe_cache = false;
+ bool retry_update = false;
+
+ char buffer[1024];
+ FILE* from_child = fdopen(pipefd[0], "r");
+ while (fgets(buffer, sizeof(buffer), from_child) != nullptr) {
+ std::string line(buffer);
+ size_t space = line.find_first_of(" \n");
+ std::string command(line.substr(0, space));
+ if (command.empty()) continue;
+
+ // Get rid of the leading and trailing space and/or newline.
+ std::string args = space == std::string::npos ? "" : android::base::Trim(line.substr(space));
+
+ if (command == "progress") {
+ std::vector<std::string> tokens = android::base::Split(args, " ");
+ double fraction;
+ int seconds;
+ if (tokens.size() == 2 && android::base::ParseDouble(tokens[0].c_str(), &fraction) &&
+ android::base::ParseInt(tokens[1], &seconds)) {
+ ui->ShowProgress(fraction * (1 - VERIFICATION_PROGRESS_FRACTION), seconds);
+ } else {
+ LOG(ERROR) << "invalid \"progress\" parameters: " << line;
+ }
+ } else if (command == "set_progress") {
+ std::vector<std::string> tokens = android::base::Split(args, " ");
+ double fraction;
+ if (tokens.size() == 1 && android::base::ParseDouble(tokens[0].c_str(), &fraction)) {
+ ui->SetProgress(fraction);
+ } else {
+ LOG(ERROR) << "invalid \"set_progress\" parameters: " << line;
+ }
+ } else if (command == "ui_print") {
+ if (!args.empty()) {
+ ui->PrintOnScreenOnly("%s", args.c_str());
+ } else {
+ ui->PrintOnScreenOnly("\n");
+ }
+ fflush(stdout);
+ } else if (command == "wipe_cache") {
+ *wipe_cache = true;
+ } else if (command == "clear_display") {
+ ui->SetBackground(RecoveryUI::NONE);
+ } else if (command == "enable_reboot") {
+ // packages can explicitly request that they want the user
+ // to be able to reboot during installation (useful for
+ // debugging packages that don't exit).
+ ui->SetEnableReboot(true);
+ } else if (command == "retry_update") {
+ retry_update = true;
+ } else if (command == "log") {
+ if (!args.empty()) {
+ // Save the logging request from updater and write to last_install later.
+ log_buffer.push_back(args);
+ } else {
+ LOG(ERROR) << "invalid \"log\" parameters: " << line;
+ }
+ } else {
+ LOG(ERROR) << "unknown command [" << command << "]";
+ }
+ }
+ fclose(from_child);
+
+ int status;
+ waitpid(pid, &status, 0);
+ if (retry_update) {
+ return INSTALL_RETRY;
+ }
+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+ LOG(ERROR) << "Error in " << path << " (Status " << WEXITSTATUS(status) << ")";
+ return INSTALL_ERROR;
+ }
+
+ return INSTALL_SUCCESS;
}
static int
diff --git a/tests/component/updater_test.cpp b/tests/component/updater_test.cpp
index f31f1f82a..fa5f03134 100644
--- a/tests/component/updater_test.cpp
+++ b/tests/component/updater_test.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
@@ -22,6 +23,8 @@
#include <android-base/file.h>
#include <android-base/properties.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
#include <android-base/test_utils.h>
#include <bootloader_message/bootloader_message.h>
#include <gtest/gtest.h>
@@ -510,3 +513,50 @@ TEST_F(UpdaterTest, set_stage) {
script = "set_stage(\"/dev/full\", \"1/3\")";
expect("", script.c_str(), kNoCause);
}
+
+TEST_F(UpdaterTest, set_progress) {
+ // set_progress() expects one argument.
+ expect(nullptr, "set_progress()", kArgsParsingFailure);
+ expect(nullptr, "set_progress(\"arg1\", \"arg2\")", kArgsParsingFailure);
+
+ // Invalid progress argument.
+ expect(nullptr, "set_progress(\"arg1\")", kArgsParsingFailure);
+ expect(nullptr, "set_progress(\"3x+5\")", kArgsParsingFailure);
+ expect(nullptr, "set_progress(\".3.5\")", kArgsParsingFailure);
+
+ TemporaryFile tf;
+ UpdaterInfo updater_info;
+ updater_info.cmd_pipe = fdopen(tf.fd, "w");
+ expect(".52", "set_progress(\".52\")", kNoCause, &updater_info);
+ fflush(updater_info.cmd_pipe);
+
+ std::string cmd;
+ ASSERT_TRUE(android::base::ReadFileToString(tf.path, &cmd));
+ ASSERT_EQ(android::base::StringPrintf("set_progress %f\n", .52), cmd);
+ // recovery-updater protocol expects 2 tokens ("set_progress <frac>").
+ ASSERT_EQ(2U, android::base::Split(cmd, " ").size());
+}
+
+TEST_F(UpdaterTest, show_progress) {
+ // show_progress() expects two arguments.
+ expect(nullptr, "show_progress()", kArgsParsingFailure);
+ expect(nullptr, "show_progress(\"arg1\")", kArgsParsingFailure);
+ expect(nullptr, "show_progress(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
+
+ // Invalid progress arguments.
+ expect(nullptr, "show_progress(\"arg1\", \"arg2\")", kArgsParsingFailure);
+ expect(nullptr, "show_progress(\"3x+5\", \"10\")", kArgsParsingFailure);
+ expect(nullptr, "show_progress(\".3\", \"5a\")", kArgsParsingFailure);
+
+ TemporaryFile tf;
+ UpdaterInfo updater_info;
+ updater_info.cmd_pipe = fdopen(tf.fd, "w");
+ expect(".52", "show_progress(\".52\", \"10\")", kNoCause, &updater_info);
+ fflush(updater_info.cmd_pipe);
+
+ std::string cmd;
+ ASSERT_TRUE(android::base::ReadFileToString(tf.path, &cmd));
+ ASSERT_EQ(android::base::StringPrintf("progress %f %d\n", .52, 10), cmd);
+ // recovery-updater protocol expects 3 tokens ("progress <frac> <secs>").
+ ASSERT_EQ(3U, android::base::Split(cmd, " ").size());
+}
diff --git a/uncrypt/uncrypt.cpp b/uncrypt/uncrypt.cpp
index 597307607..4f5b2f807 100644
--- a/uncrypt/uncrypt.cpp
+++ b/uncrypt/uncrypt.cpp
@@ -118,7 +118,8 @@
#include "error_code.h"
-#define WINDOW_SIZE 5
+static constexpr int WINDOW_SIZE = 5;
+static constexpr int FIBMAP_RETRY_LIMIT = 3;
// uncrypt provides three services: SETUP_BCB, CLEAR_BCB and UNCRYPT.
//
@@ -233,6 +234,26 @@ static bool find_uncrypt_package(const std::string& uncrypt_path_file, std::stri
return true;
}
+static int retry_fibmap(const int fd, const char* name, int* block, const int head_block) {
+ CHECK(block != nullptr);
+ for (size_t i = 0; i < FIBMAP_RETRY_LIMIT; i++) {
+ if (fsync(fd) == -1) {
+ PLOG(ERROR) << "failed to fsync \"" << name << "\"";
+ return kUncryptFileSyncError;
+ }
+ if (ioctl(fd, FIBMAP, block) != 0) {
+ PLOG(ERROR) << "failed to find block " << head_block;
+ return kUncryptIoctlError;
+ }
+ if (*block != 0) {
+ return kUncryptNoError;
+ }
+ sleep(1);
+ }
+ LOG(ERROR) << "fibmap of " << head_block << "always returns 0";
+ return kUncryptIoctlError;
+}
+
static int produce_block_map(const char* path, const char* map_file, const char* blk_dev,
bool encrypted, int socket) {
std::string err;
@@ -314,6 +335,15 @@ static int produce_block_map(const char* path, const char* map_file, const char*
PLOG(ERROR) << "failed to find block " << head_block;
return kUncryptIoctlError;
}
+
+ if (block == 0) {
+ LOG(ERROR) << "failed to find block " << head_block << ", retrying";
+ int error = retry_fibmap(fd, path, &block, head_block);
+ if (error != kUncryptNoError) {
+ return error;
+ }
+ }
+
add_block_to_ranges(ranges, block);
if (encrypted) {
if (write_at_offset(buffers[head].data(), sb.st_blksize, wfd,
@@ -350,6 +380,15 @@ static int produce_block_map(const char* path, const char* map_file, const char*
PLOG(ERROR) << "failed to find block " << head_block;
return kUncryptIoctlError;
}
+
+ if (block == 0) {
+ LOG(ERROR) << "failed to find block " << head_block << ", retrying";
+ int error = retry_fibmap(fd, path, &block, head_block);
+ if (error != kUncryptNoError) {
+ return error;
+ }
+ }
+
add_block_to_ranges(ranges, block);
if (encrypted) {
if (write_at_offset(buffers[head].data(), sb.st_blksize, wfd,
diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp
index 03089ae41..6755d78cb 100644
--- a/updater/blockimg.cpp
+++ b/updater/blockimg.cpp
@@ -41,27 +41,26 @@
#include <android-base/parseint.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
+#include <applypatch/applypatch.h>
+#include <openssl/sha.h>
#include <ziparchive/zip_archive.h>
-#include "applypatch/applypatch.h"
#include "edify/expr.h"
#include "error_code.h"
#include "updater/install.h"
-#include "openssl/sha.h"
#include "ota_io.h"
#include "print_sha1.h"
#include "updater/updater.h"
-static constexpr size_t BLOCKSIZE = 4096;
-
// Set this to 0 to interpret 'erase' transfers to mean do a
// BLKDISCARD ioctl (the normal behavior). Set to 1 to interpret
// erase to mean fill the region with zeroes.
#define DEBUG_ERASE 0
-#define STASH_DIRECTORY_BASE "/cache/recovery"
-#define STASH_DIRECTORY_MODE 0700
-#define STASH_FILE_MODE 0600
+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;
struct RangeSet {
size_t count; // Limit is INT_MAX.
@@ -507,18 +506,18 @@ static void EnumerateStash(const std::string& dirname, StashCallback callback, v
}
static void UpdateFileSize(const std::string& fn, void* data) {
- if (fn.empty() || !data) {
- return;
- }
+ if (fn.empty() || !data) {
+ return;
+ }
- struct stat sb;
- if (stat(fn.c_str(), &sb) == -1) {
- PLOG(ERROR) << "stat \"" << fn << "\" failed";
- return;
- }
+ struct stat sb;
+ if (stat(fn.c_str(), &sb) == -1) {
+ PLOG(ERROR) << "stat \"" << fn << "\" failed";
+ return;
+ }
- int* size = reinterpret_cast<int*>(data);
- *size += sb.st_size;
+ size_t* size = static_cast<size_t*>(data);
+ *size += sb.st_size;
}
// Deletes the stash directory and all files in it. Assumes that it only
@@ -708,63 +707,67 @@ static int WriteStash(const std::string& base, const std::string& id, int blocks
// hash enough space for the expected amount of blocks we need to store. Returns
// >0 if we created the directory, zero if it existed already, and <0 of failure.
-static int CreateStash(State* state, int maxblocks, const char* blockdev, std::string& base) {
- if (blockdev == nullptr) {
- return -1;
- }
-
- // Stash directory should be different for each partition to avoid conflicts
- // when updating multiple partitions at the same time, so we use the hash of
- // the block device name as the base directory
- uint8_t digest[SHA_DIGEST_LENGTH];
- SHA1(reinterpret_cast<const uint8_t*>(blockdev), strlen(blockdev), digest);
- base = print_sha1(digest);
-
- std::string dirname = GetStashFileName(base, "", "");
- struct stat sb;
- int res = stat(dirname.c_str(), &sb);
-
- if (res == -1 && errno != ENOENT) {
- ErrorAbort(state, kStashCreationFailure, "stat \"%s\" failed: %s\n",
- dirname.c_str(), strerror(errno));
- return -1;
- } else if (res != 0) {
- LOG(INFO) << "creating stash " << dirname;
- res = mkdir(dirname.c_str(), STASH_DIRECTORY_MODE);
+static int CreateStash(State* state, size_t maxblocks, const std::string& blockdev,
+ std::string& base) {
+ if (blockdev.empty()) {
+ return -1;
+ }
- if (res != 0) {
- ErrorAbort(state, kStashCreationFailure, "mkdir \"%s\" failed: %s\n",
- dirname.c_str(), strerror(errno));
- return -1;
- }
+ // Stash directory should be different for each partition to avoid conflicts
+ // when updating multiple partitions at the same time, so we use the hash of
+ // the block device name as the base directory
+ uint8_t digest[SHA_DIGEST_LENGTH];
+ SHA1(reinterpret_cast<const uint8_t*>(blockdev.data()), blockdev.size(), digest);
+ base = print_sha1(digest);
+
+ std::string dirname = GetStashFileName(base, "", "");
+ struct stat sb;
+ int res = stat(dirname.c_str(), &sb);
+ size_t max_stash_size = maxblocks * BLOCKSIZE;
+
+ if (res == -1 && errno != ENOENT) {
+ ErrorAbort(state, kStashCreationFailure, "stat \"%s\" failed: %s\n", dirname.c_str(),
+ strerror(errno));
+ return -1;
+ } else if (res != 0) {
+ LOG(INFO) << "creating stash " << dirname;
+ res = mkdir(dirname.c_str(), STASH_DIRECTORY_MODE);
- if (CacheSizeCheck(maxblocks * BLOCKSIZE) != 0) {
- ErrorAbort(state, kStashCreationFailure, "not enough space for stash\n");
- return -1;
- }
+ if (res != 0) {
+ ErrorAbort(state, kStashCreationFailure, "mkdir \"%s\" failed: %s\n", dirname.c_str(),
+ strerror(errno));
+ return -1;
+ }
- return 1; // Created directory
+ if (CacheSizeCheck(max_stash_size) != 0) {
+ ErrorAbort(state, kStashCreationFailure, "not enough space for stash (%zu needed)\n",
+ max_stash_size);
+ return -1;
}
- LOG(INFO) << "using existing stash " << dirname;
+ return 1; // Created directory
+ }
- // If the directory already exists, calculate the space already allocated to
- // stash files and check if there's enough for all required blocks. Delete any
- // partially completed stash files first.
+ LOG(INFO) << "using existing stash " << dirname;
- EnumerateStash(dirname, DeletePartial, nullptr);
- int size = 0;
- EnumerateStash(dirname, UpdateFileSize, &size);
+ // If the directory already exists, calculate the space already allocated to
+ // stash files and check if there's enough for all required blocks. Delete any
+ // partially completed stash files first.
- size = maxblocks * BLOCKSIZE - size;
+ EnumerateStash(dirname, DeletePartial, nullptr);
+ size_t existing = 0;
+ EnumerateStash(dirname, UpdateFileSize, &existing);
- if (size > 0 && CacheSizeCheck(size) != 0) {
- ErrorAbort(state, kStashCreationFailure, "not enough space for stash (%d more needed)\n",
- size);
- return -1;
+ if (max_stash_size > existing) {
+ size_t needed = max_stash_size - existing;
+ if (CacheSizeCheck(needed) != 0) {
+ ErrorAbort(state, kStashCreationFailure, "not enough space for stash (%zu more needed)\n",
+ needed);
+ return -1;
}
+ }
- return 0; // Using existing directory
+ return 0; // Using existing directory
}
static int SaveStash(CommandParameters& params, const std::string& base,
@@ -1384,8 +1387,7 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
return StringValue("");
}
- UpdaterInfo* ui = reinterpret_cast<UpdaterInfo*>(state->cookie);
-
+ UpdaterInfo* ui = static_cast<UpdaterInfo*>(state->cookie);
if (ui == nullptr) {
return StringValue("");
}
@@ -1443,7 +1445,7 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
}
// First line in transfer list is the version number
- if (!android::base::ParseInt(lines[0].c_str(), &params.version, 1, 4)) {
+ if (!android::base::ParseInt(lines[0], &params.version, 1, 4)) {
LOG(ERROR) << "unexpected transfer list version [" << lines[0] << "]";
return StringValue("");
}
@@ -1451,8 +1453,8 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
LOG(INFO) << "blockimg version is " << params.version;
// Second line in transfer list is the total number of blocks we expect to write
- int total_blocks;
- if (!android::base::ParseInt(lines[1].c_str(), &total_blocks, 0)) {
+ size_t total_blocks;
+ if (!android::base::ParseUint(lines[1], &total_blocks)) {
ErrorAbort(state, kArgsParsingFailure, "unexpected block count [%s]\n", lines[1].c_str());
return StringValue("");
}
@@ -1464,23 +1466,23 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
size_t start = 2;
if (params.version >= 2) {
if (lines.size() < 4) {
- ErrorAbort(state, kArgsParsingFailure, "too few lines in the transfer list [%zu]\n",
- lines.size());
- return StringValue("");
+ ErrorAbort(state, kArgsParsingFailure, "too few lines in the transfer list [%zu]\n",
+ lines.size());
+ return StringValue("");
}
// Third line is how many stash entries are needed simultaneously
LOG(INFO) << "maximum stash entries " << lines[2];
// Fourth line is the maximum number of blocks that will be stashed simultaneously
- int stash_max_blocks;
- if (!android::base::ParseInt(lines[3].c_str(), &stash_max_blocks, 0)) {
+ size_t stash_max_blocks;
+ if (!android::base::ParseUint(lines[3], &stash_max_blocks)) {
ErrorAbort(state, kArgsParsingFailure, "unexpected maximum stash blocks [%s]\n",
lines[3].c_str());
return StringValue("");
}
- int res = CreateStash(state, stash_max_blocks, blockdev_filename->data.c_str(), params.stashbase);
+ int res = CreateStash(state, stash_max_blocks, blockdev_filename->data, params.stashbase);
if (res == -1) {
return StringValue("");
}
@@ -1505,15 +1507,13 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
// Subsequent lines are all individual transfer commands
for (auto it = lines.cbegin() + start; it != lines.cend(); it++) {
- const std::string& line_str(*it);
- if (line_str.empty()) {
- continue;
- }
+ const std::string& line(*it);
+ if (line.empty()) continue;
- params.tokens = android::base::Split(line_str, " ");
+ params.tokens = android::base::Split(line, " ");
params.cpos = 0;
params.cmdname = params.tokens[params.cpos++].c_str();
- params.cmdline = line_str.c_str();
+ params.cmdline = line.c_str();
if (cmd_map.find(params.cmdname) == cmd_map.end()) {
LOG(ERROR) << "unexpected command [" << params.cmdname << "]";
@@ -1523,7 +1523,7 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
const Command* cmd = cmd_map[params.cmdname];
if (cmd->f != nullptr && cmd->f(params) == -1) {
- LOG(ERROR) << "failed to execute command [" << line_str << "]";
+ LOG(ERROR) << "failed to execute command [" << line << "]";
goto pbiudone;
}
@@ -1533,7 +1533,8 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
PLOG(ERROR) << "fsync failed";
goto pbiudone;
}
- fprintf(cmd_pipe, "set_progress %.4f\n", (double) params.written / total_blocks);
+ fprintf(cmd_pipe, "set_progress %.4f\n",
+ static_cast<double>(params.written) / total_blocks);
fflush(cmd_pipe);
}
}
@@ -1546,7 +1547,7 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
LOG(INFO) << "max alloc needed was " << params.buffer.size();
const char* partition = strrchr(blockdev_filename->data.c_str(), '/');
- if (partition != nullptr && *(partition+1) != 0) {
+ if (partition != nullptr && *(partition + 1) != 0) {
fprintf(cmd_pipe, "log bytes_written_%s: %zu\n", partition + 1,
params.written * BLOCKSIZE);
fprintf(cmd_pipe, "log bytes_stashed_%s: %zu\n", partition + 1,