diff options
-rw-r--r-- | applypatch/applypatch.cpp | 12 | ||||
-rw-r--r-- | bootloader.h | 8 | ||||
-rw-r--r-- | common.h | 8 | ||||
-rw-r--r-- | edify/Android.mk | 8 | ||||
-rw-r--r-- | minadbd/adb_main.cpp | 2 | ||||
-rw-r--r-- | print_sha1.h | 43 | ||||
-rw-r--r-- | recovery.cpp | 2 | ||||
-rw-r--r-- | uncrypt/Android.mk | 2 | ||||
-rw-r--r-- | uncrypt/uncrypt.cpp | 32 | ||||
-rw-r--r-- | unique_fd.h | 73 | ||||
-rw-r--r-- | updater/blockimg.cpp | 406 |
11 files changed, 294 insertions, 302 deletions
diff --git a/applypatch/applypatch.cpp b/applypatch/applypatch.cpp index 751d3e392..1767761a8 100644 --- a/applypatch/applypatch.cpp +++ b/applypatch/applypatch.cpp @@ -31,6 +31,7 @@ #include "applypatch.h" #include "mtdutils/mtdutils.h" #include "edify/expr.h" +#include "print_sha1.h" static int LoadPartitionContents(const char* filename, FileContents* file); static ssize_t FileSink(const unsigned char* data, ssize_t len, void* token); @@ -43,7 +44,6 @@ static int GenerateTarget(FileContents* source_file, const uint8_t target_sha1[SHA_DIGEST_SIZE], size_t target_size, const Value* bonus_data); -static std::string short_sha1(const uint8_t sha1[SHA_DIGEST_SIZE]); static bool mtd_partitions_scanned = false; @@ -630,16 +630,6 @@ int CacheSizeCheck(size_t bytes) { } } -static std::string short_sha1(const uint8_t sha1[SHA_DIGEST_SIZE]) { - const char* hex = "0123456789abcdef"; - std::string result = ""; - for (size_t i = 0; i < 4; ++i) { - result.push_back(hex[(sha1[i]>>4) & 0xf]); - result.push_back(hex[sha1[i] & 0xf]); - } - return result; -} - // This function applies binary patches to files in a way that is safe // (the original file is not touched until we have the desired // replacement for it) and idempotent (it's okay to run this program diff --git a/bootloader.h b/bootloader.h index c2895dd91..4e9fb0a0d 100644 --- a/bootloader.h +++ b/bootloader.h @@ -17,10 +17,6 @@ #ifndef _RECOVERY_BOOTLOADER_H #define _RECOVERY_BOOTLOADER_H -#ifdef __cplusplus -extern "C" { -#endif - /* Bootloader Message * * This structure describes the content of a block in flash @@ -64,8 +60,4 @@ struct bootloader_message { int get_bootloader_message(struct bootloader_message *out); int set_bootloader_message(const struct bootloader_message *in); -#ifdef __cplusplus -} -#endif - #endif @@ -21,10 +21,6 @@ #include <stdio.h> #include <stdarg.h> -#ifdef __cplusplus -extern "C" { -#endif - #define LOGE(...) ui_print("E:" __VA_ARGS__) #define LOGW(...) fprintf(stdout, "W:" __VA_ARGS__) #define LOGI(...) fprintf(stdout, "I:" __VA_ARGS__) @@ -50,8 +46,4 @@ void ui_print(const char* format, ...); bool is_ro_debuggable(); -#ifdef __cplusplus -} -#endif - #endif // RECOVERY_COMMON_H diff --git a/edify/Android.mk b/edify/Android.mk index c36645045..eb366c287 100644 --- a/edify/Android.mk +++ b/edify/Android.mk @@ -21,10 +21,10 @@ LOCAL_SRC_FILES := \ $(edify_src_files) \ main.c -LOCAL_CFLAGS := $(edify_cflags) -g -O0 +LOCAL_CPPFLAGS := $(edify_cflags) -g -O0 LOCAL_MODULE := edify LOCAL_YACCFLAGS := -v -LOCAL_CFLAGS += -Wno-unused-parameter +LOCAL_CPPFLAGS += -Wno-unused-parameter LOCAL_CLANG := true include $(BUILD_HOST_EXECUTABLE) @@ -36,8 +36,8 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := $(edify_src_files) -LOCAL_CFLAGS := $(edify_cflags) -LOCAL_CFLAGS += -Wno-unused-parameter +LOCAL_CPPFLAGS := $(edify_cflags) +LOCAL_CPPFLAGS += -Wno-unused-parameter LOCAL_MODULE := libedify LOCAL_CLANG := true diff --git a/minadbd/adb_main.cpp b/minadbd/adb_main.cpp index 724f39c1d..514f19699 100644 --- a/minadbd/adb_main.cpp +++ b/minadbd/adb_main.cpp @@ -27,7 +27,7 @@ #include "adb_auth.h" #include "transport.h" -int adb_main(int is_daemon, int server_port) { +int adb_main(int is_daemon, int server_port, int /* reply_fd */) { adb_device_banner = "sideload"; signal(SIGPIPE, SIG_IGN); diff --git a/print_sha1.h b/print_sha1.h new file mode 100644 index 000000000..9e37c5fe3 --- /dev/null +++ b/print_sha1.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2015 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 RECOVERY_PRINT_SHA1_H +#define RECOVERY_PRINT_SHA1_H + +#include <stdint.h> +#include <string> + +#include "mincrypt/sha.h" + +static std::string print_sha1(const uint8_t sha1[SHA_DIGEST_SIZE], size_t len) { + const char* hex = "0123456789abcdef"; + std::string result = ""; + for (size_t i = 0; i < len; ++i) { + result.push_back(hex[(sha1[i]>>4) & 0xf]); + result.push_back(hex[sha1[i] & 0xf]); + } + return result; +} + +static std::string print_sha1(const uint8_t sha1[SHA_DIGEST_SIZE]) { + return print_sha1(sha1, SHA_DIGEST_SIZE); +} + +static std::string short_sha1(const uint8_t sha1[SHA_DIGEST_SIZE]) { + return print_sha1(sha1, 4); +} + +#endif // RECOVERY_PRINT_SHA1_H diff --git a/recovery.cpp b/recovery.cpp index d90e10a8b..c683bae1d 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -942,7 +942,7 @@ main(int argc, char **argv) { // only way recovery should be run with this argument is when it // starts a copy of itself from the apply_from_adb() function. if (argc == 2 && strcmp(argv[1], "--adbd") == 0) { - adb_main(0, DEFAULT_ADB_PORT); + adb_main(0, DEFAULT_ADB_PORT, -1); return 0; } diff --git a/uncrypt/Android.mk b/uncrypt/Android.mk index e73c8f1b6..f31db4243 100644 --- a/uncrypt/Android.mk +++ b/uncrypt/Android.mk @@ -20,6 +20,8 @@ LOCAL_CLANG := true LOCAL_SRC_FILES := uncrypt.cpp +LOCAL_C_INCLUDES := $(LOCAL_PATH)/.. + LOCAL_MODULE := uncrypt LOCAL_STATIC_LIBRARIES := libbase liblog libfs_mgr libcutils diff --git a/uncrypt/uncrypt.cpp b/uncrypt/uncrypt.cpp index 8785b29af..aef480035 100644 --- a/uncrypt/uncrypt.cpp +++ b/uncrypt/uncrypt.cpp @@ -51,6 +51,8 @@ #include <sys/types.h> #include <unistd.h> +#include <memory> + #include <base/file.h> #include <base/strings.h> #include <cutils/android_reboot.h> @@ -60,6 +62,8 @@ #define LOG_TAG "uncrypt" #include <log/log.h> +#include "unique_fd.h" + #define WINDOW_SIZE 5 static const std::string cache_block_map = "/cache/recovery/block.map"; @@ -183,6 +187,7 @@ static int produce_block_map(const char* path, const char* map_file, const char* return -1; } FILE* mapf = fdopen(mapfd, "w"); + unique_file mapf_holder(mapf); // Make sure we can write to the status_file. if (!android::base::WriteStringToFd("0\n", status_fd)) { @@ -191,8 +196,7 @@ static int produce_block_map(const char* path, const char* map_file, const char* } struct stat sb; - int ret = stat(path, &sb); - if (ret != 0) { + if (stat(path, &sb) != 0) { ALOGE("failed to stat %s\n", path); return -1; } @@ -221,15 +225,18 @@ static int produce_block_map(const char* path, const char* map_file, const char* size_t pos = 0; int fd = open(path, O_RDONLY); - if (fd < 0) { + unique_fd fd_holder(fd); + if (fd == -1) { ALOGE("failed to open fd for reading: %s\n", strerror(errno)); return -1; } int wfd = -1; + unique_fd wfd_holder(wfd); if (encrypted) { wfd = open(blk_dev, O_WRONLY | O_SYNC); - if (wfd < 0) { + wfd_holder = unique_fd(wfd); + if (wfd == -1) { ALOGE("failed to open fd for writing: %s\n", strerror(errno)); return -1; } @@ -247,8 +254,7 @@ static int produce_block_map(const char* path, const char* map_file, const char* if ((tail+1) % WINDOW_SIZE == head) { // write out head buffer int block = head_block; - ret = ioctl(fd, FIBMAP, &block); - if (ret != 0) { + if (ioctl(fd, FIBMAP, &block) != 0) { ALOGE("failed to find block %d\n", head_block); return -1; } @@ -288,8 +294,7 @@ static int produce_block_map(const char* path, const char* map_file, const char* while (head != tail) { // write out head buffer int block = head_block; - ret = ioctl(fd, FIBMAP, &block); - if (ret != 0) { + if (ioctl(fd, FIBMAP, &block) != 0) { ALOGE("failed to find block %d\n", head_block); return -1; } @@ -313,14 +318,11 @@ static int produce_block_map(const char* path, const char* map_file, const char* ALOGE("failed to fsync \"%s\": %s\n", map_file, strerror(errno)); return -1; } - fclose(mapf); - close(fd); if (encrypted) { if (fsync(wfd) == -1) { ALOGE("failed to fsync \"%s\": %s\n", blk_dev, strerror(errno)); return -1; } - close(wfd); } return 0; @@ -333,6 +335,8 @@ static void wipe_misc() { if (!v->mount_point) continue; if (strcmp(v->mount_point, "/misc") == 0) { int fd = open(v->blk_device, O_WRONLY | O_SYNC); + unique_fd fd_holder(fd); + uint8_t zeroes[1088]; // sizeof(bootloader_message) from recovery memset(zeroes, 0, sizeof(zeroes)); @@ -349,10 +353,8 @@ static void wipe_misc() { } if (fsync(fd) == -1) { ALOGE("failed to fsync \"%s\": %s\n", v->blk_device, strerror(errno)); - close(fd); return; } - close(fd); } } } @@ -437,6 +439,7 @@ int main(int argc, char** argv) { ALOGE("failed to open pipe \"%s\": %s\n", status_file.c_str(), strerror(errno)); return 1; } + unique_fd status_fd_holder(status_fd); if (argc == 3) { // when command-line args are given this binary is being used @@ -447,7 +450,6 @@ int main(int argc, char** argv) { std::string package; if (!find_uncrypt_package(package)) { android::base::WriteStringToFd("-1\n", status_fd); - close(status_fd); return 1; } input_path = package.c_str(); @@ -457,12 +459,10 @@ int main(int argc, char** argv) { int status = uncrypt(input_path, map_file, status_fd); if (status != 0) { android::base::WriteStringToFd("-1\n", status_fd); - close(status_fd); return 1; } android::base::WriteStringToFd("100\n", status_fd); - close(status_fd); } return 0; diff --git a/unique_fd.h b/unique_fd.h new file mode 100644 index 000000000..98a7c7b67 --- /dev/null +++ b/unique_fd.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2015 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 UNIQUE_FD_H +#define UNIQUE_FD_H + +#include <stdio.h> + +#include <memory> + +class unique_fd { + public: + unique_fd(int fd) : fd_(fd) { } + + unique_fd(unique_fd&& uf) { + fd_ = uf.fd_; + uf.fd_ = -1; + } + + ~unique_fd() { + if (fd_ != -1) { + close(fd_); + } + } + + int get() { + return fd_; + } + + // Movable. + unique_fd& operator=(unique_fd&& uf) { + fd_ = uf.fd_; + uf.fd_ = -1; + return *this; + } + + explicit operator bool() const { + return fd_ != -1; + } + + private: + int fd_; + + // Non-copyable. + unique_fd(const unique_fd&) = delete; + unique_fd& operator=(const unique_fd&) = delete; +}; + +// Custom deleter for unique_file to avoid fclose(NULL). +struct safe_fclose { + void operator()(FILE *fp) const { + if (fp) { + fclose(fp); + }; + } +}; + +using unique_file = std::unique_ptr<FILE, safe_fclose>; + +#endif // UNIQUE_FD_H diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp index 77117db05..3a07da404 100644 --- a/updater/blockimg.cpp +++ b/updater/blockimg.cpp @@ -32,11 +32,17 @@ #include <time.h> #include <unistd.h> +#include <memory> +#include <string> + +#include <base/strings.h> + #include "applypatch/applypatch.h" #include "edify/expr.h" #include "mincrypt/sha.h" #include "minzip/Hash.h" #include "updater.h" +#include "print_sha1.h" #define BLOCKSIZE 4096 @@ -49,8 +55,6 @@ #define STASH_DIRECTORY_MODE 0700 #define STASH_FILE_MODE 0600 -char* PrintSha1(const uint8_t* digest); - typedef struct { int count; int size; @@ -144,28 +148,22 @@ err: exit(1); } -static int range_overlaps(RangeSet* r1, RangeSet* r2) { - int i, j, r1_0, r1_1, r2_0, r2_1; - - if (!r1 || !r2) { - return 0; - } - - for (i = 0; i < r1->count; ++i) { - r1_0 = r1->pos[i * 2]; - r1_1 = r1->pos[i * 2 + 1]; +static bool range_overlaps(const RangeSet& r1, const RangeSet& r2) { + for (int i = 0; i < r1.count; ++i) { + int r1_0 = r1.pos[i * 2]; + int r1_1 = r1.pos[i * 2 + 1]; - for (j = 0; j < r2->count; ++j) { - r2_0 = r2->pos[j * 2]; - r2_1 = r2->pos[j * 2 + 1]; + for (int j = 0; j < r2.count; ++j) { + int r2_0 = r2.pos[j * 2]; + int r2_1 = r2.pos[j * 2 + 1]; if (!(r2_0 >= r1_1 || r1_0 >= r2_1)) { - return 1; + return true; } } } - return 0; + return false; } static int read_all(int fd, uint8_t* data, size_t size) { @@ -404,7 +402,7 @@ static int WriteBlocks(RangeSet* tgt, uint8_t* buffer, int fd) { // in *tgt, if tgt is non-NULL. static int LoadSrcTgtVersion1(char** wordsave, RangeSet** tgt, int* src_blocks, - uint8_t** buffer, size_t* buffer_alloc, int fd) { + uint8_t** buffer, size_t* buffer_alloc, int fd) { char* word; int rc; @@ -425,8 +423,7 @@ static int LoadSrcTgtVersion1(char** wordsave, RangeSet** tgt, int* src_blocks, } static int VerifyBlocks(const char *expected, const uint8_t *buffer, - size_t blocks, int printerror) { - char* hexdigest = NULL; + size_t blocks, bool printerror) { int rc = -1; uint8_t digest[SHA_DIGEST_SIZE]; @@ -435,128 +432,75 @@ static int VerifyBlocks(const char *expected, const uint8_t *buffer, } SHA_hash(buffer, blocks * BLOCKSIZE, digest); - hexdigest = PrintSha1(digest); - if (hexdigest != NULL) { - rc = strcmp(expected, hexdigest); + std::string hexdigest = print_sha1(digest); - if (rc != 0 && printerror) { - fprintf(stderr, "failed to verify blocks (expected %s, read %s)\n", - expected, hexdigest); - } + rc = hexdigest != std::string(expected); - free(hexdigest); + if (rc != 0 && printerror) { + fprintf(stderr, "failed to verify blocks (expected %s, read %s)\n", + expected, hexdigest.c_str()); } return rc; } -static char* GetStashFileName(const char* base, const char* id, const char* postfix) { - char* fn; - int len; - int res; - - if (base == NULL) { - return NULL; +static std::string GetStashFileName(const std::string& base, const std::string id, + const std::string postfix) { + if (base.empty()) { + return ""; } - if (id == NULL) { - id = ""; - } - - if (postfix == NULL) { - postfix = ""; - } - - len = strlen(STASH_DIRECTORY_BASE) + 1 + strlen(base) + 1 + strlen(id) + strlen(postfix) + 1; - fn = reinterpret_cast<char*>(malloc(len)); - - if (fn == NULL) { - fprintf(stderr, "failed to malloc %d bytes for fn\n", len); - return NULL; - } - - res = snprintf(fn, len, STASH_DIRECTORY_BASE "/%s/%s%s", base, id, postfix); - - if (res < 0 || res >= len) { - fprintf(stderr, "failed to format file name (return value %d)\n", res); - free(fn); - return NULL; - } + std::string fn(STASH_DIRECTORY_BASE); + fn += "/" + base + "/" + id + postfix; return fn; } -typedef void (*StashCallback)(const char*, void*); +typedef void (*StashCallback)(const std::string&, void*); // Does a best effort enumeration of stash files. Ignores possible non-file // items in the stash directory and continues despite of errors. Calls the // 'callback' function for each file and passes 'data' to the function as a // parameter. -static void EnumerateStash(const char* dirname, StashCallback callback, void* data) { - char* fn; - DIR* directory; - int len; - int res; - struct dirent* item; - - if (dirname == NULL || callback == NULL) { +static void EnumerateStash(const std::string& dirname, StashCallback callback, void* data) { + if (dirname.empty() || callback == NULL) { return; } - directory = opendir(dirname); + std::unique_ptr<DIR, int(*)(DIR*)> directory(opendir(dirname.c_str()), closedir); if (directory == NULL) { if (errno != ENOENT) { - fprintf(stderr, "opendir \"%s\" failed: %s\n", dirname, strerror(errno)); + fprintf(stderr, "opendir \"%s\" failed: %s\n", dirname.c_str(), strerror(errno)); } return; } - while ((item = readdir(directory)) != NULL) { + struct dirent* item; + while ((item = readdir(directory.get())) != NULL) { if (item->d_type != DT_REG) { continue; } - len = strlen(dirname) + 1 + strlen(item->d_name) + 1; - fn = reinterpret_cast<char*>(malloc(len)); - - if (fn == NULL) { - fprintf(stderr, "failed to malloc %d bytes for fn\n", len); - continue; - } - - res = snprintf(fn, len, "%s/%s", dirname, item->d_name); - - if (res < 0 || res >= len) { - fprintf(stderr, "failed to format file name (return value %d)\n", res); - free(fn); - continue; - } - + std::string fn = dirname + "/" + std::string(item->d_name); callback(fn, data); - free(fn); - } - - if (closedir(directory) == -1) { - fprintf(stderr, "closedir \"%s\" failed: %s\n", dirname, strerror(errno)); } } -static void UpdateFileSize(const char* fn, void* data) { - int* size = (int*) data; - struct stat st; - - if (!fn || !data) { +static void UpdateFileSize(const std::string& fn, void* data) { + if (fn.empty() || !data) { return; } - if (stat(fn, &st) == -1) { - fprintf(stderr, "stat \"%s\" failed: %s\n", fn, strerror(errno)); + struct stat st; + if (stat(fn.c_str(), &st) == -1) { + fprintf(stderr, "stat \"%s\" failed: %s\n", fn.c_str(), strerror(errno)); return; } + int* size = reinterpret_cast<int*>(data); *size += st.st_size; } @@ -564,57 +508,49 @@ static void UpdateFileSize(const char* fn, void* data) { // contains files. There is nothing we can do about unlikely, but possible // errors, so they are merely logged. -static void DeleteFile(const char* fn, void* data) { - if (fn) { - fprintf(stderr, "deleting %s\n", fn); +static void DeleteFile(const std::string& fn, void* data) { + if (!fn.empty()) { + fprintf(stderr, "deleting %s\n", fn.c_str()); - if (unlink(fn) == -1 && errno != ENOENT) { - fprintf(stderr, "unlink \"%s\" failed: %s\n", fn, strerror(errno)); + if (unlink(fn.c_str()) == -1 && errno != ENOENT) { + fprintf(stderr, "unlink \"%s\" failed: %s\n", fn.c_str(), strerror(errno)); } } } -static void DeletePartial(const char* fn, void* data) { - if (fn && strstr(fn, ".partial") != NULL) { +static void DeletePartial(const std::string& fn, void* data) { + if (android::base::EndsWith(fn, ".partial")) { DeleteFile(fn, data); } } -static void DeleteStash(const char* base) { - char* dirname; - - if (base == NULL) { +static void DeleteStash(const std::string& base) { + if (base.empty()) { return; } - dirname = GetStashFileName(base, NULL, NULL); - - if (dirname == NULL) { - return; - } + fprintf(stderr, "deleting stash %s\n", base.c_str()); - fprintf(stderr, "deleting stash %s\n", base); + std::string dirname = GetStashFileName(base, "", ""); EnumerateStash(dirname, DeleteFile, NULL); - if (rmdir(dirname) == -1) { + if (rmdir(dirname.c_str()) == -1) { if (errno != ENOENT && errno != ENOTDIR) { - fprintf(stderr, "rmdir \"%s\" failed: %s\n", dirname, strerror(errno)); + fprintf(stderr, "rmdir \"%s\" failed: %s\n", dirname.c_str(), strerror(errno)); } } - - free(dirname); } -static int LoadStash(const char* base, const char* id, int verify, int* blocks, uint8_t** buffer, - size_t* buffer_alloc, int printnoent) { - char *fn = NULL; +static int LoadStash(const std::string& base, const char* id, int verify, int* blocks, + uint8_t** buffer, size_t* buffer_alloc, bool printnoent) { + std::string fn; int blockcount = 0; int fd = -1; int rc = -1; int res; struct stat st; - if (!base || !id || !buffer || !buffer_alloc) { + if (base.empty() || !id || !buffer || !buffer_alloc) { goto lsout; } @@ -622,33 +558,29 @@ static int LoadStash(const char* base, const char* id, int verify, int* blocks, blocks = &blockcount; } - fn = GetStashFileName(base, id, NULL); - - if (fn == NULL) { - goto lsout; - } + fn = GetStashFileName(base, std::string(id), ""); - res = stat(fn, &st); + res = stat(fn.c_str(), &st); if (res == -1) { if (errno != ENOENT || printnoent) { - fprintf(stderr, "stat \"%s\" failed: %s\n", fn, strerror(errno)); + fprintf(stderr, "stat \"%s\" failed: %s\n", fn.c_str(), strerror(errno)); } goto lsout; } - fprintf(stderr, " loading %s\n", fn); + fprintf(stderr, " loading %s\n", fn.c_str()); if ((st.st_size % BLOCKSIZE) != 0) { fprintf(stderr, "%s size %" PRId64 " not multiple of block size %d", - fn, static_cast<int64_t>(st.st_size), BLOCKSIZE); + fn.c_str(), static_cast<int64_t>(st.st_size), BLOCKSIZE); goto lsout; } - fd = TEMP_FAILURE_RETRY(open(fn, O_RDONLY)); + fd = TEMP_FAILURE_RETRY(open(fn.c_str(), O_RDONLY)); if (fd == -1) { - fprintf(stderr, "open \"%s\" failed: %s\n", fn, strerror(errno)); + fprintf(stderr, "open \"%s\" failed: %s\n", fn.c_str(), strerror(errno)); goto lsout; } @@ -660,8 +592,8 @@ static int LoadStash(const char* base, const char* id, int verify, int* blocks, *blocks = st.st_size / BLOCKSIZE; - if (verify && VerifyBlocks(id, *buffer, *blocks, 1) != 0) { - fprintf(stderr, "unexpected contents in %s\n", fn); + if (verify && VerifyBlocks(id, *buffer, *blocks, true) != 0) { + fprintf(stderr, "unexpected contents in %s\n", fn.c_str()); DeleteFile(fn, NULL); goto lsout; } @@ -673,23 +605,21 @@ lsout: close(fd); } - if (fn) { - free(fn); - } - return rc; } -static int WriteStash(const char* base, const char* id, int blocks, uint8_t* buffer, - int checkspace, int *exists) { - char *fn = NULL; - char *cn = NULL; +static int WriteStash(const std::string& base, const char* id, int blocks, + uint8_t* buffer, bool checkspace, int *exists) { + std::string fn; + std::string cn; + std::string dname; int fd = -1; int rc = -1; + int dfd = -1; int res; struct stat st; - if (base == NULL || buffer == NULL) { + if (base.empty() || buffer == NULL) { goto wsout; } @@ -698,21 +628,17 @@ static int WriteStash(const char* base, const char* id, int blocks, uint8_t* buf goto wsout; } - fn = GetStashFileName(base, id, ".partial"); - cn = GetStashFileName(base, id, NULL); - - if (fn == NULL || cn == NULL) { - goto wsout; - } + fn = GetStashFileName(base, std::string(id), ".partial"); + cn = GetStashFileName(base, std::string(id), ""); if (exists) { - res = stat(cn, &st); + res = stat(cn.c_str(), &st); if (res == 0) { // The file already exists and since the name is the hash of the contents, // it's safe to assume the contents are identical (accidental hash collisions // are unlikely) - fprintf(stderr, " skipping %d existing blocks in %s\n", blocks, cn); + fprintf(stderr, " skipping %d existing blocks in %s\n", blocks, cn.c_str()); *exists = 1; rc = 0; goto wsout; @@ -721,12 +647,12 @@ static int WriteStash(const char* base, const char* id, int blocks, uint8_t* buf *exists = 0; } - fprintf(stderr, " writing %d blocks to %s\n", blocks, cn); + fprintf(stderr, " writing %d blocks to %s\n", blocks, cn.c_str()); - fd = TEMP_FAILURE_RETRY(open(fn, O_WRONLY | O_CREAT | O_TRUNC, STASH_FILE_MODE)); + fd = TEMP_FAILURE_RETRY(open(fn.c_str(), O_WRONLY | O_CREAT | O_TRUNC, STASH_FILE_MODE)); if (fd == -1) { - fprintf(stderr, "failed to create \"%s\": %s\n", fn, strerror(errno)); + fprintf(stderr, "failed to create \"%s\": %s\n", fn.c_str(), strerror(errno)); goto wsout; } @@ -735,12 +661,26 @@ static int WriteStash(const char* base, const char* id, int blocks, uint8_t* buf } if (fsync(fd) == -1) { - fprintf(stderr, "fsync \"%s\" failed: %s\n", fn, strerror(errno)); + fprintf(stderr, "fsync \"%s\" failed: %s\n", fn.c_str(), strerror(errno)); + goto wsout; + } + + if (rename(fn.c_str(), cn.c_str()) == -1) { + fprintf(stderr, "rename(\"%s\", \"%s\") failed: %s\n", fn.c_str(), cn.c_str(), + strerror(errno)); + goto wsout; + } + + dname = GetStashFileName(base, "", ""); + dfd = TEMP_FAILURE_RETRY(open(dname.c_str(), O_RDONLY | O_DIRECTORY)); + + if (dfd == -1) { + fprintf(stderr, "failed to open \"%s\" failed: %s\n", dname.c_str(), strerror(errno)); goto wsout; } - if (rename(fn, cn) == -1) { - fprintf(stderr, "rename(\"%s\", \"%s\") failed: %s\n", fn, cn, strerror(errno)); + if (fsync(dfd) == -1) { + fprintf(stderr, "fsync \"%s\" failed: %s\n", dname.c_str(), strerror(errno)); goto wsout; } @@ -751,12 +691,8 @@ wsout: close(fd); } - if (fn) { - free(fn); - } - - if (cn) { - free(cn); + if (dfd != -1) { + close(dfd); } return rc; @@ -766,103 +702,79 @@ wsout: // 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, char** base) { - char* dirname = NULL; - const uint8_t* digest; - int rc = -1; - int res; - int size = 0; - SHA_CTX ctx; - struct stat st; - - if (blockdev == NULL || base == NULL) { - goto csout; +static int CreateStash(State* state, int maxblocks, const char* blockdev, + std::string& base) { + if (blockdev == NULL) { + 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 + SHA_CTX ctx; SHA_init(&ctx); SHA_update(&ctx, blockdev, strlen(blockdev)); - digest = SHA_final(&ctx); - *base = PrintSha1(digest); + const uint8_t* digest = SHA_final(&ctx); + base = print_sha1(digest); - if (*base == NULL) { - goto csout; - } - - dirname = GetStashFileName(*base, NULL, NULL); - - if (dirname == NULL) { - goto csout; - } - - res = stat(dirname, &st); + std::string dirname = GetStashFileName(base, "", ""); + struct stat st; + int res = stat(dirname.c_str(), &st); if (res == -1 && errno != ENOENT) { - ErrorAbort(state, "stat \"%s\" failed: %s\n", dirname, strerror(errno)); - goto csout; + ErrorAbort(state, "stat \"%s\" failed: %s\n", dirname.c_str(), strerror(errno)); + return -1; } else if (res != 0) { - fprintf(stderr, "creating stash %s\n", dirname); - res = mkdir(dirname, STASH_DIRECTORY_MODE); + fprintf(stderr, "creating stash %s\n", dirname.c_str()); + res = mkdir(dirname.c_str(), STASH_DIRECTORY_MODE); if (res != 0) { - ErrorAbort(state, "mkdir \"%s\" failed: %s\n", dirname, strerror(errno)); - goto csout; + ErrorAbort(state, "mkdir \"%s\" failed: %s\n", dirname.c_str(), strerror(errno)); + return -1; } if (CacheSizeCheck(maxblocks * BLOCKSIZE) != 0) { ErrorAbort(state, "not enough space for stash\n"); - goto csout; + return -1; } - rc = 1; // Created directory - goto csout; + return 1; // Created directory } - fprintf(stderr, "using existing stash %s\n", dirname); + fprintf(stderr, "using existing stash %s\n", dirname.c_str()); // 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. EnumerateStash(dirname, DeletePartial, NULL); + int size = 0; EnumerateStash(dirname, UpdateFileSize, &size); size = (maxblocks * BLOCKSIZE) - size; if (size > 0 && CacheSizeCheck(size) != 0) { ErrorAbort(state, "not enough space for stash (%d more needed)\n", size); - goto csout; - } - - rc = 0; // Using existing directory - -csout: - if (dirname) { - free(dirname); + return -1; } - return rc; + return 0; // Using existing directory } -static int SaveStash(const char* base, char** wordsave, uint8_t** buffer, size_t* buffer_alloc, - int fd, int usehash, int* isunresumable) { - char *id = NULL; - int blocks = 0; - +static int SaveStash(const std::string& base, char** wordsave, uint8_t** buffer, + size_t* buffer_alloc, int fd, int usehash, bool* isunresumable) { if (!wordsave || !buffer || !buffer_alloc || !isunresumable) { return -1; } - id = strtok_r(NULL, " ", wordsave); - + char *id = strtok_r(NULL, " ", wordsave); if (id == NULL) { fprintf(stderr, "missing id field in stash command\n"); return -1; } - if (usehash && LoadStash(base, id, 1, &blocks, buffer, buffer_alloc, 0) == 0) { + int blocks = 0; + if (usehash && LoadStash(base, id, 1, &blocks, buffer, buffer_alloc, false) == 0) { // Stash file already exists and has expected contents. Do not // read from source again, as the source may have been already // overwritten during a previous attempt. @@ -873,7 +785,7 @@ static int SaveStash(const char* base, char** wordsave, uint8_t** buffer, size_t return -1; } - if (usehash && VerifyBlocks(id, *buffer, blocks, 1) != 0) { + if (usehash && VerifyBlocks(id, *buffer, blocks, true) != 0) { // Source blocks have unexpected contents. If we actually need this // data later, this is an unrecoverable error. However, the command // that uses the data may have already completed previously, so the @@ -883,24 +795,17 @@ static int SaveStash(const char* base, char** wordsave, uint8_t** buffer, size_t } fprintf(stderr, "stashing %d blocks to %s\n", blocks, id); - return WriteStash(base, id, blocks, *buffer, 0, NULL); + return WriteStash(base, id, blocks, *buffer, false, NULL); } -static int FreeStash(const char* base, const char* id) { - char *fn = NULL; - - if (base == NULL || id == NULL) { +static int FreeStash(const std::string& base, const char* id) { + if (base.empty() || id == NULL) { return -1; } - fn = GetStashFileName(base, id, NULL); - - if (fn == NULL) { - return -1; - } + std::string fn = GetStashFileName(base, std::string(id), ""); DeleteFile(fn, NULL); - free(fn); return 0; } @@ -939,8 +844,8 @@ static void MoveRange(uint8_t* dest, RangeSet* locs, const uint8_t* source) { // target RangeSet. Any stashes required are loaded using LoadStash. static int LoadSrcTgtVersion2(char** wordsave, RangeSet** tgt, int* src_blocks, - uint8_t** buffer, size_t* buffer_alloc, int fd, - const char* stashbase, int* overlap) { + uint8_t** buffer, size_t* buffer_alloc, int fd, + const std::string& stashbase, bool* overlap) { char* word; char* colonsave; char* colon; @@ -967,7 +872,7 @@ static int LoadSrcTgtVersion2(char** wordsave, RangeSet** tgt, int* src_blocks, res = ReadBlocks(src, *buffer, fd); if (overlap && tgt) { - *overlap = range_overlaps(src, *tgt); + *overlap = range_overlaps(*src, **tgt); } free(src); @@ -994,7 +899,7 @@ static int LoadSrcTgtVersion2(char** wordsave, RangeSet** tgt, int* src_blocks, colonsave = NULL; colon = strtok_r(word, ":", &colonsave); - res = LoadStash(stashbase, colon, 0, NULL, &stash, &stashalloc, 1); + res = LoadStash(stashbase, colon, 0, NULL, &stash, &stashalloc, true); if (res == -1) { // These source blocks will fail verification if used later, but we @@ -1022,12 +927,12 @@ typedef struct { char* cmdname; char* cpos; char* freestash; - char* stashbase; - int canwrite; + std::string stashbase; + bool canwrite; int createdstash; int fd; int foundwrites; - int isunresumable; + bool isunresumable; int version; int written; NewThreadInfo nti; @@ -1055,7 +960,7 @@ typedef struct { // can be performed. static int LoadSrcTgtVersion3(CommandParameters* params, RangeSet** tgt, int* src_blocks, - int onehash, int* overlap) { + int onehash, bool* overlap) { char* srchash = NULL; char* tgthash = NULL; int stash_exists = 0; @@ -1100,20 +1005,20 @@ static int LoadSrcTgtVersion3(CommandParameters* params, RangeSet** tgt, int* sr goto v3out; } - if (VerifyBlocks(tgthash, tgtbuffer, (*tgt)->size, 0) == 0) { + if (VerifyBlocks(tgthash, tgtbuffer, (*tgt)->size, false) == 0) { // Target blocks already have expected content, command should be skipped rc = 1; goto v3out; } - if (VerifyBlocks(srchash, params->buffer, *src_blocks, 1) == 0) { + if (VerifyBlocks(srchash, params->buffer, *src_blocks, true) == 0) { // If source and target blocks overlap, stash the source blocks so we can // resume from possible write errors if (*overlap) { fprintf(stderr, "stashing %d overlapping blocks to %s\n", *src_blocks, srchash); - if (WriteStash(params->stashbase, srchash, *src_blocks, params->buffer, 1, + if (WriteStash(params->stashbase, srchash, *src_blocks, params->buffer, true, &stash_exists) != 0) { fprintf(stderr, "failed to stash overlapping source blocks\n"); goto v3out; @@ -1131,7 +1036,7 @@ static int LoadSrcTgtVersion3(CommandParameters* params, RangeSet** tgt, int* sr } if (*overlap && LoadStash(params->stashbase, srchash, 1, NULL, ¶ms->buffer, - ¶ms->bufsize, 1) == 0) { + ¶ms->bufsize, true) == 0) { // Overlapping source blocks were previously stashed, command can proceed. // We are recovering from an interrupted command, so we don't know if the // stash can safely be deleted after this command. @@ -1141,7 +1046,7 @@ static int LoadSrcTgtVersion3(CommandParameters* params, RangeSet** tgt, int* sr // Valid source data not available, update cannot be resumed fprintf(stderr, "partition has unexpected contents\n"); - params->isunresumable = 1; + params->isunresumable = true; v3out: if (tgtbuffer) { @@ -1153,7 +1058,7 @@ v3out: static int PerformCommandMove(CommandParameters* params) { int blocks = 0; - int overlap = 0; + bool overlap = false; int rc = -1; int status = 0; RangeSet* tgt = NULL; @@ -1344,7 +1249,7 @@ static int PerformCommandDiff(CommandParameters* params) { char* logparams = NULL; char* value = NULL; int blocks = 0; - int overlap = 0; + bool overlap = false; int rc = -1; int status = 0; RangeSet* tgt = NULL; @@ -1550,7 +1455,7 @@ static unsigned int HashString(const char *s) { // - patch stream (filename within package.zip, must be uncompressed) static Value* PerformBlockImageUpdate(const char* name, State* state, int argc, Expr* argv[], - const Command* commands, int cmdcount, int dryrun) { + const Command* commands, int cmdcount, bool dryrun) { char* line = NULL; char* linesave = NULL; @@ -1705,8 +1610,7 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int argc, } if (stash_max_blocks >= 0) { - res = CreateStash(state, stash_max_blocks, blockdev_filename->data, - ¶ms.stashbase); + res = CreateStash(state, stash_max_blocks, blockdev_filename->data, params.stashbase); if (res == -1) { goto pbiudone; @@ -1827,10 +1731,6 @@ pbiudone: DeleteStash(params.stashbase); } - if (params.stashbase) { - free(params.stashbase); - } - return StringValue(rc == 0 ? strdup("t") : strdup("")); } @@ -1902,7 +1802,7 @@ Value* BlockImageVerifyFn(const char* name, State* state, int argc, Expr* argv[] // Perform a dry run without writing to test if an update can proceed return PerformBlockImageUpdate(name, state, argc, argv, commands, - sizeof(commands) / sizeof(commands[0]), 1); + sizeof(commands) / sizeof(commands[0]), true); } Value* BlockImageUpdateFn(const char* name, State* state, int argc, Expr* argv[]) { @@ -1918,7 +1818,7 @@ Value* BlockImageUpdateFn(const char* name, State* state, int argc, Expr* argv[] }; return PerformBlockImageUpdate(name, state, argc, argv, commands, - sizeof(commands) / sizeof(commands[0]), 0); + sizeof(commands) / sizeof(commands[0]), false); } Value* RangeSha1Fn(const char* name, State* state, int argc, Expr* argv[]) { @@ -1979,7 +1879,7 @@ Value* RangeSha1Fn(const char* name, State* state, int argc, Expr* argv[]) { if (digest == NULL) { return StringValue(strdup("")); } else { - return StringValue(PrintSha1(digest)); + return StringValue(strdup(print_sha1(digest).c_str())); } } |