Revert "Make libbcc public."
This reverts commit 80232dd16c0affb2afae01cde6c94abf23ac1ba8.
diff --git a/lib/ExecutionEngine/FileBase.cpp b/lib/ExecutionEngine/FileBase.cpp
new file mode 100644
index 0000000..379406d
--- /dev/null
+++ b/lib/ExecutionEngine/FileBase.cpp
@@ -0,0 +1,279 @@
+/*
+ * 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;
+}