Merge "IO fault injection for OTA packages"
diff --git a/Android.mk b/Android.mk
index a48980f..4da34ee 100644
--- a/Android.mk
+++ b/Android.mk
@@ -117,6 +117,7 @@
     $(LOCAL_PATH)/tools/Android.mk \
     $(LOCAL_PATH)/edify/Android.mk \
     $(LOCAL_PATH)/uncrypt/Android.mk \
+    $(LOCAL_PATH)/otafault/Android.mk \
     $(LOCAL_PATH)/updater/Android.mk \
     $(LOCAL_PATH)/update_verifier/Android.mk \
     $(LOCAL_PATH)/applypatch/Android.mk
diff --git a/applypatch/Android.mk b/applypatch/Android.mk
index 23d0f7b..90a86dc 100644
--- a/applypatch/Android.mk
+++ b/applypatch/Android.mk
@@ -21,7 +21,7 @@
 LOCAL_MODULE := libapplypatch
 LOCAL_MODULE_TAGS := eng
 LOCAL_C_INCLUDES += bootable/recovery
-LOCAL_STATIC_LIBRARIES += libbase libmtdutils libcrypto_static libbz libz
+LOCAL_STATIC_LIBRARIES += libbase libotafault libmtdutils libcrypto_static libbz libz
 
 include $(BUILD_STATIC_LIBRARY)
 
@@ -55,7 +55,7 @@
 LOCAL_SRC_FILES := main.cpp
 LOCAL_MODULE := applypatch
 LOCAL_C_INCLUDES += bootable/recovery
-LOCAL_STATIC_LIBRARIES += libapplypatch libbase libmtdutils libcrypto_static libbz libedify
+LOCAL_STATIC_LIBRARIES += libapplypatch libbase libotafault libmtdutils libcrypto_static libbz libedify
 LOCAL_SHARED_LIBRARIES += libz libcutils libc
 
 include $(BUILD_EXECUTABLE)
diff --git a/applypatch/applypatch.cpp b/applypatch/applypatch.cpp
index 75d7737..4eec332 100644
--- a/applypatch/applypatch.cpp
+++ b/applypatch/applypatch.cpp
@@ -35,6 +35,7 @@
 #include "mtdutils/mtdutils.h"
 #include "edify/expr.h"
 #include "print_sha1.h"
+#include "otafault/ota_io.h"
 
 static int LoadPartitionContents(const char* filename, FileContents* file);
 static ssize_t FileSink(const unsigned char* data, ssize_t len, void* token);
@@ -79,19 +80,19 @@
         return -1;
     }
 
-    FILE* f = fopen(filename, "rb");
+    FILE* f = ota_fopen(filename, "rb");
     if (f == NULL) {
         printf("failed to open \"%s\": %s\n", filename, strerror(errno));
         return -1;
     }
 
-    size_t bytes_read = fread(data.get(), 1, file->size, f);
+    size_t bytes_read = ota_fread(data.get(), 1, file->size, f);
     if (bytes_read != static_cast<size_t>(file->size)) {
         printf("short read of \"%s\" (%zu bytes of %zd)\n", filename, bytes_read, file->size);
-        fclose(f);
+        ota_fclose(f);
         return -1;
     }
-    fclose(f);
+    ota_fclose(f);
     file->data = data.release();
     SHA1(file->data, file->size, file->sha1);
     return 0;
@@ -180,7 +181,7 @@
         }
 
         case EMMC:
-            dev = fopen(partition, "rb");
+            dev = ota_fopen(partition, "rb");
             if (dev == NULL) {
                 printf("failed to open emmc partition \"%s\": %s\n", partition, strerror(errno));
                 return -1;
@@ -209,7 +210,7 @@
                     break;
 
                 case EMMC:
-                    read = fread(p, 1, next, dev);
+                    read = ota_fread(p, 1, next, dev);
                     break;
             }
             if (next != read) {
@@ -255,7 +256,7 @@
             break;
 
         case EMMC:
-            fclose(dev);
+            ota_fclose(dev);
             break;
     }
 
