summaryrefslogtreecommitdiffstats
path: root/otafault
diff options
context:
space:
mode:
Diffstat (limited to 'otafault')
-rw-r--r--otafault/Android.mk48
-rw-r--r--otafault/config.cpp65
-rw-r--r--otafault/config.h74
-rw-r--r--otafault/ota_io.cpp175
-rw-r--r--otafault/ota_io.h4
-rw-r--r--otafault/test.cpp6
6 files changed, 136 insertions, 236 deletions
diff --git a/otafault/Android.mk b/otafault/Android.mk
index 52d706722..d441a7752 100644
--- a/otafault/Android.mk
+++ b/otafault/Android.mk
@@ -1,10 +1,10 @@
-# Copyright 2015 The Android Open Source Project
+# Copyright 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
+# 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,
@@ -14,21 +14,29 @@
LOCAL_PATH := $(call my-dir)
-# otafault (static library)
-# ===============================
-include $(CLEAR_VARS)
+empty :=
+space := $(empty) $(empty)
+comma := ,
-otafault_static_libs := \
- libminzip \
- libselinux \
- libz
+ifneq ($(TARGET_INJECT_FAULTS),)
+TARGET_INJECT_FAULTS := $(subst $(comma),$(space),$(strip $(TARGET_INJECT_FAULTS)))
+endif
+
+include $(CLEAR_VARS)
-LOCAL_SRC_FILES := config.cpp ota_io.cpp
+LOCAL_SRC_FILES := ota_io.cpp
+LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := libotafault
LOCAL_CLANG := true
-LOCAL_C_INCLUDES := bootable/recovery
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
-LOCAL_STATIC_LIBRARIES := $(otafault_static_libs)
+
+ifneq ($(TARGET_INJECT_FAULTS),)
+$(foreach ft,$(TARGET_INJECT_FAULTS),\
+ $(eval LOCAL_CFLAGS += -DTARGET_$(ft)_FAULT=$(TARGET_$(ft)_FAULT_FILE)))
+LOCAL_CFLAGS += -Wno-unused-parameter
+LOCAL_CFLAGS += -DTARGET_INJECT_FAULTS
+endif
+
+LOCAL_STATIC_LIBRARIES := libc
include $(BUILD_STATIC_LIBRARY)
@@ -36,13 +44,17 @@ include $(BUILD_STATIC_LIBRARY)
# ===============================
include $(CLEAR_VARS)
-LOCAL_SRC_FILES := config.cpp ota_io.cpp test.cpp
+LOCAL_SRC_FILES := ota_io.cpp test.cpp
LOCAL_MODULE_TAGS := tests
LOCAL_MODULE := otafault_test
-LOCAL_STATIC_LIBRARIES := \
- libotafault \
- $(otafault_static_libs)
-LOCAL_C_INCLUDES := bootable/recovery
+LOCAL_STATIC_LIBRARIES := libc
LOCAL_FORCE_STATIC_EXECUTABLE := true
+LOCAL_CFLAGS += -Wno-unused-parameter -Wno-writable-strings
+
+ifneq ($(TARGET_INJECT_FAULTS),)
+$(foreach ft,$(TARGET_INJECT_FAULTS),\
+ $(eval LOCAL_CFLAGS += -DTARGET_$(ft)_FAULT=$(TARGET_$(ft)_FAULT_FILE)))
+LOCAL_CFLAGS += -DTARGET_INJECT_FAULTS
+endif
include $(BUILD_EXECUTABLE)
diff --git a/otafault/config.cpp b/otafault/config.cpp
deleted file mode 100644
index c87f9a631..000000000
--- a/otafault/config.cpp
+++ /dev/null
@@ -1,65 +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 <map>
-#include <string>
-
-#include <stdio.h>
-#include <unistd.h>
-
-#include "minzip/Zip.h"
-#include "config.h"
-#include "ota_io.h"
-
-#define OTAIO_MAX_FNAME_SIZE 128
-
-static ZipArchive* archive;
-static std::map<const char*, bool> should_inject_cache;
-
-static const char* get_type_path(const char* io_type) {
- char* path = (char*)calloc(strlen(io_type) + strlen(OTAIO_BASE_DIR) + 2, sizeof(char));
- sprintf(path, "%s/%s", OTAIO_BASE_DIR, io_type);
- return path;
-}
-
-void ota_io_init(ZipArchive* za) {
- archive = za;
- ota_set_fault_files();
-}
-
-bool should_fault_inject(const char* io_type) {
- if (should_inject_cache.find(io_type) != should_inject_cache.end()) {
- return should_inject_cache[io_type];
- }
- const char* type_path = get_type_path(io_type);
- const ZipEntry* entry = mzFindZipEntry(archive, type_path);
- should_inject_cache[type_path] = entry != nullptr;
- free((void*)type_path);
- return entry != NULL;
-}
-
-bool should_hit_cache() {
- return should_fault_inject(OTAIO_CACHE);
-}
-
-std::string fault_fname(const char* io_type) {
- const char* type_path = get_type_path(io_type);
- char* fname = (char*) calloc(OTAIO_MAX_FNAME_SIZE, sizeof(char));
- const ZipEntry* entry = mzFindZipEntry(archive, type_path);
- mzReadZipEntry(archive, entry, fname, OTAIO_MAX_FNAME_SIZE);
- free((void*)type_path);
- return std::string(fname);
-}
diff --git a/otafault/config.h b/otafault/config.h
deleted file mode 100644
index 4430be3fb..000000000
--- a/otafault/config.h
+++ /dev/null
@@ -1,74 +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 <stdbool.h>
-
-#include "minzip/Zip.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(ZipArchive* za);
-
-/*
- * 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/ota_io.cpp b/otafault/ota_io.cpp
index dd805e56e..2d08fdef2 100644
--- a/otafault/ota_io.cpp
+++ b/otafault/ota_io.cpp
@@ -14,7 +14,9 @@
* limitations under the License.
*/
+#if defined (TARGET_INJECT_FAULTS)
#include <map>
+#endif
#include <errno.h>
#include <fcntl.h>
@@ -22,155 +24,186 @@
#include <sys/stat.h>
#include <unistd.h>
-#include "config.h"
#include "ota_io.h"
-static std::map<intptr_t, const char*> filename_cache;
-static std::string read_fault_file_name = "";
-static std::string write_fault_file_name = "";
-static std::string fsync_fault_file_name = "";
-bool have_eio_error = false;
-
-static bool get_hit_file(const char* cached_path, 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));
-}
+#if defined (TARGET_INJECT_FAULTS)
+static std::map<int, const char*> FilenameCache;
+static std::string FaultFileName =
+#if defined (TARGET_READ_FAULT)
+ TARGET_READ_FAULT;
+#elif defined (TARGET_WRITE_FAULT)
+ TARGET_WRITE_FAULT;
+#elif defined (TARGET_FSYNC_FAULT)
+ TARGET_FSYNC_FAULT;
+#endif // defined (TARGET_READ_FAULT)
+#endif // defined (TARGET_INJECT_FAULTS)
-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) {
+#if defined (TARGET_INJECT_FAULTS)
// Let the caller handle errors; we do not care if open succeeds or fails
int fd = open(path, oflags);
- filename_cache[fd] = path;
+ FilenameCache[fd] = path;
return fd;
+#else
+ return open(path, oflags);
+#endif
}
int ota_open(const char* path, int oflags, mode_t mode) {
+#if defined (TARGET_INJECT_FAULTS)
int fd = open(path, oflags, mode);
- filename_cache[fd] = path;
- return fd; }
+ FilenameCache[fd] = path;
+ return fd;
+#else
+ return open(path, oflags, mode);
+#endif
+}
FILE* ota_fopen(const char* path, const char* mode) {
+#if defined (TARGET_INJECT_FAULTS)
FILE* fh = fopen(path, mode);
- filename_cache[(intptr_t)fh] = path;
+ FilenameCache[(intptr_t)fh] = path;
return fh;
+#else
+ return fopen(path, mode);
+#endif
}
int ota_close(int fd) {
- // descriptors can be reused, so make sure not to leave them in the cache
- filename_cache.erase(fd);
+#if defined (TARGET_INJECT_FAULTS)
+ // descriptors can be reused, so make sure not to leave them in the cahce
+ FilenameCache.erase(fd);
+#endif
return close(fd);
}
int ota_fclose(FILE* fh) {
- filename_cache.erase((intptr_t)fh);
+#if defined (TARGET_INJECT_FAULTS)
+ FilenameCache.erase((intptr_t)fh);
+#endif
return fclose(fh);
}
size_t ota_fread(void* ptr, size_t size, size_t nitems, FILE* stream) {
- if (should_fault_inject(OTAIO_READ)) {
- 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;
+#if defined (TARGET_READ_FAULT)
+ if (FilenameCache.find((intptr_t)stream) != FilenameCache.end()
+ && FilenameCache[(intptr_t)stream] == FaultFileName) {
+ FaultFileName = "";
+ errno = EIO;
+ have_eio_error = true;
+ return 0;
+ } else {
+ 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 0;
}
+ return status;
}
+#else
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;
+#endif
}
ssize_t ota_read(int fd, void* buf, size_t nbyte) {
- if (should_fault_inject(OTAIO_READ)) {
- 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;
+#if defined (TARGET_READ_FAULT)
+ if (FilenameCache.find(fd) != FilenameCache.end()
+ && FilenameCache[fd] == FaultFileName) {
+ FaultFileName = "";
+ errno = EIO;
+ have_eio_error = true;
+ return -1;
+ } else {
+ ssize_t status = read(fd, buf, nbyte);
+ if (status == -1 && errno == EIO) {
have_eio_error = true;
- return -1;
}
+ return status;
}
+#else
ssize_t status = read(fd, buf, nbyte);
if (status == -1 && errno == EIO) {
have_eio_error = true;
}
return status;
+#endif
}
size_t ota_fwrite(const void* ptr, size_t size, size_t count, FILE* stream) {
- if (should_fault_inject(OTAIO_WRITE)) {
- 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;
+#if defined (TARGET_WRITE_FAULT)
+ if (FilenameCache.find((intptr_t)stream) != FilenameCache.end()
+ && FilenameCache[(intptr_t)stream] == FaultFileName) {
+ FaultFileName = "";
+ errno = EIO;
+ have_eio_error = true;
+ return 0;
+ } else {
+ size_t status = fwrite(ptr, size, count, stream);
+ if (status != count && errno == EIO) {
have_eio_error = true;
- return 0;
}
+ return status;
}
+#else
size_t status = fwrite(ptr, size, count, stream);
if (status != count && errno == EIO) {
have_eio_error = true;
}
return status;
+#endif
}
ssize_t ota_write(int fd, const void* buf, size_t nbyte) {
- if (should_fault_inject(OTAIO_WRITE)) {
- 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;
+#if defined (TARGET_WRITE_FAULT)
+ if (FilenameCache.find(fd) != FilenameCache.end()
+ && FilenameCache[fd] == FaultFileName) {
+ FaultFileName = "";
+ errno = EIO;
+ have_eio_error = true;
+ return -1;
+ } else {
+ ssize_t status = write(fd, buf, nbyte);
+ if (status == -1 && errno == EIO) {
have_eio_error = true;
- return -1;
}
+ return status;
}
+#else
ssize_t status = write(fd, buf, nbyte);
if (status == -1 && errno == EIO) {
have_eio_error = true;
}
return status;
+#endif
}
int ota_fsync(int fd) {
- if (should_fault_inject(OTAIO_FSYNC)) {
- 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;
+#if defined (TARGET_FSYNC_FAULT)
+ if (FilenameCache.find(fd) != FilenameCache.end()
+ && FilenameCache[fd] == FaultFileName) {
+ FaultFileName = "";
+ errno = EIO;
+ have_eio_error = true;
+ return -1;
+ } else {
+ int status = fsync(fd);
+ if (status == -1 && errno == EIO) {
have_eio_error = true;
- return -1;
}
+ return status;
}
+#else
int status = fsync(fd);
if (status == -1 && errno == EIO) {
have_eio_error = true;
}
return status;
+#endif
}
-
diff --git a/otafault/ota_io.h b/otafault/ota_io.h
index 84187a76e..641a5ae0a 100644
--- a/otafault/ota_io.h
+++ b/otafault/ota_io.h
@@ -26,10 +26,6 @@
#include <stdio.h>
#include <sys/stat.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);
diff --git a/otafault/test.cpp b/otafault/test.cpp
index 6514782bf..a0f731517 100644
--- a/otafault/test.cpp
+++ b/otafault/test.cpp
@@ -17,18 +17,16 @@
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
-#include <unistd.h>
#include "ota_io.h"
-int main(int /* argc */, char** /* argv */) {
+int main(int argc, char **argv) {
int fd = open("testdata/test.file", O_RDWR);
char buf[8];
- const char* out = "321";
+ 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;
}