diff options
-rw-r--r-- | minadbd/README.md (renamed from minadbd/README.txt) | 2 | ||||
-rw-r--r-- | recovery.cpp | 4 | ||||
-rw-r--r-- | uncrypt/uncrypt.cpp | 41 |
3 files changed, 43 insertions, 4 deletions
diff --git a/minadbd/README.txt b/minadbd/README.md index e69dc87c6..5a0a067de 100644 --- a/minadbd/README.txt +++ b/minadbd/README.md @@ -3,6 +3,6 @@ minadbd, and services.c has been modified as follows: - all services removed - all host mode support removed - - sideload_service() added; this is the only service supported. It + - `sideload_service()` added; this is the only service supported. It receives a single blob of data, writes it to a fixed filename, and makes the process exit. diff --git a/recovery.cpp b/recovery.cpp index 5888c542a..fac241d63 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -322,7 +322,7 @@ static std::vector<std::string> get_args(const int argc, char** const argv) { std::vector<std::string> args(argv, argv + argc); // --- if arguments weren't supplied, look in the bootloader control block - if (argc == 1) { + if (args.size() == 1) { boot.recovery[sizeof(boot.recovery) - 1] = '\0'; // Ensure termination std::string boot_recovery(boot.recovery); std::vector<std::string> tokens = android::base::Split(boot_recovery, "\n"); @@ -338,7 +338,7 @@ static std::vector<std::string> get_args(const int argc, char** const argv) { } // --- if that doesn't work, try the command file (if we have /cache). - if (argc == 1 && has_cache) { + if (args.size() == 1 && has_cache) { std::string content; if (ensure_path_mounted(COMMAND_FILE) == 0 && android::base::ReadFileToString(COMMAND_FILE, &content)) { diff --git a/uncrypt/uncrypt.cpp b/uncrypt/uncrypt.cpp index 4ac516d21..a06384dd5 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, |