@@ -282,7 +283,7 @@
 // Save the contents of the given FileContents object under the given
 // filename.  Return 0 on success.
 int SaveFileContents(const char* filename, const FileContents* file) {
-    int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, S_IRUSR | S_IWUSR);
+    int fd = ota_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, S_IRUSR | S_IWUSR);
     if (fd < 0) {
         printf("failed to open \"%s\" for write: %s\n", filename, strerror(errno));
         return -1;
@@ -292,14 +293,14 @@
     if (bytes_written != file->size) {
         printf("short write of \"%s\" (%zd bytes of %zd) (%s)\n",
                filename, bytes_written, file->size, strerror(errno));
-        close(fd);
+        ota_close(fd);
         return -1;
     }
-    if (fsync(fd) != 0) {
+    if (ota_fsync(fd) != 0) {
         printf("fsync of \"%s\" failed: %s\n", filename, strerror(errno));
         return -1;
     }
-    if (close(fd) != 0) {
+    if (ota_close(fd) != 0) {
         printf("close of \"%s\" failed: %s\n", filename, strerror(errno));
         return -1;
     }
@@ -382,7 +383,7 @@
         case EMMC: {
             size_t start = 0;
             bool success = false;
-            int fd = open(partition, O_RDWR | O_SYNC);
+            int fd = ota_open(partition, O_RDWR | O_SYNC);
             if (fd < 0) {
                 printf("failed to open %s: %s\n", partition, strerror(errno));
                 return -1;
@@ -397,22 +398,22 @@
                     size_t to_write = len - start;
                     if (to_write > 1<<20) to_write = 1<<20;
 
-                    ssize_t written = TEMP_FAILURE_RETRY(write(fd, data+start, to_write));
+                    ssize_t written = TEMP_FAILURE_RETRY(ota_write(fd, data+start, to_write));
                     if (written == -1) {
                         printf("failed write writing to %s: %s\n", partition, strerror(errno));
                         return -1;
                     }
                     start += written;
                 }
-                if (fsync(fd) != 0) {
+                if (ota_fsync(fd) != 0) {
                    printf("failed to sync to %s (%s)\n", partition, strerror(errno));
                    return -1;
                 }
-                if (close(fd) != 0) {
+                if (ota_close(fd) != 0) {
                    printf("failed to close %s (%s)\n", partition, strerror(errno));
                    return -1;
                 }
-                fd = open(partition, O_RDONLY);
+                fd = ota_open(partition, O_RDONLY);
                 if (fd < 0) {
                    printf("failed to reopen %s for verify (%s)\n", partition, strerror(errno));
                    return -1;
@@ -421,13 +422,13 @@
                 // Drop caches so our subsequent verification read
                 // won't just be reading the cache.
                 sync();
-                int dc = open("/proc/sys/vm/drop_caches", O_WRONLY);
-                if (TEMP_FAILURE_RETRY(write(dc, "3\n", 2)) == -1) {
+                int dc = ota_open("/proc/sys/vm/drop_caches", O_WRONLY);
+                if (TEMP_FAILURE_RETRY(ota_write(dc, "3\n", 2)) == -1) {
                     printf("write to /proc/sys/vm/drop_caches failed: %s\n", strerror(errno));
                 } else {
                     printf("  caches dropped\n");
                 }
-                close(dc);
+                ota_close(dc);
                 sleep(1);
 
                 // verify
@@ -447,7 +448,7 @@
                     size_t so_far = 0;
                     while (so_far < to_read) {
                         ssize_t read_count =
-                                TEMP_FAILURE_RETRY(read(fd, buffer+so_far, to_read-so_far));
+                                TEMP_FAILURE_RETRY(ota_read(fd, buffer+so_far, to_read-so_far));
                         if (read_count == -1) {
                             printf("verify read error %s at %zu: %s\n",
                                    partition, p, strerror(errno));
@@ -479,7 +480,7 @@
                 return -1;
             }
 
-            if (close(fd) != 0) {
+            if (ota_close(fd) != 0) {
                 printf("error closing %s (%s)\n", partition, strerror(errno));
                 return -1;
             }
@@ -589,7 +590,7 @@
     ssize_t done = 0;
     ssize_t wrote;
     while (done < len) {
-        wrote = TEMP_FAILURE_RETRY(write(fd, data+done, len-done));
+        wrote = TEMP_FAILURE_RETRY(ota_write(fd, data+done, len-done));
         if (wrote == -1) {
             printf("error writing %zd bytes: %s\n", (len-done), strerror(errno));
             return done;
@@ -934,8 +935,8 @@
             token = &memory_sink_str;
         } else {
             // We write the decoded output to "<tgt-file>.patch".
-            output_fd = open(tmp_target_filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_SYNC,
-                          S_IRUSR | S_IWUSR);
+            output_fd = ota_open(tmp_target_filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_SYNC,
+                                 S_IRUSR | S_IWUSR);
             if (output_fd < 0) {
                 printf("failed to open output file %s: %s\n", tmp_target_filename.c_str(),
                        strerror(errno));
@@ -958,12 +959,12 @@
         }
 
         if (!target_is_partition) {
-            if (fsync(output_fd) != 0) {
+            if (ota_fsync(output_fd) != 0) {
                 printf("failed to fsync file \"%s\" (%s)\n", tmp_target_filename.c_str(),
                        strerror(errno));
                 result = 1;
             }
-            if (close(output_fd) != 0) {
+            if (ota_close(output_fd) != 0) {
                 printf("failed to close file \"%s\" (%s)\n", tmp_target_filename.c_str(),
                        strerror(errno));
                 result = 1;
diff --git a/otafault/Android.mk b/otafault/Android.mk
new file mode 100644
index 0000000..75617a1
--- /dev/null
+++ b/otafault/Android.mk
@@ -0,0 +1,58 @@
+# 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
+#
+# 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 languae governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+empty :=
+space := $(empty) $(empty)
+comma := ,
+
+ifneq ($(TARGET_INJECT_FAULTS),)
+TARGET_INJECT_FAULTS := $(subst $(comma),$(space),$(strip $(TARGET_INJECT_FAULTS)))
+endif
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := ota_io.cpp
+LOCAL_MODULE_TAGS := eng
+LOCAL_MODULE := libotafault
+LOCAL_CLANG := true
+
+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)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := ota_io.cpp test.cpp
+LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE := otafault_test
+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/ota_io.cpp b/otafault/ota_io.cpp
new file mode 100644
index 0000000..02e80f9
--- /dev/null
+++ b/otafault/ota_io.cpp
@@ -0,0 +1,160 @@
+/*
+ * 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.
+ */
+
+#if defined (TARGET_INJECT_FAULTS)
+#include <map>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "ota_io.h"
+
+#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)
+
+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);
+    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);
+    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);
+    FilenameCache[(intptr_t)fh] = path;
+    return fh;
+#else
+    return fopen(path, mode);
+#endif
+}
+
+int ota_close(int 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) {
+#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 defined (TARGET_READ_FAULT)
+    if (FilenameCache.find((intptr_t)stream) != FilenameCache.end()
+            && FilenameCache[(intptr_t)stream] == FaultFileName) {
+        FaultFileName = "";
+        errno = EIO;
+        return 0;
+    } else {
+        return fread(ptr, size, nitems, stream);
+    }
+#else
+    return fread(ptr, size, nitems, stream);
+#endif
+}
+
+ssize_t ota_read(int fd, void* buf, size_t nbyte) {
+#if defined (TARGET_READ_FAULT)
+    if (FilenameCache.find(fd) != FilenameCache.end()
+            && FilenameCache[fd] == FaultFileName) {
+        FaultFileName = "";
+        errno = EIO;
+        return -1;
+    } else {
+        return read(fd, buf, nbyte);
+    }
+#else
+    return read(fd, buf, nbyte);
+#endif
+}
+
+size_t ota_fwrite(const void* ptr, size_t size, size_t count, FILE* stream) {
+#if defined (TARGET_WRITE_FAULT)
+    if (FilenameCache.find((intptr_t)stream) != FilenameCache.end()
+            && FilenameCache[(intptr_t)stream] == FaultFileName) {
+        FaultFileName = "";
+        errno = EIO;
+        return 0;
+    } else {
+        return fwrite(ptr, size, count, stream);
+    }
+#else
+    return fwrite(ptr, size, count, stream);
+#endif
+}
+
+ssize_t ota_write(int fd, const void* buf, size_t nbyte) {
+#if defined (TARGET_WRITE_FAULT)
+    if (FilenameCache.find(fd) != FilenameCache.end()
+            && FilenameCache[fd] == FaultFileName) {
+        FaultFileName = "";
+        errno = EIO;
+        return -1;
+    } else {
+        return write(fd, buf, nbyte);
+    }
+#else
+    return write(fd, buf, nbyte);
+#endif
+}
+
+int ota_fsync(int fd) {
+#if defined (TARGET_FSYNC_FAULT)
+    if (FilenameCache.find(fd) != FilenameCache.end()
+            && FilenameCache[fd] == FaultFileName) {
+        FaultFileName = "";
+        errno = EIO;
+        return -1;
+    } else {
+        return fsync(fd);
+    }
+#else
+    return fsync(fd);
+#endif
+}
diff --git a/otafault/ota_io.h b/otafault/ota_io.h
new file mode 100644
index 0000000..641a5ae
--- /dev/null
+++ b/otafault/ota_io.h
@@ -0,0 +1,49 @@
+/*
+ * 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 <stdio.h>
+#include <sys/stat.h>
+
+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);
+
+int ota_close(int fd);
+
+int ota_fclose(FILE* fh);
+
+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);
+
+#endif
diff --git a/otafault/test.cpp b/otafault/test.cpp
new file mode 100644
index 0000000..a0f7315
--- /dev/null
+++ b/otafault/test.cpp
@@ -0,0 +1,32 @@
+/*
+ * 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 <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+#include "ota_io.h"
+
+int main(int argc, char **argv) {
+    int fd = open("testdata/test.file", O_RDWR);
+    char buf[8];
+    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);
+    return 0;
+}
diff --git a/updater/Android.mk b/updater/Android.mk
index 6fdd308..d7aa613 100644
--- a/updater/Android.mk
+++ b/updater/Android.mk
@@ -45,7 +45,7 @@
 endif
 
 LOCAL_STATIC_LIBRARIES += $(TARGET_RECOVERY_UPDATER_LIBS) $(TARGET_RECOVERY_UPDATER_EXTRA_LIBS)
-LOCAL_STATIC_LIBRARIES += libapplypatch libbase libedify libmtdutils libminzip libz
+LOCAL_STATIC_LIBRARIES += libapplypatch libbase libotafault libedify libmtdutils libminzip libz
 LOCAL_STATIC_LIBRARIES += libbz
 LOCAL_STATIC_LIBRARIES += libcutils liblog libc
 LOCAL_STATIC_LIBRARIES += libselinux
diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp
index 6e05600..44de4e0 100644
--- a/updater/blockimg.cpp
+++ b/updater/blockimg.cpp
@@ -45,6 +45,7 @@
 #include "install.h"
 #include "openssl/sha.h"
 #include "minzip/Hash.h"
+#include "otafault/ota_io.h"
 #include "print_sha1.h"
 #include "unique_fd.h"
 #include "updater.h"
@@ -139,7 +140,7 @@
 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(read(fd, data+so_far, size-so_far));
+        ssize_t r = TEMP_FAILURE_RETRY(ota_read(fd, data+so_far, size-so_far));
         if (r == -1) {
             fprintf(stderr, "read failed: %s\n", strerror(errno));
             return -1;
@@ -156,7 +157,7 @@
 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(write(fd, data+written, size-written));
+        ssize_t w = TEMP_FAILURE_RETRY(ota_write(fd, data+written, size-written));
         if (w == -1) {
             fprintf(stderr, "write failed: %s\n", strerror(errno));
             return -1;
@@ -553,7 +554,7 @@
         return -1;
     }
 
-    int fd = TEMP_FAILURE_RETRY(open(fn.c_str(), O_RDONLY));
+    int fd = TEMP_FAILURE_RETRY(ota_open(fn.c_str(), O_RDONLY));
     unique_fd fd_holder(fd);
 
     if (fd == -1) {
@@ -610,7 +611,7 @@
 
     fprintf(stderr, " writing %d blocks to %s\n", blocks, cn.c_str());
 
-    int fd = TEMP_FAILURE_RETRY(open(fn.c_str(), O_WRONLY | O_CREAT | O_TRUNC, STASH_FILE_MODE));
+    int fd = TEMP_FAILURE_RETRY(ota_open(fn.c_str(), O_WRONLY | O_CREAT | O_TRUNC, STASH_FILE_MODE));
     unique_fd fd_holder(fd);
 
     if (fd == -1) {
@@ -622,7 +623,7 @@
         return -1;
     }
 
-    if (fsync(fd) == -1) {
+    if (ota_fsync(fd) == -1) {
         fprintf(stderr, "fsync \"%s\" failed: %s\n", fn.c_str(), strerror(errno));
         return -1;
     }
@@ -634,7 +635,7 @@
     }
 
     std::string dname = GetStashFileName(base, "", "");
-    int dfd = TEMP_FAILURE_RETRY(open(dname.c_str(), O_RDONLY | O_DIRECTORY));
+    int dfd = TEMP_FAILURE_RETRY(ota_open(dname.c_str(), O_RDONLY | O_DIRECTORY));
     unique_fd dfd_holder(dfd);
 
     if (dfd == -1) {
@@ -642,7 +643,7 @@
         return -1;
     }
 
-    if (fsync(dfd) == -1) {
+    if (ota_fsync(dfd) == -1) {
         fprintf(stderr, "fsync \"%s\" failed: %s\n", dname.c_str(), strerror(errno));
         return -1;
     }
@@ -1346,7 +1347,7 @@
         return StringValue(strdup(""));
     }
 
-    params.fd = TEMP_FAILURE_RETRY(open(blockdev_filename->data, O_RDWR));
+    params.fd = TEMP_FAILURE_RETRY(ota_open(blockdev_filename->data, O_RDWR));
     unique_fd fd_holder(params.fd);
 
     if (params.fd == -1) {
@@ -1465,7 +1466,7 @@
         }
 
         if (params.canwrite) {
-            if (fsync(params.fd) == -1) {
+            if (ota_fsync(params.fd) == -1) {
                 fprintf(stderr, "fsync failed: %s\n", strerror(errno));
                 goto pbiudone;
             }
@@ -1490,7 +1491,7 @@
     rc = 0;
 
 pbiudone:
-    if (fsync(params.fd) == -1) {
+    if (ota_fsync(params.fd) == -1) {
         fprintf(stderr, "fsync failed: %s\n", strerror(errno));
     }
     // params.fd will be automatically closed because of the fd_holder above.
@@ -1614,7 +1615,7 @@
         return StringValue(strdup(""));
     }
 
-    int fd = open(blockdev_filename->data, O_RDWR);
+    int fd = ota_open(blockdev_filename->data, O_RDWR);
     unique_fd fd_holder(fd);
     if (fd < 0) {
         ErrorAbort(state, "open \"%s\" failed: %s", blockdev_filename->data, strerror(errno));
@@ -1668,7 +1669,7 @@
         return StringValue(strdup(""));
     }
 
-    int fd = open(arg_filename->data, O_RDONLY);
+    int fd = ota_open(arg_filename->data, O_RDONLY);
     unique_fd fd_holder(fd);
     if (fd == -1) {
         ErrorAbort(state, "open \"%s\" failed: %s", arg_filename->data, strerror(errno));
diff --git a/updater/install.cpp b/updater/install.cpp
index 45bbf2b..1cd9a56 100644
--- a/updater/install.cpp
+++ b/updater/install.cpp
@@ -51,6 +51,7 @@
 #include "minzip/DirUtil.h"
 #include "mtdutils/mounts.h"
 #include "mtdutils/mtdutils.h"
+#include "otafault/ota_io.h"
 #include "updater.h"
 #include "install.h"
 #include "tune2fs.h"
@@ -557,18 +558,18 @@
         }
 
         {
-            int fd = TEMP_FAILURE_RETRY(open(dest_path, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC,
+            int fd = TEMP_FAILURE_RETRY(ota_open(dest_path, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC,
                   S_IRUSR | S_IWUSR));
             if (fd == -1) {
                 printf("%s: can't open %s for write: %s\n", name, dest_path, strerror(errno));
                 goto done2;
             }
             success = mzExtractZipEntryToFile(za, entry, fd);
-            if (fsync(fd) == -1) {
+            if (ota_fsync(fd) == -1) {
                 printf("fsync of \"%s\" failed: %s\n", dest_path, strerror(errno));
                 success = false;
             }
-            if (close(fd) == -1) {
+            if (ota_close(fd) == -1) {
                 printf("close of \"%s\" failed: %s\n", dest_path, strerror(errno));
                 success = false;
             }
@@ -995,21 +996,21 @@
     }
 
     FILE* f;
-    f = fopen(filename, "rb");
+    f = ota_fopen(filename, "rb");
     if (f == NULL) {
         ErrorAbort(state, "%s: failed to open %s: %s", name, filename, strerror(errno));
         goto done;
     }
 
-    if (fread(buffer, 1, st.st_size, f) != static_cast<size_t>(st.st_size)) {
+    if (ota_fread(buffer, 1, st.st_size, f) != static_cast<size_t>(st.st_size)) {
         ErrorAbort(state, "%s: failed to read %lld bytes from %s",
                    name, (long long)st.st_size+1, filename);
-        fclose(f);
+        ota_fclose(f);
         goto done;
     }
     buffer[st.st_size] = '\0';
 
-    fclose(f);
+    ota_fclose(f);
 
     char* line;
     line = strtok(buffer, "\n");
@@ -1104,7 +1105,7 @@
     if (contents->type == VAL_STRING) {
         // we're given a filename as the contents
         char* filename = contents->data;
-        FILE* f = fopen(filename, "rb");
+        FILE* f = ota_fopen(filename, "rb");
         if (f == NULL) {
             printf("%s: can't open %s: %s\n", name, filename, strerror(errno));
             result = strdup("");
@@ -1114,12 +1115,12 @@
         success = true;
         char* buffer = reinterpret_cast<char*>(malloc(BUFSIZ));
         int read;
-        while (success && (read = fread(buffer, 1, BUFSIZ, f)) > 0) {
+        while (success && (read = ota_fread(buffer, 1, BUFSIZ, f)) > 0) {
             int wrote = mtd_write_data(ctx, buffer, read);
             success = success && (wrote == read);
         }
         free(buffer);
-        fclose(f);
+        ota_fclose(f);
     } else {
         // we're given a blob as the contents
         ssize_t wrote = mtd_write_data(ctx, contents->data, contents->size);
@@ -1438,10 +1439,10 @@
 
     // zero out the 'command' field of the bootloader message.
     memset(buffer, 0, sizeof(((struct bootloader_message*)0)->command));
-    FILE* f = fopen(filename, "r+b");
+    FILE* f = ota_fopen(filename, "r+b");
     fseek(f, offsetof(struct bootloader_message, command), SEEK_SET);
-    fwrite(buffer, sizeof(((struct bootloader_message*)0)->command), 1, f);
-    fclose(f);
+    ota_fwrite(buffer, sizeof(((struct bootloader_message*)0)->command), 1, f);
+    ota_fclose(f);
     free(filename);
 
     strcpy(buffer, "reboot,");
@@ -1480,7 +1481,7 @@
     // bootloader message that the main recovery uses to save its
     // arguments in case of the device restarting midway through
     // package installation.
-    FILE* f = fopen(filename, "r+b");
+    FILE* f = ota_fopen(filename, "r+b");
     fseek(f, offsetof(struct bootloader_message, stage), SEEK_SET);
     int to_write = strlen(stagestr)+1;
     int max_size = sizeof(((struct bootloader_message*)0)->stage);
@@ -1488,8 +1489,8 @@
         to_write = max_size;
         stagestr[max_size-1] = 0;
     }
-    fwrite(stagestr, to_write, 1, f);
-    fclose(f);
+    ota_fwrite(stagestr, to_write, 1, f);
+    ota_fclose(f);
 
     free(stagestr);
     return StringValue(filename);
@@ -1506,10 +1507,10 @@
     if (ReadArgs(state, argv, 1, &filename) < 0) return NULL;
 
     char buffer[sizeof(((struct bootloader_message*)0)->stage)];
-    FILE* f = fopen(filename, "rb");
+    FILE* f = ota_fopen(filename, "rb");
     fseek(f, offsetof(struct bootloader_message, stage), SEEK_SET);
-    fread(buffer, sizeof(buffer), 1, f);
-    fclose(f);
+    ota_fread(buffer, sizeof(buffer), 1, f);
+    ota_fclose(f);
     buffer[sizeof(buffer)-1] = '\0';
 
     return StringValue(strdup(buffer));
@@ -1526,13 +1527,13 @@
 
     size_t len;
     android::base::ParseUint(len_str, &len);
-    int fd = open(filename, O_WRONLY, 0644);
+    int fd = ota_open(filename, O_WRONLY, 0644);
     int success = wipe_block_device(fd, len);
 
     free(filename);
     free(len_str);
 
-    close(fd);
+    ota_close(fd);
 
     return StringValue(strdup(success ? "t" : ""));
 }