Merge "Remove otafault"
diff --git a/applypatch/Android.bp b/applypatch/Android.bp
index cb0b367..620ca6c 100644
--- a/applypatch/Android.bp
+++ b/applypatch/Android.bp
@@ -53,7 +53,6 @@
         "libbz",
         "libcrypto",
         "libedify",
-        "libotafault",
         "libotautil",
         "libz",
     ],
@@ -100,7 +99,6 @@
         "libapplypatch_modes",
         "libapplypatch",
         "libedify",
-        "libotafault",
         "libotautil",
         "libbspatch",
     ],
diff --git a/applypatch/applypatch.cpp b/applypatch/applypatch.cpp
index b1aefa4..bc8ea79 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 @@
     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 @@
   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 @@
 
   // 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 @@
 
     // 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 @@
 
   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 @@
     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 @@
 
     // 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 @@
         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 @@
       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 @@
     return -1;
   }
 
-  if (ota_close(fd) == -1) {
-    PLOG(ERROR) << "Failed to close " << partition;
-    return -1;
-  }
   sync();
 
   return 0;
@@ -407,19 +362,6 @@
   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 b39d5be..0000000
--- 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 3993948..0000000
--- 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 cc4bfd2..0000000
--- 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 45e481a..0000000
--- 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 63ef18e..0000000
--- 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 63e2445..0000000
--- 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 0f6c9f8..2b73c13 100644
--- a/otautil/include/otautil/error_code.h
+++ b/otautil/include/otautil/error_code.h
@@ -49,6 +49,7 @@
   kPackageExtractFileFailure,
   kPatchApplicationFailure,
   kHashTreeComputationFailure,
+  kEioFailure,
   kVendorFailure = 200
 };
 
diff --git a/tests/Android.bp b/tests/Android.bp
index dc20f33..ab4d31d 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -56,7 +56,6 @@
     "libedify",
     "libimgdiff",
     "libimgpatch",
-    "libotafault",
     "libotautil",
     "libbsdiff",
     "libbspatch",
diff --git a/tests/component/updater_test.cpp b/tests/component/updater_test.cpp
index c4f3176..b253abc 100644
--- a/tests/component/updater_test.cpp
+++ b/tests/component/updater_test.cpp
@@ -272,7 +272,7 @@
     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 c77bac8..c95ec5e 100644
--- a/updater/Android.bp
+++ b/updater/Android.bp
@@ -24,7 +24,6 @@
         "libbootloader_message",
         "libbspatch",
         "libedify",
-        "libotafault",
         "libotautil",
         "libext4_utils",
         "libfec",
diff --git a/updater/Android.mk b/updater/Android.mk
index 5478a7d..78e32ba 100644
--- a/updater/Android.mk
+++ b/updater/Android.mk
@@ -27,7 +27,6 @@
     libbootloader_message \
     libbspatch \
     libedify \
-    libotafault \
     libotautil \
     libext4_utils \
     libfec \
diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp
index 96b2d9f..823a1cb 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 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 @@
   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 @@
         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 @@
     }
 
     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 @@
       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 @@
     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 @@
   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 @@
     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 @@
 
   std::string dname = GetStashFileName(base, "", "");
   if (!FsyncDir(dname)) {
-    failure_type = kFsyncFailure;
     return -1;
   }
 
@@ -1313,7 +1281,9 @@
       }
 
       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 @@
     }
 
     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 @@
     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 @@
     }
 
     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 @@
     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 @@
     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 @@
     }
 
     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 @@
     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 @@
   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 f933345..34514b6 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 @@
       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 @@
                  << "\": " << 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 @@
   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 @@
   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 e06d453..e87c57a 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 @@
       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 @@
       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");
       }
     }