Revert "Introduce InputFile/OutputFile and FileMutex."

This reverts commit d670be7a08cb85329ff3b5e9039cda9ffa4a35a1.

Conflicts:

	lib/ExecutionEngine/InputFile.cpp
	lib/ExecutionEngine/OutputFile.cpp

Change-Id: I99d5ed4cbda7296a399d683dfa264ce68bc4ddf3
diff --git a/lib/ExecutionEngine/Android.mk b/lib/ExecutionEngine/Android.mk
index ae6352c..e26be60 100644
--- a/lib/ExecutionEngine/Android.mk
+++ b/lib/ExecutionEngine/Android.mk
@@ -26,13 +26,11 @@
   BCCContext.cpp \
   BCCContextImpl.cpp \
   Compiler.cpp \
-  FileBase.cpp \
+  FileHandle.cpp \
   GDBJIT.cpp \
   GDBJITRegistrar.cpp \
-  InputFile.cpp \
   MCCacheWriter.cpp \
   MCCacheReader.cpp \
-  OutputFile.cpp \
   RSScript.cpp \
   Runtime.c \
   RuntimeStub.c \
diff --git a/lib/ExecutionEngine/Compiler.cpp b/lib/ExecutionEngine/Compiler.cpp
index a56c11c..100f54b 100644
--- a/lib/ExecutionEngine/Compiler.cpp
+++ b/lib/ExecutionEngine/Compiler.cpp
@@ -24,6 +24,7 @@
 #endif
 
 #include "DebugHelper.h"
+#include "FileHandle.h"
 #include "Runtime.h"
 #include "ScriptCompiled.h"
 #include "Sha1Helper.h"
