diff options
-rw-r--r-- | applypatch/Android.bp | 2 | ||||
-rw-r--r-- | applypatch/applypatch.cpp | 150 | ||||
-rw-r--r-- | otafault/Android.bp | 68 | ||||
-rw-r--r-- | otafault/config.cpp | 75 | ||||
-rw-r--r-- | otafault/include/otafault/config.h | 72 | ||||
-rw-r--r-- | otafault/include/otafault/ota_io.h | 70 | ||||
-rw-r--r-- | otafault/ota_io.cpp | 212 | ||||
-rw-r--r-- | otafault/test.cpp | 35 | ||||
-rw-r--r-- | otautil/include/otautil/error_code.h | 1 | ||||
-rw-r--r-- | tests/Android.bp | 1 | ||||
-rw-r--r-- | tests/component/updater_test.cpp | 2 | ||||
-rw-r--r-- | updater/Android.bp | 1 | ||||
-rw-r--r-- | updater/Android.mk | 1 | ||||
-rw-r--r-- | updater/blockimg.cpp | 116 | ||||
-rw-r--r-- | updater/install.cpp | 45 | ||||
-rw-r--r-- | updater/updater.cpp | 11 |
16 files changed, 112 insertions, 750 deletions
diff --git a/applypatch/Android.bp b/applypatch/Android.bp index cb0b36746..620ca6cc9 100644 --- a/applypatch/Android.bp +++ b/applypatch/Android.bp @@ -53,7 +53,6 @@ cc_library_static { "libbz", "libcrypto", "libedify", - "libotafault", "libotautil", "libz", ], @@ -100,7 +99,6 @@ cc_binary { "libapplypatch_modes", "libapplypatch", "libedify", - "libotafault", "libotautil", "libbspatch", ], diff --git a/applypatch/applypatch.cpp b/applypatch/applypatch.cpp index b1aefa49b..bc8ea79a9 100644 --- a/applypatch/applypatch.cpp +++ b/applypatch/applypatch.cpp @@ -26,24 +26,25 @@ #include <sys/types.h> #include <unistd.h> +#include <algorithm> #include <functional> #include <memory> #include <string> #include <utility> #include <vector> +#include <android-base/file.h> #include <android-base/logging.h> #include <android-base/parseint.h> #include <android-base/strings.h> +#include <android-base/unique_fd.h> #include <openssl/sha.h> #include "edify/expr.h" -#include "otafault/ota_io.h" #include "otautil/paths.h" #include "otautil/print_sha1.h" 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, const std::string& target_filename, const uint8_t target_sha1[SHA_DIGEST_LENGTH], const Value* bonus_data); @@ -54,26 +55,13 @@ int LoadFileContents(const std::string& filename, FileContents* file) { return LoadPartitionContents(filename, file); } - struct stat sb; - if (stat(filename.c_str(), &sb) == -1) { - PLOG(ERROR) << "Failed to stat \"" << filename << "\""; + std::string data; + if (!android::base::ReadFileToString(filename, &data)) { + PLOG(ERROR) << "Failed to read \"" << filename << "\""; return -1; } - std::vector<unsigned char> data(sb.st_size); - unique_file f(ota_fopen(filename.c_str(), "rb")); - if (!f) { - PLOG(ERROR) << "Failed to open \"" << filename << "\""; - return -1; - } - - size_t bytes_read = ota_fread(data.data(), 1, data.size(), f.get()); - if (bytes_read != data.size()) { - LOG(ERROR) << "Short read of \"" << filename << "\" (" << bytes_read << " bytes of " - << data.size() << ")"; - return -1; - } - file->data = std::move(data); + file->data = std::vector<unsigned char>(data.begin(), data.end()); SHA1(file->data.data(), file->data.size(), file->sha1); return 0; } @@ -110,8 +98,8 @@ static int LoadPartitionContents(const std::string& filename, FileContents* file std::sort(pairs.begin(), pairs.end()); const char* partition = pieces[1].c_str(); - unique_file dev(ota_fopen(partition, "rb")); - if (!dev) { + android::base::unique_fd dev(open(partition, O_RDONLY)); + if (dev == -1) { PLOG(ERROR) << "Failed to open eMMC partition \"" << partition << "\""; return -1; } @@ -121,8 +109,7 @@ static int LoadPartitionContents(const std::string& filename, FileContents* file // Allocate enough memory to hold the largest size. std::vector<unsigned char> buffer(pairs[pair_count - 1].first); - unsigned char* buffer_ptr = buffer.data(); - size_t buffer_size = 0; // # bytes read so far + size_t offset = 0; // # bytes read so far bool found = false; for (const auto& pair : pairs) { @@ -131,19 +118,16 @@ static int LoadPartitionContents(const std::string& filename, FileContents* file // Read enough additional bytes to get us up to the next size. (Again, // we're trying the possibilities in order of increasing size). - size_t next = current_size - buffer_size; - if (next > 0) { - size_t read = ota_fread(buffer_ptr, 1, next, dev.get()); - if (next != read) { - LOG(ERROR) << "Short read (" << read << " bytes of " << next << ") for partition \"" - << partition << "\""; + if (current_size - offset > 0) { + if (!android::base::ReadFully(dev, buffer.data() + offset, current_size - offset)) { + PLOG(ERROR) << "Failed to read " << current_size - offset << " bytes of data at offset " + << offset << " for partition " << partition; return -1; } - SHA1_Update(&sha_ctx, buffer_ptr, read); - buffer_size += read; - buffer_ptr += read; - } + SHA1_Update(&sha_ctx, buffer.data() + offset, current_size - offset); + offset = current_size; + } // Duplicate the SHA context and finalize the duplicate so we can // check it against this pair's expected hash. SHA_CTX temp_ctx; @@ -173,31 +157,31 @@ static int LoadPartitionContents(const std::string& filename, FileContents* file SHA1_Final(file->sha1, &sha_ctx); - buffer.resize(buffer_size); + buffer.resize(offset); file->data = std::move(buffer); return 0; } int SaveFileContents(const std::string& filename, const FileContents* file) { - unique_fd fd( - ota_open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, S_IRUSR | S_IWUSR)); + android::base::unique_fd fd( + open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, S_IRUSR | S_IWUSR)); if (fd == -1) { PLOG(ERROR) << "Failed to open \"" << filename << "\" for write"; return -1; } - size_t bytes_written = FileSink(file->data.data(), file->data.size(), fd); - if (bytes_written != file->data.size()) { - PLOG(ERROR) << "Short write of \"" << filename << "\" (" << bytes_written << " bytes of " - << file->data.size(); + if (!android::base::WriteFully(fd, file->data.data(), file->data.size())) { + PLOG(ERROR) << "Failed to write " << file->data.size() << " bytes of data to " << filename; return -1; } - if (ota_fsync(fd) != 0) { + + if (fsync(fd) != 0) { PLOG(ERROR) << "Failed to fsync \"" << filename << "\""; return -1; } - if (ota_close(fd) != 0) { + + if (close(fd.release()) != 0) { PLOG(ERROR) << "Failed to close \"" << filename << "\""; return -1; } @@ -215,42 +199,36 @@ static int WriteToPartition(const unsigned char* data, size_t len, const std::st return -1; } - const char* partition = pieces[1].c_str(); - unique_fd fd(ota_open(partition, O_RDWR)); - if (fd == -1) { - PLOG(ERROR) << "Failed to open \"" << partition << "\""; - return -1; - } - size_t start = 0; bool success = false; for (size_t attempt = 0; attempt < 2; ++attempt) { + std::string partition = pieces[1]; + android::base::unique_fd fd(open(partition.c_str(), O_RDWR)); + if (fd == -1) { + PLOG(ERROR) << "Failed to open \"" << partition << "\""; + return -1; + } + if (TEMP_FAILURE_RETRY(lseek(fd, start, SEEK_SET)) == -1) { PLOG(ERROR) << "Failed to seek to " << start << " on \"" << partition << "\""; return -1; } - while (start < len) { - size_t to_write = len - start; - if (to_write > 1 << 20) to_write = 1 << 20; - ssize_t written = TEMP_FAILURE_RETRY(ota_write(fd, data + start, to_write)); - if (written == -1) { - PLOG(ERROR) << "Failed to write to \"" << partition << "\""; - return -1; - } - start += written; + if (!android::base::WriteFully(fd, data + start, len - start)) { + PLOG(ERROR) << "Failed to write " << len - start << " bytes to \"" << partition << "\""; + return -1; } - if (ota_fsync(fd) != 0) { + if (fsync(fd) != 0) { PLOG(ERROR) << "Failed to sync \"" << partition << "\""; return -1; } - if (ota_close(fd) != 0) { + if (close(fd.release()) != 0) { PLOG(ERROR) << "Failed to close \"" << partition << "\""; return -1; } - fd.reset(ota_open(partition, O_RDONLY)); + fd.reset(open(partition.c_str(), O_RDONLY)); if (fd == -1) { PLOG(ERROR) << "Failed to reopen \"" << partition << "\" for verification"; return -1; @@ -258,13 +236,12 @@ static int WriteToPartition(const unsigned char* data, size_t len, const std::st // Drop caches so our subsequent verification read won't just be reading the cache. sync(); - unique_fd dc(ota_open("/proc/sys/vm/drop_caches", O_WRONLY)); - if (TEMP_FAILURE_RETRY(ota_write(dc, "3\n", 2)) == -1) { - PLOG(ERROR) << "Failed to write to /proc/sys/vm/drop_caches"; + std::string drop_cache = "/proc/sys/vm/drop_caches"; + if (!android::base::WriteStringToFile("3\n", drop_cache)) { + PLOG(ERROR) << "Failed to write to " << drop_cache; } else { LOG(INFO) << " caches dropped"; } - ota_close(dc); sleep(1); // Verify. @@ -281,21 +258,9 @@ static int WriteToPartition(const unsigned char* data, size_t len, const std::st to_read = sizeof(buffer); } - size_t so_far = 0; - while (so_far < to_read) { - ssize_t read_count = TEMP_FAILURE_RETRY(ota_read(fd, buffer + so_far, to_read - so_far)); - if (read_count == -1) { - PLOG(ERROR) << "Failed to verify-read " << partition << " at " << p; - return -1; - } else if (read_count == 0) { - LOG(ERROR) << "Verify-reading " << partition << " reached unexpected EOF at " << p; - return -1; - } - if (static_cast<size_t>(read_count) < to_read) { - LOG(INFO) << "Short verify-read " << partition << " at " << p << ": expected " << to_read - << " actual " << read_count; - } - so_far += read_count; + if (!android::base::ReadFully(fd, buffer, to_read)) { + PLOG(ERROR) << "Failed to verify-read " << partition << " at " << p; + return -1; } if (memcmp(buffer, data + p, to_read) != 0) { @@ -311,16 +276,10 @@ static int WriteToPartition(const unsigned char* data, size_t len, const std::st break; } - if (ota_close(fd) != 0) { + if (close(fd.release()) != 0) { PLOG(ERROR) << "Failed to close " << partition; return -1; } - - fd.reset(ota_open(partition, O_RDWR)); - if (fd == -1) { - PLOG(ERROR) << "Failed to reopen " << partition << " for next attempt"; - return -1; - } } if (!success) { @@ -328,10 +287,6 @@ static int WriteToPartition(const unsigned char* data, size_t len, const std::st return -1; } - if (ota_close(fd) == -1) { - PLOG(ERROR) << "Failed to close " << partition; - return -1; - } sync(); return 0; @@ -407,19 +362,6 @@ int ShowLicenses() { return 0; } -static size_t FileSink(const unsigned char* data, size_t len, int fd) { - size_t done = 0; - while (done < len) { - ssize_t wrote = TEMP_FAILURE_RETRY(ota_write(fd, data + done, len - done)); - if (wrote == -1) { - PLOG(ERROR) << "Failed to write " << len - done << " bytes"; - return done; - } - done += wrote; - } - return done; -} - int applypatch(const char* source_filename, const char* target_filename, const char* target_sha1_str, size_t /* target_size */, const std::vector<std::string>& patch_sha1s, diff --git a/otafault/Android.bp b/otafault/Android.bp deleted file mode 100644 index b39d5bee2..000000000 --- a/otafault/Android.bp +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (C) 2017 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. - -cc_library_static { - name: "libotafault", - - host_supported: true, - - srcs: [ - "config.cpp", - "ota_io.cpp", - ], - - static_libs: [ - "libbase", - "liblog", - "libziparchive", - ], - - export_include_dirs: [ - "include", - ], - - cflags: [ - "-D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS", - "-Wall", - "-Werror", - "-Wthread-safety", - "-Wthread-safety-negative", - ], - - target: { - darwin: { - enabled: false, - }, - }, -} - -cc_test { - name: "otafault_test", - - srcs: ["test.cpp"], - - cflags: [ - "-Wall", - "-Werror", - ], - - static_executable: true, - - static_libs: [ - "libotafault", - "libziparchive", - "libbase", - "liblog", - ], -} diff --git a/otafault/config.cpp b/otafault/config.cpp deleted file mode 100644 index 3993948ff..000000000 --- a/otafault/config.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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. - */ - -#include "otafault/config.h" - -#include <map> -#include <string> - -#include <android-base/stringprintf.h> -#include <ziparchive/zip_archive.h> - -#include "otafault/ota_io.h" - -#define OTAIO_MAX_FNAME_SIZE 128 - -static ZipArchiveHandle archive; -static bool is_retry = false; -static std::map<std::string, bool> should_inject_cache; - -static std::string get_type_path(const char* io_type) { - return android::base::StringPrintf("%s/%s", OTAIO_BASE_DIR, io_type); -} - -void ota_io_init(ZipArchiveHandle za, bool retry) { - archive = za; - is_retry = retry; - ota_set_fault_files(); -} - -bool should_fault_inject(const char* io_type) { - // archive will be NULL if we used an entry point other - // than updater/updater.cpp:main - if (archive == nullptr || is_retry) { - return false; - } - const std::string type_path = get_type_path(io_type); - if (should_inject_cache.find(type_path) != should_inject_cache.end()) { - return should_inject_cache[type_path]; - } - ZipString zip_type_path(type_path.c_str()); - ZipEntry entry; - int status = FindEntry(archive, zip_type_path, &entry); - should_inject_cache[type_path] = (status == 0); - return (status == 0); -} - -bool should_hit_cache() { - return should_fault_inject(OTAIO_CACHE); -} - -std::string fault_fname(const char* io_type) { - std::string type_path = get_type_path(io_type); - std::string fname; - fname.resize(OTAIO_MAX_FNAME_SIZE); - ZipString zip_type_path(type_path.c_str()); - ZipEntry entry; - if (FindEntry(archive, zip_type_path, &entry) != 0) { - return {}; - } - ExtractToMemory(archive, &entry, reinterpret_cast<uint8_t*>(&fname[0]), OTAIO_MAX_FNAME_SIZE); - return fname; -} diff --git a/otafault/include/otafault/config.h b/otafault/include/otafault/config.h deleted file mode 100644 index cc4bfd2ad..000000000 --- a/otafault/include/otafault/config.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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. - */ - -/* - * Read configuration files in the OTA package to determine which files, if any, will trigger - * errors. - * - * OTA packages can be modified to trigger errors by adding a top-level directory called - * .libotafault, which may optionally contain up to three files called READ, WRITE, and FSYNC. - * Each one of these optional files contains the name of a single file on the device disk which - * will cause an IO error on the first call of the appropriate I/O action to that file. - * - * Example: - * ota.zip - * <normal package contents> - * .libotafault - * WRITE - * - * If the contents of the file WRITE were /system/build.prop, the first write action to - * /system/build.prop would fail with EIO. Note that READ and FSYNC files are absent, so these - * actions will not cause an error. - */ - -#ifndef _UPDATER_OTA_IO_CFG_H_ -#define _UPDATER_OTA_IO_CFG_H_ - -#include <string> - -#include <ziparchive/zip_archive.h> - -#define OTAIO_BASE_DIR ".libotafault" -#define OTAIO_READ "READ" -#define OTAIO_WRITE "WRITE" -#define OTAIO_FSYNC "FSYNC" -#define OTAIO_CACHE "CACHE" - -/* - * Initialize libotafault by providing a reference to the OTA package. - */ -void ota_io_init(ZipArchiveHandle zip, bool retry); - -/* - * Return true if a config file is present for the given IO type. - */ -bool should_fault_inject(const char* io_type); - -/* - * Return true if an EIO should occur on the next hit to /cache/saved.file - * instead of the next hit to the specified file. - */ -bool should_hit_cache(); - -/* - * Return the name of the file that should cause an error for the - * given IO type. - */ -std::string fault_fname(const char* io_type); - -#endif diff --git a/otafault/include/otafault/ota_io.h b/otafault/include/otafault/ota_io.h deleted file mode 100644 index 45e481a62..000000000 --- a/otafault/include/otafault/ota_io.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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. - */ - -/* - * Provide a series of proxy functions for basic file accessors. - * The behavior of these functions can be changed to return different - * errors under a variety of conditions. - */ - -#ifndef _UPDATER_OTA_IO_H_ -#define _UPDATER_OTA_IO_H_ - -#include <stddef.h> -#include <stdio.h> -#include <sys/stat.h> // mode_t - -#include <memory> - -#include <android-base/unique_fd.h> - -#define OTAIO_CACHE_FNAME "/cache/saved.file" - -void ota_set_fault_files(); - -int ota_open(const char* path, int oflags); - -int ota_open(const char* path, int oflags, mode_t mode); - -FILE* ota_fopen(const char* filename, const char* mode); - -size_t ota_fread(void* ptr, size_t size, size_t nitems, FILE* stream); - -ssize_t ota_read(int fd, void* buf, size_t nbyte); - -size_t ota_fwrite(const void* ptr, size_t size, size_t count, FILE* stream); - -ssize_t ota_write(int fd, const void* buf, size_t nbyte); - -int ota_fsync(int fd); - -struct OtaCloser { - static void Close(int); -}; - -using unique_fd = android::base::unique_fd_impl<OtaCloser>; - -int ota_close(unique_fd& fd); - -struct OtaFcloser { - void operator()(FILE*) const; -}; - -using unique_file = std::unique_ptr<FILE, OtaFcloser>; - -int ota_fclose(unique_file& fh); - -#endif diff --git a/otafault/ota_io.cpp b/otafault/ota_io.cpp deleted file mode 100644 index 63ef18e26..000000000 --- a/otafault/ota_io.cpp +++ /dev/null @@ -1,212 +0,0 @@ -/* - * 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. - */ - -#include "otafault/ota_io.h" - -#include <errno.h> -#include <fcntl.h> -#include <stdint.h> -#include <stdio.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> - -#include <map> -#include <mutex> -#include <string> - -#include <android-base/thread_annotations.h> - -#include "otafault/config.h" - -static std::mutex filename_mutex; -static std::map<intptr_t, const char*> filename_cache GUARDED_BY(filename_mutex); -static std::string read_fault_file_name = ""; -static std::string write_fault_file_name = ""; -static std::string fsync_fault_file_name = ""; - -static bool get_hit_file(const char* cached_path, const std::string& ffn) { - return should_hit_cache() - ? !strncmp(cached_path, OTAIO_CACHE_FNAME, strlen(cached_path)) - : !strncmp(cached_path, ffn.c_str(), strlen(cached_path)); -} - -void ota_set_fault_files() { - if (should_fault_inject(OTAIO_READ)) { - read_fault_file_name = fault_fname(OTAIO_READ); - } - if (should_fault_inject(OTAIO_WRITE)) { - write_fault_file_name = fault_fname(OTAIO_WRITE); - } - if (should_fault_inject(OTAIO_FSYNC)) { - fsync_fault_file_name = fault_fname(OTAIO_FSYNC); - } -} - -bool have_eio_error = false; - -int ota_open(const char* path, int oflags) { - // Let the caller handle errors; we do not care if open succeeds or fails - int fd = open(path, oflags); - std::lock_guard<std::mutex> lock(filename_mutex); - filename_cache[fd] = path; - return fd; -} - -int ota_open(const char* path, int oflags, mode_t mode) { - int fd = open(path, oflags, mode); - std::lock_guard<std::mutex> lock(filename_mutex); - filename_cache[fd] = path; - return fd; -} - -FILE* ota_fopen(const char* path, const char* mode) { - FILE* fh = fopen(path, mode); - std::lock_guard<std::mutex> lock(filename_mutex); - filename_cache[(intptr_t)fh] = path; - return fh; -} - -static int __ota_close(int fd) { - // descriptors can be reused, so make sure not to leave them in the cache - std::lock_guard<std::mutex> lock(filename_mutex); - filename_cache.erase(fd); - return close(fd); -} - -void OtaCloser::Close(int fd) { - __ota_close(fd); -} - -int ota_close(unique_fd& fd) { - return __ota_close(fd.release()); -} - -static int __ota_fclose(FILE* fh) { - std::lock_guard<std::mutex> lock(filename_mutex); - filename_cache.erase(reinterpret_cast<intptr_t>(fh)); - return fclose(fh); -} - -void OtaFcloser::operator()(FILE* f) const { - __ota_fclose(f); -}; - -int ota_fclose(unique_file& fh) { - return __ota_fclose(fh.release()); -} - -size_t ota_fread(void* ptr, size_t size, size_t nitems, FILE* stream) { - if (should_fault_inject(OTAIO_READ)) { - std::lock_guard<std::mutex> lock(filename_mutex); - auto cached = filename_cache.find((intptr_t)stream); - const char* cached_path = cached->second; - if (cached != filename_cache.end() && - get_hit_file(cached_path, read_fault_file_name)) { - read_fault_file_name = ""; - errno = EIO; - have_eio_error = true; - return 0; - } - } - size_t status = fread(ptr, size, nitems, stream); - // If I/O error occurs, set the retry-update flag. - if (status != nitems && errno == EIO) { - have_eio_error = true; - } - return status; -} - -ssize_t ota_read(int fd, void* buf, size_t nbyte) { - if (should_fault_inject(OTAIO_READ)) { - std::lock_guard<std::mutex> lock(filename_mutex); - auto cached = filename_cache.find(fd); - const char* cached_path = cached->second; - if (cached != filename_cache.end() - && get_hit_file(cached_path, read_fault_file_name)) { - read_fault_file_name = ""; - errno = EIO; - have_eio_error = true; - return -1; - } - } - ssize_t status = read(fd, buf, nbyte); - if (status == -1 && errno == EIO) { - have_eio_error = true; - } - return status; -} - -size_t ota_fwrite(const void* ptr, size_t size, size_t count, FILE* stream) { - if (should_fault_inject(OTAIO_WRITE)) { - std::lock_guard<std::mutex> lock(filename_mutex); - auto cached = filename_cache.find((intptr_t)stream); - const char* cached_path = cached->second; - if (cached != filename_cache.end() && - get_hit_file(cached_path, write_fault_file_name)) { - write_fault_file_name = ""; - errno = EIO; - have_eio_error = true; - return 0; - } - } - size_t status = fwrite(ptr, size, count, stream); - if (status != count && errno == EIO) { - have_eio_error = true; - } - return status; -} - -ssize_t ota_write(int fd, const void* buf, size_t nbyte) { - if (should_fault_inject(OTAIO_WRITE)) { - std::lock_guard<std::mutex> lock(filename_mutex); - auto cached = filename_cache.find(fd); - const char* cached_path = cached->second; - if (cached != filename_cache.end() && - get_hit_file(cached_path, write_fault_file_name)) { - write_fault_file_name = ""; - errno = EIO; - have_eio_error = true; - return -1; - } - } - ssize_t status = write(fd, buf, nbyte); - if (status == -1 && errno == EIO) { - have_eio_error = true; - } - return status; -} - -int ota_fsync(int fd) { - if (should_fault_inject(OTAIO_FSYNC)) { - std::lock_guard<std::mutex> lock(filename_mutex); - auto cached = filename_cache.find(fd); - const char* cached_path = cached->second; - if (cached != filename_cache.end() && - get_hit_file(cached_path, fsync_fault_file_name)) { - fsync_fault_file_name = ""; - errno = EIO; - have_eio_error = true; - return -1; - } - } - int status = fsync(fd); - if (status == -1 && errno == EIO) { - have_eio_error = true; - } - return status; -} - diff --git a/otafault/test.cpp b/otafault/test.cpp deleted file mode 100644 index 63e2445af..000000000 --- a/otafault/test.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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. - */ - -#include <fcntl.h> -#include <stdio.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> - -#include "otafault/ota_io.h" - -int main(int /* argc */, char** /* argv */) { - int fd = open("testdata/test.file", O_RDWR); - char buf[8]; - const char* out = "321"; - int readv = ota_read(fd, buf, 4); - printf("Read returned %d\n", readv); - int writev = ota_write(fd, out, 4); - printf("Write returned %d\n", writev); - close(fd); - return 0; -} diff --git a/otautil/include/otautil/error_code.h b/otautil/include/otautil/error_code.h index 0f6c9f85f..2b73c1353 100644 --- a/otautil/include/otautil/error_code.h +++ b/otautil/include/otautil/error_code.h @@ -49,6 +49,7 @@ enum CauseCode : int { kPackageExtractFileFailure, kPatchApplicationFailure, kHashTreeComputationFailure, + kEioFailure, kVendorFailure = 200 }; diff --git a/tests/Android.bp b/tests/Android.bp index dc20f3326..ab4d31da2 100644 --- a/tests/Android.bp +++ b/tests/Android.bp @@ -56,7 +56,6 @@ libapplypatch_static_libs = [ "libedify", "libimgdiff", "libimgpatch", - "libotafault", "libotautil", "libbsdiff", "libbspatch", diff --git a/tests/component/updater_test.cpp b/tests/component/updater_test.cpp index c4f3176f9..b253abccf 100644 --- a/tests/component/updater_test.cpp +++ b/tests/component/updater_test.cpp @@ -272,7 +272,7 @@ TEST_F(UpdaterTest, file_getprop) { expect(nullptr, "file_getprop(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure); // File doesn't exist. - expect(nullptr, "file_getprop(\"/doesntexist\", \"key1\")", kFileGetPropFailure); + expect(nullptr, "file_getprop(\"/doesntexist\", \"key1\")", kFreadFailure); // Reject too large files (current limit = 65536). TemporaryFile temp_file1; diff --git a/updater/Android.bp b/updater/Android.bp index c77bac8fb..c95ec5e90 100644 --- a/updater/Android.bp +++ b/updater/Android.bp @@ -24,7 +24,6 @@ cc_defaults { "libbootloader_message", "libbspatch", "libedify", - "libotafault", "libotautil", "libext4_utils", "libfec", diff --git a/updater/Android.mk b/updater/Android.mk index 5478a7df6..78e32ba39 100644 --- a/updater/Android.mk +++ b/updater/Android.mk @@ -27,7 +27,6 @@ updater_common_static_libraries := \ libbootloader_message \ libbspatch \ libedify \ - libotafault \ libotautil \ libext4_utils \ libfec \ diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp index 96b2d9feb..823a1cbbd 100644 --- a/updater/blockimg.cpp +++ b/updater/blockimg.cpp @@ -53,7 +53,6 @@ #include <ziparchive/zip_archive.h> #include "edify/expr.h" -#include "otafault/ota_io.h" #include "otautil/error_code.h" #include "otautil/paths.h" #include "otautil/print_sha1.h" @@ -119,15 +118,14 @@ static bool ParseLastCommandFile(size_t* last_command_index) { } static bool FsyncDir(const std::string& dirname) { - android::base::unique_fd dfd( - TEMP_FAILURE_RETRY(ota_open(dirname.c_str(), O_RDONLY | O_DIRECTORY))); + android::base::unique_fd dfd(TEMP_FAILURE_RETRY(open(dirname.c_str(), O_RDONLY | O_DIRECTORY))); if (dfd == -1) { - failure_type = kFileOpenFailure; + failure_type = errno == EIO ? kEioFailure : kFileOpenFailure; PLOG(ERROR) << "Failed to open " << dirname; return false; } if (fsync(dfd) == -1) { - failure_type = kFsyncFailure; + failure_type = errno == EIO ? kEioFailure : kFsyncFailure; PLOG(ERROR) << "Failed to fsync " << dirname; return false; } @@ -180,47 +178,6 @@ static bool SetPartitionUpdatedMarker(const std::string& marker) { return true; } -static int read_all(int fd, uint8_t* data, size_t size) { - size_t so_far = 0; - while (so_far < size) { - ssize_t r = TEMP_FAILURE_RETRY(ota_read(fd, data+so_far, size-so_far)); - if (r == -1) { - failure_type = kFreadFailure; - PLOG(ERROR) << "read failed"; - return -1; - } else if (r == 0) { - failure_type = kFreadFailure; - LOG(ERROR) << "read reached unexpected EOF."; - return -1; - } - so_far += r; - } - return 0; -} - -static int read_all(int fd, std::vector<uint8_t>* buffer, size_t size) { - return read_all(fd, buffer->data(), size); -} - -static int write_all(int fd, const uint8_t* data, size_t size) { - size_t written = 0; - while (written < size) { - ssize_t w = TEMP_FAILURE_RETRY(ota_write(fd, data+written, size-written)); - if (w == -1) { - failure_type = kFwriteFailure; - PLOG(ERROR) << "write failed"; - return -1; - } - written += w; - } - - return 0; -} - -static int write_all(int fd, const std::vector<uint8_t>& buffer, size_t size) { - return write_all(fd, buffer.data(), size); -} - static bool discard_blocks(int fd, off64_t offset, uint64_t size) { // Don't discard blocks unless the update is a retry run. if (!is_retry) { @@ -293,7 +250,9 @@ class RangeSinkWriter { write_now = current_range_left_; } - if (write_all(fd_, data, write_now) == -1) { + if (!android::base::WriteFully(fd_, data, write_now)) { + failure_type = errno == EIO ? kEioFailure : kFwriteFailure; + PLOG(ERROR) << "Failed to write " << write_now << " bytes of data"; break; } @@ -510,7 +469,9 @@ static int ReadBlocks(const RangeSet& src, std::vector<uint8_t>* buffer, int fd) } size_t size = (range.second - range.first) * BLOCKSIZE; - if (read_all(fd, buffer->data() + p, size) == -1) { + if (!android::base::ReadFully(fd, buffer->data() + p, size)) { + failure_type = errno == EIO ? kEioFailure : kFreadFailure; + PLOG(ERROR) << "Failed to read " << size << " bytes of data"; return -1; } @@ -533,7 +494,9 @@ static int WriteBlocks(const RangeSet& tgt, const std::vector<uint8_t>& buffer, return -1; } - if (write_all(fd, buffer.data() + written, size) == -1) { + if (!android::base::WriteFully(fd, buffer.data() + written, size)) { + failure_type = errno == EIO ? kEioFailure : kFwriteFailure; + PLOG(ERROR) << "Failed to write " << size << " bytes of data"; return -1; } @@ -793,15 +756,18 @@ static int LoadStash(const CommandParameters& params, const std::string& id, boo return -1; } - android::base::unique_fd fd(TEMP_FAILURE_RETRY(ota_open(fn.c_str(), O_RDONLY))); + android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(fn.c_str(), O_RDONLY))); if (fd == -1) { + failure_type = errno == EIO ? kEioFailure : kFileOpenFailure; PLOG(ERROR) << "open \"" << fn << "\" failed"; return -1; } allocate(sb.st_size, buffer); - if (read_all(fd, buffer, sb.st_size) == -1) { + if (!android::base::ReadFully(fd, buffer->data(), sb.st_size)) { + failure_type = errno == EIO ? kEioFailure : kFreadFailure; + PLOG(ERROR) << "Failed to read " << sb.st_size << " bytes of data"; return -1; } @@ -855,8 +821,9 @@ static int WriteStash(const std::string& base, const std::string& id, int blocks LOG(INFO) << " writing " << blocks << " blocks to " << cn; android::base::unique_fd fd( - TEMP_FAILURE_RETRY(ota_open(fn.c_str(), O_WRONLY | O_CREAT | O_TRUNC, STASH_FILE_MODE))); + TEMP_FAILURE_RETRY(open(fn.c_str(), O_WRONLY | O_CREAT | O_TRUNC, STASH_FILE_MODE))); if (fd == -1) { + failure_type = errno == EIO ? kEioFailure : kFileOpenFailure; PLOG(ERROR) << "failed to create \"" << fn << "\""; return -1; } @@ -866,12 +833,14 @@ static int WriteStash(const std::string& base, const std::string& id, int blocks return -1; } - if (write_all(fd, buffer, blocks * BLOCKSIZE) == -1) { + if (!android::base::WriteFully(fd, buffer.data(), blocks * BLOCKSIZE)) { + failure_type = errno == EIO ? kEioFailure : kFwriteFailure; + PLOG(ERROR) << "Failed to write " << blocks * BLOCKSIZE << " bytes of data"; return -1; } - if (ota_fsync(fd) == -1) { - failure_type = kFsyncFailure; + if (fsync(fd) == -1) { + failure_type = errno == EIO ? kEioFailure : kFsyncFailure; PLOG(ERROR) << "fsync \"" << fn << "\" failed"; return -1; } @@ -883,7 +852,6 @@ static int WriteStash(const std::string& base, const std::string& id, int blocks std::string dname = GetStashFileName(base, "", ""); if (!FsyncDir(dname)) { - failure_type = kFsyncFailure; return -1; } @@ -1313,7 +1281,9 @@ static int PerformCommandZero(CommandParameters& params) { } for (size_t j = range.first; j < range.second; ++j) { - if (write_all(params.fd, params.buffer, BLOCKSIZE) == -1) { + if (!android::base::WriteFully(params.fd, params.buffer.data(), BLOCKSIZE)) { + failure_type = errno == EIO ? kEioFailure : kFwriteFailure; + PLOG(ERROR) << "Failed to write " << BLOCKSIZE << " bytes of data"; return -1; } } @@ -1560,7 +1530,8 @@ static int PerformCommandComputeHashTree(CommandParameters& params) { } for (size_t i = range.first; i < range.second; i++) { - if (read_all(params.fd, buffer, BLOCKSIZE) == -1) { + if (!android::base::ReadFully(params.fd, buffer, BLOCKSIZE)) { + failure_type = errno == EIO ? kEioFailure : kFreadFailure; LOG(ERROR) << "Failed to read data in " << range.first << ":" << range.second; return -1; } @@ -1676,8 +1647,9 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, return StringValue(""); } - params.fd.reset(TEMP_FAILURE_RETRY(ota_open(blockdev_filename->data.c_str(), O_RDWR))); + params.fd.reset(TEMP_FAILURE_RETRY(open(blockdev_filename->data.c_str(), O_RDWR))); if (params.fd == -1) { + failure_type = errno == EIO ? kEioFailure : kFileOpenFailure; PLOG(ERROR) << "open \"" << blockdev_filename->data << "\" failed"; return StringValue(""); } @@ -1859,8 +1831,8 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, } if (params.canwrite) { - if (ota_fsync(params.fd) == -1) { - failure_type = kFsyncFailure; + if (fsync(params.fd) == -1) { + failure_type = errno == EIO ? kEioFailure : kFsyncFailure; PLOG(ERROR) << "fsync failed"; goto pbiudone; } @@ -1920,8 +1892,8 @@ pbiudone: LOG(INFO) << "verified partition contents; update may be resumed"; } - if (ota_fsync(params.fd) == -1) { - failure_type = kFsyncFailure; + if (fsync(params.fd) == -1) { + failure_type = errno == EIO ? kEioFailure : kFsyncFailure; PLOG(ERROR) << "fsync failed"; } // params.fd will be automatically closed because it's a unique_fd. @@ -2059,9 +2031,10 @@ Value* RangeSha1Fn(const char* name, State* state, const std::vector<std::unique return StringValue(""); } - android::base::unique_fd fd(ota_open(blockdev_filename->data.c_str(), O_RDWR)); + android::base::unique_fd fd(open(blockdev_filename->data.c_str(), O_RDWR)); if (fd == -1) { - ErrorAbort(state, kFileOpenFailure, "open \"%s\" failed: %s", blockdev_filename->data.c_str(), + CauseCode cause_code = errno == EIO ? kEioFailure : kFileOpenFailure; + ErrorAbort(state, cause_code, "open \"%s\" failed: %s", blockdev_filename->data.c_str(), strerror(errno)); return StringValue(""); } @@ -2081,8 +2054,9 @@ Value* RangeSha1Fn(const char* name, State* state, const std::vector<std::unique } for (size_t j = range.first; j < range.second; ++j) { - if (read_all(fd, &buffer, BLOCKSIZE) == -1) { - ErrorAbort(state, kFreadFailure, "failed to read %s: %s", blockdev_filename->data.c_str(), + if (!android::base::ReadFully(fd, buffer.data(), BLOCKSIZE)) { + CauseCode cause_code = errno == EIO ? kEioFailure : kFreadFailure; + ErrorAbort(state, cause_code, "failed to read %s: %s", blockdev_filename->data.c_str(), strerror(errno)); return StringValue(""); } @@ -2121,9 +2095,10 @@ Value* CheckFirstBlockFn(const char* name, State* state, return StringValue(""); } - android::base::unique_fd fd(ota_open(arg_filename->data.c_str(), O_RDONLY)); + android::base::unique_fd fd(open(arg_filename->data.c_str(), O_RDONLY)); if (fd == -1) { - ErrorAbort(state, kFileOpenFailure, "open \"%s\" failed: %s", arg_filename->data.c_str(), + CauseCode cause_code = errno == EIO ? kEioFailure : kFileOpenFailure; + ErrorAbort(state, cause_code, "open \"%s\" failed: %s", arg_filename->data.c_str(), strerror(errno)); return StringValue(""); } @@ -2132,7 +2107,8 @@ Value* CheckFirstBlockFn(const char* name, State* state, std::vector<uint8_t> block0_buffer(BLOCKSIZE); if (ReadBlocks(blk0, &block0_buffer, fd) == -1) { - ErrorAbort(state, kFreadFailure, "failed to read %s: %s", arg_filename->data.c_str(), + CauseCode cause_code = errno == EIO ? kEioFailure : kFreadFailure; + ErrorAbort(state, cause_code, "failed to read %s: %s", arg_filename->data.c_str(), strerror(errno)); return StringValue(""); } diff --git a/updater/install.cpp b/updater/install.cpp index f9333459b..34514b65a 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -46,6 +46,7 @@ #include <android-base/properties.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> +#include <android-base/unique_fd.h> #include <applypatch/applypatch.h> #include <bootloader_message/bootloader_message.h> #include <ext4_utils/wipe.h> @@ -56,7 +57,6 @@ #include <ziparchive/zip_archive.h> #include "edify/expr.h" -#include "otafault/ota_io.h" #include "otautil/dirutil.h" #include "otautil/error_code.h" #include "otautil/mounts.h" @@ -137,8 +137,8 @@ Value* PackageExtractFileFn(const char* name, State* state, return StringValue(""); } - unique_fd fd(TEMP_FAILURE_RETRY( - ota_open(dest_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR))); + android::base::unique_fd fd(TEMP_FAILURE_RETRY( + open(dest_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR))); if (fd == -1) { PLOG(ERROR) << name << ": can't open " << dest_path << " for write"; return StringValue(""); @@ -152,11 +152,12 @@ Value* PackageExtractFileFn(const char* name, State* state, << "\": " << ErrorCodeString(ret); success = false; } - if (ota_fsync(fd) == -1) { + if (fsync(fd) == -1) { PLOG(ERROR) << "fsync of \"" << dest_path << "\" failed"; success = false; } - if (ota_close(fd) == -1) { + + if (close(fd.release()) != 0) { PLOG(ERROR) << "close of \"" << dest_path << "\" failed"; success = false; } @@ -614,33 +615,12 @@ Value* FileGetPropFn(const char* name, State* state, const std::string& filename = args[0]; const std::string& key = args[1]; - struct stat st; - if (stat(filename.c_str(), &st) < 0) { - return ErrorAbort(state, kFileGetPropFailure, "%s: failed to stat \"%s\": %s", name, - filename.c_str(), strerror(errno)); - } - - constexpr off_t MAX_FILE_GETPROP_SIZE = 65536; - if (st.st_size > MAX_FILE_GETPROP_SIZE) { - return ErrorAbort(state, kFileGetPropFailure, "%s too large for %s (max %lld)", - filename.c_str(), name, static_cast<long long>(MAX_FILE_GETPROP_SIZE)); - } - - std::string buffer(st.st_size, '\0'); - unique_file f(ota_fopen(filename.c_str(), "rb")); - if (f == nullptr) { - return ErrorAbort(state, kFileOpenFailure, "%s: failed to open %s: %s", name, filename.c_str(), - strerror(errno)); - } - - if (ota_fread(&buffer[0], 1, st.st_size, f.get()) != static_cast<size_t>(st.st_size)) { - ErrorAbort(state, kFreadFailure, "%s: failed to read %zu bytes from %s", name, - static_cast<size_t>(st.st_size), filename.c_str()); + std::string buffer; + if (!android::base::ReadFileToString(filename, &buffer)) { + ErrorAbort(state, kFreadFailure, "%s: failed to read %s", name, filename.c_str()); return nullptr; } - ota_fclose(f); - std::vector<std::string> lines = android::base::Split(buffer, "\n"); for (size_t i = 0; i < lines.size(); i++) { std::string line = android::base::Trim(lines[i]); @@ -913,7 +893,12 @@ Value* WipeBlockDeviceFn(const char* name, State* state, const std::vector<std:: if (!android::base::ParseUint(len_str.c_str(), &len)) { return nullptr; } - unique_fd fd(ota_open(filename.c_str(), O_WRONLY, 0644)); + android::base::unique_fd fd(open(filename.c_str(), O_WRONLY)); + if (fd == -1) { + PLOG(ERROR) << "Failed to open " << filename; + return StringValue(""); + } + // The wipe_block_device function in ext4_utils returns 0 on success and 1 // for failure. int status = wipe_block_device(fd, len); diff --git a/updater/updater.cpp b/updater/updater.cpp index e06d45355..e87c57a5c 100644 --- a/updater/updater.cpp +++ b/updater/updater.cpp @@ -31,7 +31,6 @@ #include <ziparchive/zip_archive.h> #include "edify/expr.h" -#include "otafault/config.h" #include "otautil/dirutil.h" #include "otautil/error_code.h" #include "otautil/sysutil.h" @@ -47,8 +46,6 @@ // (Note it's "updateR-script", not the older "update-script".) static constexpr const char* SCRIPT_NAME = "META-INF/com/google/android/updater-script"; -extern bool have_eio_error; - struct selabel_handle *sehandle; static void UpdaterLogger(android::base::LogId /* id */, android::base::LogSeverity /* severity */, @@ -166,15 +163,10 @@ int main(int argc, char** argv) { printf("unexpected argument: %s", argv[4]); } } - ota_io_init(za, state.is_retry); std::string result; bool status = Evaluate(&state, root, &result); - if (have_eio_error) { - fprintf(cmd_pipe, "retry_update\n"); - } - if (!status) { if (state.errmsg.empty()) { LOG(ERROR) << "script aborted (no error message)"; @@ -206,6 +198,9 @@ int main(int argc, char** argv) { if (state.cause_code == kPatchApplicationFailure) { LOG(INFO) << "Patch application failed, retry update."; fprintf(cmd_pipe, "retry_update\n"); + } else if (state.cause_code == kEioFailure) { + LOG(INFO) << "Update failed due to EIO, retry update."; + fprintf(cmd_pipe, "retry_update\n"); } } |