| //===- FileHandle.cpp -----------------------------------------------------===// |
| // |
| // The MCLinker Project |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| #include "mcld/Config/Config.h" |
| #include "mcld/Support/FileHandle.h" |
| #include "mcld/Support/FileSystem.h" |
| |
| #include <errno.h> |
| |
| #if defined(HAVE_UNISTD_H) |
| #include <unistd.h> |
| #endif |
| #if defined(HAVE_FCNTL_H) |
| #include <fcntl.h> |
| #endif |
| |
| #include <sys/stat.h> |
| |
| namespace mcld { |
| |
| //===----------------------------------------------------------------------===// |
| // FileHandle |
| //===----------------------------------------------------------------------===// |
| FileHandle::FileHandle() |
| : m_Path(), |
| m_Handler(-1), |
| m_Size(0), |
| m_State(GoodBit), |
| m_OpenMode(NotOpen) { |
| } |
| |
| FileHandle::~FileHandle() { |
| if (isOpened()) |
| close(); |
| } |
| |
| inline static int oflag(FileHandle::OpenMode pMode) { |
| int result = 0x0; |
| if (FileHandle::Unknown == pMode) |
| return result; |
| |
| if (FileHandle::ReadWrite == (pMode & FileHandle::ReadWrite)) |
| result |= O_RDWR; |
| else if (FileHandle::ReadOnly == (pMode & FileHandle::ReadOnly)) |
| result |= O_RDONLY; |
| else if (FileHandle::WriteOnly == (pMode & FileHandle::WriteOnly)) |
| result |= O_WRONLY; |
| |
| if (FileHandle::Append == (pMode & FileHandle::Append)) |
| result |= O_APPEND; |
| |
| if (FileHandle::Create == (pMode & FileHandle::Create)) |
| result |= O_CREAT; |
| |
| if (FileHandle::Truncate == (pMode & FileHandle::Truncate)) |
| result |= O_TRUNC; |
| |
| return result; |
| } |
| |
| inline static bool get_size(int pHandler, unsigned int& pSize) { |
| struct ::stat file_stat; |
| if (-1 == ::fstat(pHandler, &file_stat)) { |
| pSize = 0; |
| return false; |
| } |
| pSize = file_stat.st_size; |
| return true; |
| } |
| |
| bool FileHandle::open(const sys::fs::Path& pPath, |
| FileHandle::OpenMode pMode, |
| FileHandle::Permission pPerm) { |
| if (isOpened() || Unknown == pMode) { |
| setState(BadBit); |
| return false; |
| } |
| |
| m_OpenMode = pMode; |
| if (System == pPerm) |
| m_Handler = sys::fs::detail::open(pPath, oflag(pMode)); |
| else |
| m_Handler = sys::fs::detail::open(pPath, oflag(pMode), |
| static_cast<int>(pPerm)); |
| |
| m_Path = pPath; |
| if (m_Handler == -1) { |
| m_OpenMode = OpenMode(NotOpen); |
| setState(FailBit); |
| return false; |
| } |
| |
| if (!get_size(m_Handler, m_Size)) { |
| setState(FailBit); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| bool FileHandle::delegate(int pFD, FileHandle::OpenModeEnum pMode) { |
| if (isOpened()) { |
| setState(BadBit); |
| return false; |
| } |
| |
| m_Handler = pFD; |
| m_OpenMode = OpenMode(pMode); |
| m_State = (GoodBit | DeputedBit); |
| |
| if (!get_size(m_Handler, m_Size)) { |
| setState(FailBit); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| bool FileHandle::close() { |
| if (!isOpened()) { |
| setState(BadBit); |
| return false; |
| } |
| |
| if (isOwned()) { |
| if (::close(m_Handler) == -1) { |
| setState(FailBit); |
| return false; |
| } |
| } |
| |
| m_Path.native().clear(); |
| m_Size = 0; |
| m_OpenMode = OpenMode(NotOpen); |
| cleanState(); |
| return true; |
| } |
| |
| bool FileHandle::truncate(size_t pSize) { |
| if (!isOpened() || !isWritable()) { |
| setState(BadBit); |
| return false; |
| } |
| |
| if (sys::fs::detail::ftruncate(m_Handler, pSize) == -1) { |
| setState(FailBit); |
| return false; |
| } |
| |
| m_Size = pSize; |
| return true; |
| } |
| |
| bool FileHandle::read(void* pMemBuffer, size_t pStartOffset, size_t pLength) { |
| if (!isOpened() || !isReadable()) { |
| setState(BadBit); |
| return false; |
| } |
| |
| if (pLength == 0) |
| return true; |
| |
| ssize_t read_bytes = |
| sys::fs::detail::pread(m_Handler, pMemBuffer, pLength, pStartOffset); |
| |
| if (read_bytes == -1) { |
| setState(FailBit); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| bool FileHandle::write(const void* pMemBuffer, |
| size_t pStartOffset, |
| size_t pLength) { |
| if (!isOpened() || !isWritable()) { |
| setState(BadBit); |
| return false; |
| } |
| |
| if (pLength == 0) |
| return true; |
| |
| ssize_t write_bytes = |
| sys::fs::detail::pwrite(m_Handler, pMemBuffer, pLength, pStartOffset); |
| |
| if (write_bytes == -1) { |
| setState(FailBit); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| void FileHandle::setState(FileHandle::IOState pState) { |
| m_State |= pState; |
| } |
| |
| void FileHandle::cleanState(FileHandle::IOState pState) { |
| m_State = pState; |
| } |
| |
| bool FileHandle::isOpened() const { |
| if (m_Handler != -1 && m_OpenMode != NotOpen && isGood()) |
| return true; |
| |
| return false; |
| } |
| |
| // Assume Unknown OpenMode is readable |
| bool FileHandle::isReadable() const { |
| return (m_OpenMode & ReadOnly); |
| } |
| |
| // Assume Unknown OpenMode is writable |
| bool FileHandle::isWritable() const { |
| return (m_OpenMode & WriteOnly); |
| } |
| |
| // Assume Unknown OpenMode is both readable and writable |
| bool FileHandle::isReadWrite() const { |
| return (FileHandle::ReadWrite == (m_OpenMode & FileHandle::ReadWrite)); |
| } |
| |
| bool FileHandle::isGood() const { |
| return !(m_State & (BadBit | FailBit)); |
| } |
| |
| bool FileHandle::isBad() const { |
| return (m_State & BadBit); |
| } |
| |
| bool FileHandle::isFailed() const { |
| return (m_State & (BadBit | FailBit)); |
| } |
| |
| bool FileHandle::isOwned() const { |
| return !(m_State & DeputedBit); |
| } |
| |
| } // namespace mcld |