diff --git a/lib/ExecutionEngine/File.h b/lib/ExecutionEngine/File.h
deleted file mode 100644
index 4b7ad4d..0000000
--- a/lib/ExecutionEngine/File.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef BCC_EXECUTION_ENGINE_FILE_H
-#define BCC_EXECUTION_ENGINE_FILE_H
-
-#include "FileBase.h"
-
-namespace bcc {
-
-template<enum FileBase::OpenModeEnum OpenMode>
-struct FileAttribute {
-  // The flags to the 2nd argument in ::open().
-  enum { kOpenFlags };
-
-  // Default value of LockMode.
-  enum { kDefaultLockMode };
-};
-
-// FileAttribute for accessing read-only file
-template<>
-struct FileAttribute<FileBase::kReadMode> {
-  enum { kOpenFlags       = O_RDONLY };
-  enum { kDefaultLockMode = FileBase::kReadLock };
-};
-
-// FileAttribute for accessing writable file
-template<>
-struct FileAttribute<FileBase::kWriteMode> {
-  enum { kOpenFlags       = O_RDWR | O_CREAT | O_TRUNC };
-  enum { kDefaultLockMode = FileBase::kWriteLock };
-};
-
-template<enum FileBase::OpenModeEnum OpenMode>
-class File : public FileBase {
-public:
-  File(const std::string &pFilename, unsigned pFlags)
-    : FileBase(pFilename, FileAttribute<OpenMode>::kOpenFlags, pFlags) { }
-
-  inline bool lock(enum LockModeEnum pMode = static_cast<enum LockModeEnum>(
-                      FileAttribute<OpenMode>::kDefaultLockMode),
-                   bool pNonblocking = true,
-                   unsigned pMaxRetry = FileBase::kDefaultMaxRetryLock,
-                   useconds_t pRetryInterval =
-                      FileBase::kDefaultRetryLockInterval) {
-    return FileBase::lock(pMode, pNonblocking, pMaxRetry, pRetryInterval);
-  }
-
-  inline android::FileMap *createMap(off_t pOffset, size_t pLength,
-                                     bool pIsReadOnly =
-                                        (OpenMode == FileBase::kReadMode)) {
-    return FileBase::createMap(pOffset, pLength, pIsReadOnly);
-  }
-};
-
-
-} // end namespace bcc
-
-#endif  // BCC_EXECUTION_ENGINE_FILE_H
diff --git a/lib/ExecutionEngine/FileBase.cpp b/lib/ExecutionEngine/FileBase.cpp
deleted file mode 100644
index 379406d..0000000
--- a/lib/ExecutionEngine/FileBase.cpp
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright 2012, 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 "FileBase.h"
-
-#include <sys/file.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include <cerrno>
-#include <new>
-
-#include <utils/FileMap.h>
-
-using namespace bcc;
-
-FileBase::FileBase(const std::string &pFilename,
-                   unsigned pOpenFlags,
-                   unsigned pFlags)
-  : mFD(-1),
-    mError(),
-    mName(pFilename), mOpenFlags(pOpenFlags),
-    mShouldUnlock(false) {
-  // Process pFlags
-#ifdef O_BINARY
-  if (pFlags & kBinary) {
-    mOpenFlags |= O_BINARY;
-  }
-#endif
-
-  // Open the file.
-  open();
-
-  return;
-}
-
-FileBase::~FileBase() {
-  close();
-}
-
-bool FileBase::open() {
-  do {
-    // FIXME: Hard-coded permissions (0644) for newly created file should be
-    //        removed and provide a way to let the user configure the value.
-    mFD = ::open(mName.c_str(), mOpenFlags, 0644);
-    if (mFD > 0) {
-      return true;
-    }
-
-    // Some errors occurred ...
-    if (errno != EINTR) {
-      detectError();
-      return false;
-    }
-  } while (true);
-  // unreachable
-}
-
-
-bool FileBase::checkFileIntegrity() {
-  // Check the file integrity by examine whether the inode referred to the mFD
-  // and to the file mName are the same.
-  struct stat fd_stat, file_stat;
-
-  // Get the file status of file descriptor mFD.
-  do {
-    if (::fstat(mFD, &fd_stat) == 0) {
-      break;
-    } else if (errno != EINTR) {
-      detectError();
-      return false;
-    }
-  } while (true);
-
-  // Get the file status of file mName.
-  do {
-    if (::stat(mName.c_str(), &file_stat) == 0) {
-      break;
-    } else if (errno != EINTR) {
-      detectError();
-      return false;
-    }
-  } while (true);
-
-  return ((fd_stat.st_dev == file_stat.st_dev) &&
-          (fd_stat.st_ino == file_stat.st_ino));
-}
-
-void FileBase::detectError() {
-  // Read error from errno.
-  mError.assign(errno, llvm::posix_category());
-}
-
-bool FileBase::lock(enum LockModeEnum pMode,
-                    bool pNonblocking,
-                    unsigned pMaxRetry,
-                    useconds_t pRetryInterval) {
-  int lock_operation;
-  unsigned retry = 0;
-
-  // Check the state.
-  if ((mFD < 0) || hasError()) {
-    return false;
-  }
-
-  // Return immediately if it's already locked.
-  if (mShouldUnlock) {
-    return true;
-  }
-
-  // Determine the lock operation (2nd argument) to the flock().
-  if (pMode == kReadLock) {
-    lock_operation = LOCK_SH;
-  } else if (pMode == kWriteLock) {
-    lock_operation = LOCK_EX;
-  } else {
-    mError.assign(llvm::errc::invalid_argument, llvm::posix_category());
-    return false;
-  }
-
-  if (pNonblocking) {
-    lock_operation |= LOCK_NB;
-  }
-
-  do {
-    if (::flock(mFD, lock_operation) == 0) {
-      mShouldUnlock = true;
-      // Here we got a lock but we need to check whether the mFD still
-      // "represents" the filename (mName) we opened in the contructor. This
-      // check may failed when another process deleted the original file mFD
-      // mapped when we were trying to obtain the lock on the file.
-      if (!checkFileIntegrity()) {
-        if (hasError() || !reopen()) {
-          // Error occurred when check the file integrity or re-open the file.
-          return false;
-        } else {
-          // Wait a while before the next try.
-          ::usleep(pRetryInterval);
-          retry++;
-          continue;
-        }
-      }
-
-      return true;
-    }
-
-    // flock() was not performed successfully. Check the errno to see whether
-    // it's retry-able.
-    if (errno == EINTR) {
-      // flock() was interrupted by delivery of a signal. Restart without
-      // decrement the retry counter.
-      continue;
-    } else if (errno == EWOULDBLOCK) {
-      // The file descriptor was locked by others, wait for a while before next
-      // retry.
-      retry++;
-      ::usleep(pRetryInterval);
-    } else {
-      // There's a fatal error occurs when perform flock(). Return immediately
-      // without further retry.
-      detectError();
-      return false;
-    }
-  } while (retry <= pMaxRetry);
-
-  return false;
-}
-
-void FileBase::unlock() {
-  if (mFD < 0) {
-    return;
-  }
-
-  do {
-    if (::flock(mFD, LOCK_UN) == 0) {
-      mShouldUnlock = false;
-      return;
-    }
-  } while (errno == EINTR);
-
-  detectError();
-  return;
-}
-
-android::FileMap *FileBase::createMap(off_t pOffset, size_t pLength,
-                                      bool pIsReadOnly) {
-  if (mFD < 0 || hasError()) {
-    return NULL;
-  }
-
-  android::FileMap *map = new (std::nothrow) android::FileMap();
-  if (map == NULL) {
-    mError.assign(llvm::errc::not_enough_memory, llvm::system_category());
-    return NULL;
-  }
-
-  if (!map->create(NULL, mFD, pOffset, pLength, pIsReadOnly)) {
-    detectError();
-    map->release();
-    return NULL;
-  }
-
-  return map;
-}
-
-size_t FileBase::getSize() {
-  if (mFD < 0 || hasError()) {
-    return static_cast<size_t>(-1);
-  }
-
-  struct stat file_stat;
-  do {
-    if (::fstat(mFD, &file_stat) == 0) {
-      break;
-    } else if (errno != EINTR) {
-      detectError();
-      return static_cast<size_t>(-1);
-    }
-  } while (true);
-
-  return file_stat.st_size;
-}
-
-off_t FileBase::seek(off_t pOffset) {
-  if ((mFD < 0) || hasError()) {
-    return static_cast<off_t>(-1);
-  }
-
-  do {
-    off_t result = ::lseek(mFD, pOffset, SEEK_SET);
-    if (result == pOffset) {
-      return result;
-    }
-  } while (errno == EINTR);
-
-  detectError();
-  return static_cast<off_t>(-1);
-}
-
-off_t FileBase::tell() {
-  if ((mFD < 0) || hasError()) {
-    return static_cast<off_t>(-1);
-  }
-
-  do {
-    off_t result = ::lseek(mFD, 0, SEEK_CUR);
-    if (result != static_cast<off_t>(-1)) {
-      return result;
-    }
-  } while (errno == EINTR);
-
-  detectError();
-  return static_cast<off_t>(-1);
-}
-
-void FileBase::close() {
-  if (mShouldUnlock) {
-    unlock();
-    mShouldUnlock = false;
-  }
-  if (mFD > 0) {
-    ::close(mFD);
-    mFD = -1;
-  }
-  return;
-}
diff --git a/lib/ExecutionEngine/FileBase.h b/lib/ExecutionEngine/FileBase.h
deleted file mode 100644
index 62d6504..0000000
--- a/lib/ExecutionEngine/FileBase.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef BCC_EXECUTION_ENGINE_FILE_BASE_H
-#define BCC_EXECUTION_ENGINE_FILE_BASE_H
-
-#include <fcntl.h>
-
-#include <string>
-
-#include <llvm/Support/system_error.h>
-
-namespace android {
-  class FileMap;
-}
-
-namespace bcc {
-
-class FileBase {
-public:
-  enum OpenModeEnum {
-    kReadMode       = 1 << 0,
-    kWriteMode      = 1 << 1,
-    kReadWriteMode  = (kReadMode | kWriteMode),
-  };
-
-  enum FlagEnum {
-    // The openning file is a binary file.
-    kBinary = 1 << 0,
-  };
-
-  enum LockModeEnum {
-    // The shared resource behind the Stream locked in ReadLock mode can be
-    // locked by other processes at the same time.
-    kReadLock,
-
-    // The shared resource behind the Stream locked in WriteLock mode can only
-    // be locked by one process. It's exclusive. That is, the shared resource
-    // cannot have both ReadLock and WriteLock simultaneously.
-    kWriteLock
-  };
-
-  // Default configuration to the lock().
-  enum {
-    kDefaultMaxRetryLock = 4,
-    kDefaultRetryLockInterval = 200000UL,
-  };
-
-protected:
-  // Grant direct access of the internal file descriptor to the sub-class and
-  // error message such that they can implement their own I/O functionality.
-  int mFD;
-
-  llvm::error_code mError;
-
-private:
-  std::string mName;
-
-  // The 2nd argument to the POSIX open().
-  unsigned mOpenFlags;
-
-  // True true if we should call unlock() in destructor.
-  bool mShouldUnlock;
-
-  // Open mName with flag mOpenFlags (using POSIX open().)
-  bool open();
-
-  // Return true if mFD is the corresponded file descriptor to the file named
-  // mName on the filesystem. This check may returns failed, for example,
-  // someone re-create the file with the same name after we openning the file.
-  bool checkFileIntegrity();
-
-  inline bool reopen() {
-    // Don't need to check the object state since this is a private method.
-    close();
-    return open();
-  }
-
-private:
-  FileBase(FileBase &); // Do not implement.
-  void operator=(const FileBase &); // Do not implement.
-
-protected:
-  // pOpenFlags is the 2nd argument to the POSIX open(). pFlags are the flags to
-  // FileBase. It's a bit set composed by the value defined in
-  // FileBase::FlagEnum.
-  FileBase(const std::string &pFilename, unsigned pOpenFlags, unsigned pFlags);
-
-  void detectError();
-
-public:
-  // Lock the file descriptor in given pMode. If pNonblocking is true, the lock
-  // request issued will return immediately when the shared resource is locked.
-  // In this case, it retries pMaxRetry times, each wait pRetryInterval (in
-  // usecs) before the previous retry getting done.
-  //
-  // Only file is allowed to use this API.
-  bool lock(enum LockModeEnum pMode, bool pNonblocking = true,
-            unsigned pMaxRetry = kDefaultMaxRetryLock,
-            useconds_t pRetryInterval = kDefaultRetryLockInterval);
-
-  void unlock();
-
-  // Map the file content to the memory.
-  //
-  // One who gets non-null android::FileMap returned from this API is resposible
-  // for destroying it after the use.
-  android::FileMap *createMap(off_t pOffset, size_t pLength, bool pIsReadOnly);
-
-  size_t getSize();
-
-  off_t seek(off_t pOffset);
-  off_t tell();
-
-  inline bool hasError() const
-  { return (mError.value() != llvm::errc::success); }
-
-  inline const llvm::error_code &getError() const
-  { return mError; }
-
-  // The return value of llvm::error_code::message() is obtained upon the call
-  // and is passed by value (that is, it's not a member of llvm::error_code.)
-  inline std::string getErrorMessage() const
-  { return mError.message(); }
-
-  inline const std::string &getName() const
-  { return mName; }
-
-  void close();
-
-  virtual ~FileBase();
-};
-
-} // end namespace bcc
-
-#endif  // BCC_EXECUTION_ENGINE_FILE_BASE_H
diff --git a/lib/ExecutionEngine/FileHandle.cpp b/lib/ExecutionEngine/FileHandle.cpp
new file mode 100644
index 0000000..c659fb5
--- /dev/null
+++ b/lib/ExecutionEngine/FileHandle.cpp
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2010, 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 "FileHandle.h"
+
+#include "DebugHelper.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <string.h>
+
+namespace bcc {
+
+int FileHandle::open(char const *filename, OpenMode::ModeType mode) {
+  static int const open_flags[2] = {
+    O_RDONLY,
+    O_RDWR | O_CREAT | O_TRUNC,
+  };
+
+  static int const lock_flags[2] = { LOCK_SH, LOCK_EX };
+
+  static char const *const open_mode_str[2] = { "read", "write" };
+
+  static size_t const RETRY_MAX = 4;
+
+  static useconds_t const RETRY_USEC = 200000UL;
+
+  for (size_t i = 0; i < RETRY_MAX; ++i) {
+    // Try to open the file
+    mFD = ::open(filename, open_flags[mode], 0644);
+
+    if (mFD < 0) {
+      if (errno == EINTR) {
+        // Interrupt occurs while opening the file.  Retry.
+        continue;
+      }
+
+      ALOGW("Unable to open %s in %s mode.  (reason: %s)\n",
+           filename, open_mode_str[mode], strerror(errno));
+
+      return -1;
+    }
+
+    // Try to lock the file
+    if (flock(mFD, lock_flags[mode] | LOCK_NB) < 0) {
+      ALOGW("Unable to acquire the lock immediately, block and wait now ...\n");
+
+      if (flock(mFD, lock_flags[mode]) < 0) {
+        ALOGE("Unable to acquire the lock. Retry ...\n");
+
+        ::close(mFD);
+        mFD = -1;
+
+        usleep(RETRY_USEC);
+        continue;
+      }
+    }
+
+    // Note: From now on, the object is correctly initialized.  We have to
+    // use this->close() to close the file now.
+
+    // Check rather we have locked the correct file or not
+    struct stat sfd, sfname;
+
+    if (fstat(mFD, &sfd) == -1 || stat(filename, &sfname) == -1 ||
+        sfd.st_dev != sfname.st_dev || sfd.st_ino != sfname.st_ino) {
+      // The file we locked is different from the given path.  This may
+      // occur when someone changes the file node before we lock the file.
+      // Just close the file, and retry after sleeping.
+
+      this->close();
+      usleep(RETRY_USEC);
+      continue;
+    }
+
+    // Good, we have open and lock the file correctly.
+    ALOGV("File opened. fd=%d\n", mFD);
+    return mFD;
+  }
+
+  ALOGW("Unable to open %s in %s mode.\n", filename, open_mode_str[mode]);
+  return -1;
+}
+
+
+void FileHandle::close() {
+  if (mFD >= 0) {
+    flock(mFD, LOCK_UN);
+    ::close(mFD);
+    ALOGV("File closed. fd=%d\n", mFD);
+    mFD = -1;
+  }
+}
+
+
+ssize_t FileHandle::read(char *buf, size_t count) {
+  if (mFD < 0) {
+    return -1;
+  }
+
+  while (true) {
+    ssize_t nread = ::read(mFD, static_cast<void *>(buf), count);
+
+    if (nread >= 0) {
+      return nread;
+    }
+
+    if (errno != EAGAIN && errno != EINTR) {
+      // If the errno is EAGAIN or EINTR, then we try to read again.
+      // Otherwise, consider this is a failure.  And returns zero.
+      return -1;
+    }
+  }
+
+  // Unreachable
+  return -1;
+}
+
+
+ssize_t FileHandle::write(char const *buf, size_t count) {
+  if (mFD < 0) {
+    return -1;
+  }
+
+  ssize_t written = 0;
+
+  while (count > 0) {
+    ssize_t nwrite = ::write(mFD, static_cast<void const *>(buf), count);
+
+    if (nwrite < 0) {
+      if (errno != EAGAIN && errno != EINTR) {
+        return written;
+      }
+
+      continue;
+    }
+
+    written += nwrite;
+    count -= (size_t)nwrite;
+    buf += (size_t)nwrite;
+  }
+
+  return written;
+}
+
+
+off_t FileHandle::seek(off_t offset, int whence) {
+  return (mFD < 0) ? -1 : lseek(mFD, offset, whence);
+}
+
+
+void FileHandle::truncate() {
+  if (mFD >= 0) {
+    if (ftruncate(mFD, 0) != 0) {
+      ALOGE("Unable to truncate the file.\n");
+    }
+  }
+}
+
+
+} // namespace bcc
diff --git a/lib/ExecutionEngine/FileHandle.h b/lib/ExecutionEngine/FileHandle.h
new file mode 100644
index 0000000..02dbe31
--- /dev/null
+++ b/lib/ExecutionEngine/FileHandle.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BCC_FILEHANDLE_H
+#define BCC_FILEHANDLE_H
+
+#include <sys/types.h>
+
+#include <stddef.h>
+#include <stdint.h>
+
+namespace bcc {
+  namespace OpenMode {
+    enum ModeType {
+      Read = 0,
+      Write = 1,
+    };
+  }
+
+  class FileHandle {
+  private:
+    int mFD;
+
+  public:
+    FileHandle() : mFD(-1) {
+    }
+
+    ~FileHandle() {
+      if (mFD >= 0) {
+        close();
+      }
+    }
+
+    int open(char const *filename, OpenMode::ModeType mode);
+
+    void close();
+
+    int getFD() {
+      // Note: This function is designed not being qualified by const.
+      // Because once the file descriptor is given, the user can do every
+      // thing on file descriptor.
+
+      return mFD;
+    }
+
+    off_t seek(off_t offset, int whence);
+
+    ssize_t read(char *buf, size_t count);
+
+    ssize_t write(char const *buf, size_t count);
+
+    void truncate();
+
+  };
+
+} // namespace bcc
+
+#endif // BCC_FILEHANDLE_H
diff --git a/lib/ExecutionEngine/FileMutex.h b/lib/ExecutionEngine/FileMutex.h
deleted file mode 100644
index 85c0e84..0000000
--- a/lib/ExecutionEngine/FileMutex.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef BCC_EXECUTION_ENGINE_FILE_MUTEX_H
-#define BCC_EXECUTION_ENGINE_FILE_MUTEX_H
-
-#include <string>
-
-#include "FileBase.h"
-
-namespace bcc {
-
-template<enum FileBase::LockModeEnum LockMode>
-class FileMutex : public FileBase {
-public:
-  FileMutex(const std::string &pFileToLock)
-    : FileBase(pFileToLock + ".lock", O_RDONLY | O_CREAT, 0) { }
-
-  // Provide a lock() interface filled with default configuration.
-  inline bool lock(bool pNonblocking = true,
-                   unsigned pMaxRetry = FileBase::kDefaultMaxRetryLock,
-                   useconds_t pRetryInterval =
-                       FileBase::kDefaultRetryLockInterval) {
-    return FileBase::lock(LockMode, pNonblocking, pMaxRetry, pRetryInterval);
-  }
-};
-
-} // namespace bcc
-
-#endif  // BCC_EXECUTION_ENGINE_FILE_MUTEX_H
diff --git a/lib/ExecutionEngine/InputFile.cpp b/lib/ExecutionEngine/InputFile.cpp
deleted file mode 100644
index a51b09e..0000000
--- a/lib/ExecutionEngine/InputFile.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2012, 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 "InputFile.h"
-
-#include "DebugHelper.h"
-
-using namespace bcc;
-
-InputFile::InputFile(const std::string &pFilename, unsigned pFlags)
-  : super(pFilename, pFlags) { }
-
-ssize_t InputFile::read(void *pBuf, size_t count) {
-  if ((mFD < 0) || hasError()) {
-    return -1;
-  }
-
-  if ((count <= 0) || (pBuf == NULL)) {
-    // Keep safe and issue a warning.
-    ALOGW("InputFile::read: count = %zu, buffer = %p", count, pBuf);
-    return 0;
-  }
-
-  while (count > 0) {
-    ssize_t read_size = ::read(mFD, pBuf, count);
-
-    if (read_size >= 0) {
-      return read_size;
-    } else if ((errno == EAGAIN) || (errno == EINTR)) {
-      // If the errno is EAGAIN or EINTR, then we try to read again.
-      //
-      // Fall-through
-    } else {
-      detectError();
-      return -1;
-    }
-  }
-  // unreachable
-  return 0;
-}
diff --git a/lib/ExecutionEngine/InputFile.h b/lib/ExecutionEngine/InputFile.h
deleted file mode 100644
index a7c22d2..0000000
--- a/lib/ExecutionEngine/InputFile.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef BCC_EXECUTION_ENGINE_INPUT_FILE_H
-#define BCC_EXECUTION_ENGINE_INPUT_FILE_H
-
-#include "File.h"
-#include "FileBase.h"
-
-namespace bcc {
-
-class InputFile : public File<FileBase::kReadMode> {
-  typedef File<FileBase::kReadMode> super;
-public:
-  InputFile(const std::string &pFilename, unsigned pFlags = 0);
-
-  ssize_t read(void *pBuf, size_t count);
-};
-
-} // end namespace bcc
-
-#endif  // BCC_EXECUTION_ENGINE_INPUT_FILE_H
diff --git a/lib/ExecutionEngine/MCCacheReader.cpp b/lib/ExecutionEngine/MCCacheReader.cpp
index 0a70ff6..bf4fe47 100644
--- a/lib/ExecutionEngine/MCCacheReader.cpp
+++ b/lib/ExecutionEngine/MCCacheReader.cpp
@@ -17,7 +17,7 @@
 #include "MCCacheReader.h"
 
 #include "DebugHelper.h"
-#include "InputFile.h"
+#include "FileHandle.h"
 #include "ScriptCached.h"
 #include "Runtime.h"
 
@@ -49,8 +49,8 @@
   if (mpFuncNameList) { free(mpFuncNameList); }
 }
 
-ScriptCached *MCCacheReader::readCacheFile(InputFile &objFile,
-                                           InputFile &infoFile,
+ScriptCached *MCCacheReader::readCacheFile(FileHandle *objFile,
+                                           FileHandle *infoFile,
                                            Script *S) {
   bool result = checkCacheFile(objFile, infoFile, S)
              && readPragmaList()
@@ -65,16 +65,16 @@
   return result ? mpResult.take() : NULL;
 }
 
-bool MCCacheReader::checkCacheFile(InputFile &objFile,
-                                   InputFile &infoFile,
-                                   Script *S) {
+bool MCCacheReader::checkCacheFile(FileHandle *objFile,
+                                            FileHandle *infoFile,
+                                            Script *S) {
   // Check file handle
-  if (objFile.hasError() || infoFile.hasError()) {
+  if (!objFile || objFile->getFD() < 0 || !infoFile || infoFile->getFD() < 0) {
     return false;
   }
 
-  mObjFile = &objFile;
-  mInfoFile = &infoFile;
+  mObjFile = objFile;
+  mInfoFile = infoFile;
 
   // Allocate ScriptCached object
   mpResult.reset(new (nothrow) ScriptCached(S));
@@ -101,7 +101,7 @@
 
 bool MCCacheReader::checkFileSize() {
   struct stat stfile;
-  if (::stat(mInfoFile->getName().c_str(), &stfile) < 0) {
+  if (fstat(mInfoFile->getFD(), &stfile) < 0) {
     ALOGE("Unable to stat cache file.\n");
     return false;
   }
@@ -118,7 +118,7 @@
 
 
 bool MCCacheReader::readHeader() {
-  if (mInfoFile->seek(0) != 0) {
+  if (mInfoFile->seek(0, SEEK_SET) != 0) {
     ALOGE("Unable to seek to 0. (reason: %s)\n", strerror(errno));
     return false;
   }
@@ -226,7 +226,7 @@
   /* We have to ensure that some one will deallocate NAME##_raw */          \
   AUTO_MANAGED_HOLDER = NAME##_raw;                                         \
                                                                             \
-  if (mInfoFile->seek(mpHeader->NAME##_offset) == -1) {                     \
+  if (mInfoFile->seek(mpHeader->NAME##_offset, SEEK_SET) == -1) {           \
     ALOGE("Unable to seek to " #NAME " section\n");                          \
     return false;                                                           \
   }                                                                         \
diff --git a/lib/ExecutionEngine/MCCacheReader.h b/lib/ExecutionEngine/MCCacheReader.h
index 972f0c8..df4aca3 100644
--- a/lib/ExecutionEngine/MCCacheReader.h
+++ b/lib/ExecutionEngine/MCCacheReader.h
@@ -31,12 +31,12 @@
 struct MCO_Header;
 
 namespace bcc {
+  class FileHandle;
   class Script;
-  class InputFile;
 
   class MCCacheReader {
   private:
-    InputFile *mObjFile, *mInfoFile;
+    FileHandle *mObjFile, *mInfoFile;
     off_t mInfoFileSize;
 
     MCO_Header *mpHeader;
@@ -75,8 +75,8 @@
                            std::make_pair((uint32_t)resType, sha1)));
     }
 
-    ScriptCached *readCacheFile(InputFile &objFile, InputFile &infoFile, Script *s);
-    bool checkCacheFile(InputFile &objFile, InputFile &infoFile, Script *S);
+    ScriptCached *readCacheFile(FileHandle *objFile, FileHandle *infoFile, Script *s);
+    bool checkCacheFile(FileHandle *objFile, FileHandle *infoFile, Script *S);
 
     bool isContextSlotNotAvail() const {
       return mIsContextSlotNotAvail;
diff --git a/lib/ExecutionEngine/MCCacheWriter.cpp b/lib/ExecutionEngine/MCCacheWriter.cpp
index 7809234..b113ad9 100644
--- a/lib/ExecutionEngine/MCCacheWriter.cpp
+++ b/lib/ExecutionEngine/MCCacheWriter.cpp
@@ -17,7 +17,7 @@
 #include "MCCacheWriter.h"
 
 #include "DebugHelper.h"
-#include "OutputFile.h"
+#include "FileHandle.h"
 #include "RSScript.h"
 
 #include <map>
@@ -47,14 +47,14 @@
 #undef CHECK_AND_FREE
 }
 
-bool MCCacheWriter::writeCacheFile(OutputFile &objFile, OutputFile &infoFile,
+bool MCCacheWriter::writeCacheFile(FileHandle *objFile, FileHandle *infoFile,
                                    RSScript *S, uint32_t libRS_threadable) {
-  if (objFile.hasError() || infoFile.hasError()) {
+  if (!objFile || objFile->getFD() < 0 || !infoFile || infoFile->getFD() < 0) {
     return false;
   }
 
-  mObjFile = &objFile;
-  mInfoFile = &infoFile;
+  mObjFile = objFile;
+  mInfoFile = infoFile;
   mpOwner = S;
 
   bool result = prepareHeader(libRS_threadable)
@@ -343,14 +343,14 @@
 bool MCCacheWriter::writeAll() {
 #define WRITE_SECTION(NAME, OFFSET, SIZE, SECTION)                          \
   do {                                                                      \
-    if (mInfoFile->seek(OFFSET) == -1) {                                    \
-      ALOGE("Unable to seek to " #NAME " section for writing.\n");          \
+    if (mInfoFile->seek(OFFSET, SEEK_SET) == -1) {                          \
+      ALOGE("Unable to seek to " #NAME " section for writing.\n");           \
       return false;                                                         \
     }                                                                       \
                                                                             \
     if (mInfoFile->write(reinterpret_cast<char *>(SECTION), (SIZE)) !=      \
         static_cast<ssize_t>(SIZE)) {                                       \
-      ALOGE("Unable to write " #NAME " section to cache file.\n");          \
+      ALOGE("Unable to write " #NAME " section to cache file.\n");           \
       return false;                                                         \
     }                                                                       \
   } while (0)
diff --git a/lib/ExecutionEngine/MCCacheWriter.h b/lib/ExecutionEngine/MCCacheWriter.h
index 1f462b3..7fa5cf5 100644
--- a/lib/ExecutionEngine/MCCacheWriter.h
+++ b/lib/ExecutionEngine/MCCacheWriter.h
@@ -19,20 +19,21 @@
 
 #include <bcc/bcc_mccache.h>
 
+#include "FileHandle.h"
+
 #include <map>
 #include <string>
 #include <utility>
 #include <vector>
 
 namespace bcc {
-  class OutputFile;
   class RSScript;
 
   class MCCacheWriter {
   private:
     RSScript *mpOwner;
 
-    OutputFile *mObjFile, *mInfoFile;
+    FileHandle *mObjFile, *mInfoFile;
 
     std::vector<std::pair<char const *, size_t> > mStringPool;
 
@@ -62,7 +63,7 @@
 
     ~MCCacheWriter();
 
-    bool writeCacheFile(OutputFile &objFile, OutputFile &infoFile,
+    bool writeCacheFile(FileHandle *objFile, FileHandle *infoFile,
                         RSScript *S, uint32_t libRS_threadable);
 
     void addDependency(MCO_ResourceType resType,
diff --git a/lib/ExecutionEngine/OutputFile.cpp b/lib/ExecutionEngine/OutputFile.cpp
deleted file mode 100644
index 6200617..0000000
--- a/lib/ExecutionEngine/OutputFile.cpp
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright 2012, 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 "OutputFile.h"
-
-#include <cstdlib>
-
-#include <llvm/Support/raw_ostream.h>
-
-#include "DebugHelper.h"
-
-using namespace bcc;
-
-OutputFile *OutputFile::CreateTemporary(const std::string &pFileTemplate,
-                                        unsigned pFlags) {
-  char *tmp_filename = NULL;
-  int tmp_fd;
-  OutputFile *result = NULL;
-
-  // Allocate memory to hold the generated unique temporary filename.
-  tmp_filename =
-      new (std::nothrow) char [ pFileTemplate.length() + /* .XXXXXX */7 + 1 ];
-  if (tmp_filename == NULL) {
-    ALOGE("Out of memory when allocates memory for filename %s in "
-          "OutputFile::CreateTemporary()!", pFileTemplate.c_str());
-    return NULL;
-  }
-
-  // Construct filename template for mkstemp().
-  if (pFileTemplate.length() > 0)
-    ::memcpy(tmp_filename, pFileTemplate.c_str(), pFileTemplate.length());
-  ::strncpy(tmp_filename + pFileTemplate.length(), ".XXXXXX", 7);
-
-  // POSIX mkstemp() never returns EINTR.
-  tmp_fd = ::mkstemp(tmp_filename);
-  if (tmp_fd < 0) {
-    llvm::error_code err(errno, llvm::posix_category());
-    ALOGE("Failed to create temporary file using mkstemp() for %s! (%s)",
-          tmp_filename, err.message().c_str());
-    delete [] tmp_filename;
-    return NULL;
-  }
-
-  // Create result OutputFile.
-  result = new (std::nothrow) OutputFile(tmp_filename, pFlags);
-  if (result == NULL) {
-    ALOGE("Out of memory when creates OutputFile for %s!", tmp_filename);
-    // Fall through to the clean-up codes.
-  } else {
-    if (result->hasError()) {
-      ALOGE("Failed to open temporary output file %s! (%s)",
-            result->getName().c_str(), result->getErrorMessage().c_str());
-      delete result;
-      result = NULL;
-      // Fall through to the clean-up codes.
-    }
-  }
-
-  // Clean up.
-  delete [] tmp_filename;
-  ::close(tmp_fd);
-
-  return result;
-}
-
-OutputFile::OutputFile(const std::string &pFilename, unsigned pFlags)
-  : super(pFilename, pFlags) { }
-
-ssize_t OutputFile::write(const void *pBuf, size_t count) {
-  if ((mFD < 0) || hasError()) {
-    return -1;
-  }
-
-  if ((count <= 0) || (pBuf == NULL)) {
-    // Keep safe and issue a warning.
-    ALOGW("OutputFile::write: count = %zu, buffer = %p", count, pBuf);
-    return 0;
-  }
-
-  while (count > 0) {
-    ssize_t write_size = ::write(mFD, pBuf, count);
-
-    if (write_size > 0) {
-      return write_size;
-    } else if ((errno == EAGAIN) || (errno == EINTR)) {
-      // If the errno is EAGAIN or EINTR, then we try to write again.
-      //
-      // Fall-through
-    } else {
-      detectError();
-      return -1;
-    }
-  }
-  // unreachable
-  return 0;
-}
-
-void OutputFile::truncate() {
-  if (mFD < 0) {
-    return;
-  }
-
-  do {
-    if (::ftruncate(mFD, 0) == 0) {
-      return;
-    }
-  } while (errno == EINTR);
-  detectError();
-
-  return;
-}
-
-llvm::raw_fd_ostream *OutputFile::dup() {
-  int newfd;
-
-  do {
-    newfd = ::dup(mFD);
-    if (newfd < 0) {
-      if (errno != EINTR) {
-        detectError();
-        return NULL;
-      }
-      // EINTR
-      continue;
-    }
-    // dup() returns ok.
-    break;
-  } while (true);
-
-  llvm::raw_fd_ostream *result =
-      new (std::nothrow) llvm::raw_fd_ostream(newfd, /* shouldClose */true);
-
-  if (result == NULL) {
-    mError.assign(llvm::errc::not_enough_memory, llvm::system_category());
-  }
-
-  return result;
-}
diff --git a/lib/ExecutionEngine/OutputFile.h b/lib/ExecutionEngine/OutputFile.h
deleted file mode 100644
index 4de8863..0000000
--- a/lib/ExecutionEngine/OutputFile.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef BCC_EXECUTION_ENGINE_OUTPUT_FILE_H
-#define BCC_EXECUTION_ENGINE_OUTPUT_FILE_H
-
-#include "File.h"
-#include "FileBase.h"
-
-namespace llvm {
-  class raw_fd_ostream;
-}
-
-namespace bcc {
-
-class OutputFile : public File<FileBase::kWriteMode> {
-  typedef File<FileBase::kWriteMode> super;
-public:
-  // Generate a unique temporary filename from pFileTemplate and open it in
-  // an OutputFile returned. The filename will be pFileTemplate with
-  // a dot ('.') plus six random characters appended. Return NULL on error.
-  static OutputFile *CreateTemporary(const std::string &pFileTemplate,
-                                     unsigned pFlags);
-
-  OutputFile(const std::string &pFilename, unsigned pFlags = 0);
-
-  ssize_t write(const void *pBuf, size_t count);
-
-  void truncate();
-
-  // This is similar to the system call dup(). It creates a copy of the file
-  // descriptor it contains and wrap it in llvm::raw_fd_ostream object. It
-  // returns a non-NULL object if everything goes well and user should later
-  // use delete operator to destroy it by itself.
-  llvm::raw_fd_ostream *dup();
-};
-
-} // end namespace bcc
-
-#endif  // BCC_EXECUTION_ENGINE_OUTPUT_FILE_H
diff --git a/lib/ExecutionEngine/RSScript.cpp b/lib/ExecutionEngine/RSScript.cpp
index d223eee..af37ab6 100644
--- a/lib/ExecutionEngine/RSScript.cpp
+++ b/lib/ExecutionEngine/RSScript.cpp
@@ -35,10 +35,8 @@
 #include "CompilerOption.h"
 
 #include "DebugHelper.h"
-#include "FileMutex.h"
+#include "FileHandle.h"
 #include "GDBJITRegistrar.h"
-#include "InputFile.h"
-#include "OutputFile.h"
 #include "ScriptCompiled.h"
 #include "ScriptCached.h"
 #include "Sha1Helper.h"
@@ -101,6 +99,7 @@
   return;
 }
 
+
 bool RSScript::doReset() {
   resetState();
   return true;
@@ -134,10 +133,9 @@
     return status;
   }
 
-  OutputFile objFile(objPath);
-  if (objFile.hasError()) {
-    ALOGE("Failed to open %s for write. (%s)", objPath,
-          objFile.getErrorMessage().c_str());
+  FileHandle objFile;
+  if (objFile.open(objPath, OpenMode::Write) < 1) {
+    ALOGE("Failed to open %s for write.\n", objPath);
     return 1;
   }
 
@@ -220,37 +218,15 @@
   std::string objPath = getCachedObjectPath();
   std::string infoPath = getCacheInfoPath();
 
-  // Locks for reading object file and info file.
-  FileMutex<FileBase::kReadLock> objFileMutex(objPath);
-  FileMutex<FileBase::kReadLock> infoFileMutex(infoPath);
-
-  // Aquire read lock for object file.
-  if (objFileMutex.hasError() || !objFileMutex.lock()) {
-    ALOGE("Unable to acquire the lock for %s! (%s)", objPath.c_str(),
-          objFileMutex.getErrorMessage().c_str());
+  FileHandle objFile;
+  if (objFile.open(objPath.c_str(), OpenMode::Read) < 0) {
+    // Unable to open the executable file in read mode.
     return 1;
   }
 
-  // Aquire read lock for info file.
-  if (infoFileMutex.hasError() || !infoFileMutex.lock()) {
-    ALOGE("Unable to acquire the lock for %s! (%s)", infoPath.c_str(),
-          infoFileMutex.getErrorMessage().c_str());
-    return 1;
-  }
-
-  // Open the object file and info file
-  InputFile objFile(objPath);
-  InputFile infoFile(infoPath);
-
-  if (objFile.hasError()) {
-    ALOGE("Unable to open %s for reading! (%s)", objPath.c_str(),
-          objFile.getErrorMessage().c_str());
-    return 1;
-  }
-
-  if (infoFile.hasError()) {
-    ALOGE("Unable to open %s for reading! (%s)", infoPath.c_str(),
-          infoFile.getErrorMessage().c_str());
+  FileHandle infoFile;
+  if (infoFile.open(infoPath.c_str(), OpenMode::Read) < 0) {
+    // Unable to open the metadata information file in read mode.
     return 1;
   }
 
@@ -274,10 +250,10 @@
   }
 
   if (checkOnly)
-    return !reader.checkCacheFile(objFile, infoFile, this);
+    return !reader.checkCacheFile(&objFile, &infoFile, this);
 
   // Read cache file
-  ScriptCached *cached = reader.readCacheFile(objFile, infoFile, this);
+  ScriptCached *cached = reader.readCacheFile(&objFile, &infoFile, this);
 
   if (!cached) {
     mIsContextSlotNotAvail = reader.isContextSlotNotAvail();
@@ -342,92 +318,72 @@
   // we don't have to cache it.
 
   if (isCacheable()) {
+
     std::string objPath = getCachedObjectPath();
     std::string infoPath = getCacheInfoPath();
 
-    // Locks for writing object file and info file.
-    FileMutex<FileBase::kWriteLock> objFileMutex(objPath);
-    FileMutex<FileBase::kWriteLock> infoFileMutex(infoPath);
+    // Remove the file if it already exists before writing the new file.
+    // The old file may still be mapped elsewhere in memory and we do not want
+    // to modify its contents.  (The same script may be running concurrently in
+    // the same process or a different process!)
+    ::unlink(objPath.c_str());
+    ::unlink(infoPath.c_str());
 
-    // Aquire write lock for object file.
-    if (objFileMutex.hasError() || !objFileMutex.lock()) {
-      ALOGE("Unable to acquire the lock for %s! (%s)", objPath.c_str(),
-            objFileMutex.getErrorMessage().c_str());
-      return 1;
-    }
+    FileHandle objFile;
+    FileHandle infoFile;
 
-    // Aquire write lock for info file.
-    if (infoFileMutex.hasError() || !infoFileMutex.lock()) {
-      ALOGE("Unable to acquire the lock for %s! (%s)", infoPath.c_str(),
-            infoFileMutex.getErrorMessage().c_str());
-      return 1;
-    }
+    if (objFile.open(objPath.c_str(), OpenMode::Write) >= 0 &&
+        infoFile.open(infoPath.c_str(), OpenMode::Write) >= 0) {
 
-    // Open the object file and info file
-    OutputFile objFile(objPath);
-    OutputFile infoFile(infoPath);
-
-    if (objFile.hasError()) {
-      ALOGE("Unable to open %s for writing! (%s)", objPath.c_str(),
-            objFile.getErrorMessage().c_str());
-      return 1;
-    }
-
-    if (infoFile.hasError()) {
-      ALOGE("Unable to open %s for writing! (%s)", infoPath.c_str(),
-            infoFile.getErrorMessage().c_str());
-      return 1;
-    }
-
-    MCCacheWriter writer;
+      MCCacheWriter writer;
 
 #ifdef TARGET_BUILD
-    // Dependencies
-    writer.addDependency(BCC_FILE_RESOURCE, pathLibBCC_SHA1, sha1LibBCC_SHA1);
-    writer.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
+      // Dependencies
+      writer.addDependency(BCC_FILE_RESOURCE, pathLibBCC_SHA1, sha1LibBCC_SHA1);
+      writer.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
 #endif
 
-    for (unsigned i = 0; i < mSourceDependencies.size(); i++) {
-      const SourceDependency *source_dep = mSourceDependencies[i];
-      writer.addDependency(source_dep->getSourceType(),
-                           source_dep->getSourceName(),
-                           source_dep->getSHA1Checksum());
-    }
-
-
-    // libRS is threadable dirty hack
-    // TODO: This should be removed in the future
-    uint32_t libRS_threadable = 0;
-    if (mpExtSymbolLookupFn) {
-      libRS_threadable =
-        (uint32_t)mpExtSymbolLookupFn(mpExtSymbolLookupFnContext,
-                                      "__isThreadable");
-    }
-
-    if (!writer.writeCacheFile(objFile, infoFile, this, libRS_threadable)) {
-      // Erase the file contents.
-      objFile.truncate();
-      infoFile.truncate();
-
-      // Close the file such that we can removed it from the filesystem.
-      objFile.close();
-      infoFile.close();
-
-      if (::unlink(objPath.c_str()) != 0) {
-        ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
-             objPath.c_str(), ::strerror(errno));
+      for (unsigned i = 0; i < mSourceDependencies.size(); i++) {
+        const SourceDependency *source_dep = mSourceDependencies[i];
+        writer.addDependency(source_dep->getSourceType(),
+                             source_dep->getSourceName(),
+                             source_dep->getSHA1Checksum());
       }
 
-      if (::unlink(infoPath.c_str()) != 0) {
-        ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
-             infoPath.c_str(), ::strerror(errno));
+
+      // libRS is threadable dirty hack
+      // TODO: This should be removed in the future
+      uint32_t libRS_threadable = 0;
+      if (mpExtSymbolLookupFn) {
+        libRS_threadable =
+          (uint32_t)mpExtSymbolLookupFn(mpExtSymbolLookupFnContext,
+                                        "__isThreadable");
+      }
+
+      if (!writer.writeCacheFile(&objFile, &infoFile, this, libRS_threadable)) {
+        objFile.truncate();
+        objFile.close();
+
+        if (unlink(objPath.c_str()) != 0) {
+          ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
+               objPath.c_str(), strerror(errno));
+        }
+
+        infoFile.truncate();
+        infoFile.close();
+
+        if (unlink(infoPath.c_str()) != 0) {
+          ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
+               infoPath.c_str(), strerror(errno));
+        }
       }
     }
-  } // isCacheable()
+  }
 
   return 0;
 }
 
+
 char const *RSScript::getCompilerErrorMessage() {
   if (mStatus != ScriptStatus::Compiled) {
     mErrorCode = BCC_INVALID_OPERATION;
diff --git a/lib/ExecutionEngine/Sha1Helper.cpp b/lib/ExecutionEngine/Sha1Helper.cpp
index 07a995f..0acd6b8 100644
--- a/lib/ExecutionEngine/Sha1Helper.cpp
+++ b/lib/ExecutionEngine/Sha1Helper.cpp
@@ -19,7 +19,7 @@
 #include "Config.h"
 
 #include "DebugHelper.h"
-#include "InputFile.h"
+#include "FileHandle.h"
 
 #include <string.h>
 
@@ -50,11 +50,10 @@
 void calcFileSHA1(unsigned char *result, char const *filename) {
   android::StopWatch calcFileSHA1Timer("calcFileSHA1 time");
 
-  InputFile file(filename);
+  FileHandle file;
 
-  if (file.hasError()) {
-    ALOGE("Unable to open the file %s before SHA-1 checksum "
-          "calculation! (%s)", filename, file.getErrorMessage().c_str());
+  if (file.open(filename, OpenMode::Read) < 0) {
+    ALOGE("Unable to calculate the sha1 checksum of %s\n", filename);
     memset(result, '\0', 20);
     return;
   }
@@ -84,10 +83,9 @@
 }
 
 void readSHA1(unsigned char *result, int result_size, char const *filename) {
-  InputFile file(filename);
-  if (file.hasError()) {
-    ALOGE("Unable to open the binary sha1 file %s! (%s)", filename,
-          file.getErrorMessage().c_str());
+  FileHandle file;
+  if (file.open(filename, OpenMode::Read) < 0) {
+    ALOGE("Unable to read binary sha1 file %s\n", filename);
     memset(result, '\0', result_size);
     return;
   }