Home | History | Annotate | Download | only in Support
      1 //===- FileHandle.cpp -----------------------------------------------------===//
      2 //
      3 //                     The MCLinker Project
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 #include "mcld/Config/Config.h"
     10 #include "mcld/Support/FileHandle.h"
     11 #include "mcld/Support/FileSystem.h"
     12 
     13 #include <errno.h>
     14 
     15 #if defined(HAVE_UNISTD_H)
     16 #include <unistd.h>
     17 #endif
     18 #if defined(HAVE_FCNTL_H)
     19 #include <fcntl.h>
     20 #endif
     21 
     22 #include <sys/stat.h>
     23 
     24 namespace mcld {
     25 
     26 //===----------------------------------------------------------------------===//
     27 // FileHandle
     28 //===----------------------------------------------------------------------===//
     29 FileHandle::FileHandle()
     30     : m_Path(),
     31       m_Handler(-1),
     32       m_Size(0),
     33       m_State(GoodBit),
     34       m_OpenMode(NotOpen) {
     35 }
     36 
     37 FileHandle::~FileHandle() {
     38   if (isOpened())
     39     close();
     40 }
     41 
     42 inline static int oflag(FileHandle::OpenMode pMode) {
     43   int result = 0x0;
     44   if (FileHandle::Unknown == pMode)
     45     return result;
     46 
     47   if (FileHandle::ReadWrite == (pMode & FileHandle::ReadWrite))
     48     result |= O_RDWR;
     49   else if (FileHandle::ReadOnly == (pMode & FileHandle::ReadOnly))
     50     result |= O_RDONLY;
     51   else if (FileHandle::WriteOnly == (pMode & FileHandle::WriteOnly))
     52     result |= O_WRONLY;
     53 
     54   if (FileHandle::Append == (pMode & FileHandle::Append))
     55     result |= O_APPEND;
     56 
     57   if (FileHandle::Create == (pMode & FileHandle::Create))
     58     result |= O_CREAT;
     59 
     60   if (FileHandle::Truncate == (pMode & FileHandle::Truncate))
     61     result |= O_TRUNC;
     62 
     63   return result;
     64 }
     65 
     66 inline static bool get_size(int pHandler, unsigned int& pSize) {
     67   struct ::stat file_stat;
     68   if (-1 == ::fstat(pHandler, &file_stat)) {
     69     pSize = 0;
     70     return false;
     71   }
     72   pSize = file_stat.st_size;
     73   return true;
     74 }
     75 
     76 bool FileHandle::open(const sys::fs::Path& pPath,
     77                       FileHandle::OpenMode pMode,
     78                       FileHandle::Permission pPerm) {
     79   if (isOpened() || Unknown == pMode) {
     80     setState(BadBit);
     81     return false;
     82   }
     83 
     84   m_OpenMode = pMode;
     85   if (System == pPerm)
     86     m_Handler = sys::fs::detail::open(pPath, oflag(pMode));
     87   else
     88     m_Handler = sys::fs::detail::open(pPath, oflag(pMode),
     89                                       static_cast<int>(pPerm));
     90 
     91   m_Path = pPath;
     92   if (m_Handler == -1) {
     93     m_OpenMode = OpenMode(NotOpen);
     94     setState(FailBit);
     95     return false;
     96   }
     97 
     98   if (!get_size(m_Handler, m_Size)) {
     99     setState(FailBit);
    100     return false;
    101   }
    102 
    103   return true;
    104 }
    105 
    106 bool FileHandle::delegate(int pFD, FileHandle::OpenModeEnum pMode) {
    107   if (isOpened()) {
    108     setState(BadBit);
    109     return false;
    110   }
    111 
    112   m_Handler = pFD;
    113   m_OpenMode = OpenMode(pMode);
    114   m_State = (GoodBit | DeputedBit);
    115 
    116   if (!get_size(m_Handler, m_Size)) {
    117     setState(FailBit);
    118     return false;
    119   }
    120 
    121   return true;
    122 }
    123 
    124 bool FileHandle::close() {
    125   if (!isOpened()) {
    126     setState(BadBit);
    127     return false;
    128   }
    129 
    130   if (isOwned()) {
    131     if (::close(m_Handler) == -1) {
    132       setState(FailBit);
    133       return false;
    134     }
    135   }
    136 
    137   m_Path.native().clear();
    138   m_Size = 0;
    139   m_OpenMode = OpenMode(NotOpen);
    140   cleanState();
    141   return true;
    142 }
    143 
    144 bool FileHandle::truncate(size_t pSize) {
    145   if (!isOpened() || !isWritable()) {
    146     setState(BadBit);
    147     return false;
    148   }
    149 
    150   if (sys::fs::detail::ftruncate(m_Handler, pSize) == -1) {
    151     setState(FailBit);
    152     return false;
    153   }
    154 
    155   m_Size = pSize;
    156   return true;
    157 }
    158 
    159 bool FileHandle::read(void* pMemBuffer, size_t pStartOffset, size_t pLength) {
    160   if (!isOpened() || !isReadable()) {
    161     setState(BadBit);
    162     return false;
    163   }
    164 
    165   if (pLength == 0)
    166     return true;
    167 
    168   ssize_t read_bytes =
    169       sys::fs::detail::pread(m_Handler, pMemBuffer, pLength, pStartOffset);
    170 
    171   if (read_bytes == -1) {
    172     setState(FailBit);
    173     return false;
    174   }
    175 
    176   return true;
    177 }
    178 
    179 bool FileHandle::write(const void* pMemBuffer,
    180                        size_t pStartOffset,
    181                        size_t pLength) {
    182   if (!isOpened() || !isWritable()) {
    183     setState(BadBit);
    184     return false;
    185   }
    186 
    187   if (pLength == 0)
    188     return true;
    189 
    190   ssize_t write_bytes =
    191       sys::fs::detail::pwrite(m_Handler, pMemBuffer, pLength, pStartOffset);
    192 
    193   if (write_bytes == -1) {
    194     setState(FailBit);
    195     return false;
    196   }
    197 
    198   return true;
    199 }
    200 
    201 void FileHandle::setState(FileHandle::IOState pState) {
    202   m_State |= pState;
    203 }
    204 
    205 void FileHandle::cleanState(FileHandle::IOState pState) {
    206   m_State = pState;
    207 }
    208 
    209 bool FileHandle::isOpened() const {
    210   if (m_Handler != -1 && m_OpenMode != NotOpen && isGood())
    211     return true;
    212 
    213   return false;
    214 }
    215 
    216 // Assume Unknown OpenMode is readable
    217 bool FileHandle::isReadable() const {
    218   return (m_OpenMode & ReadOnly);
    219 }
    220 
    221 // Assume Unknown OpenMode is writable
    222 bool FileHandle::isWritable() const {
    223   return (m_OpenMode & WriteOnly);
    224 }
    225 
    226 // Assume Unknown OpenMode is both readable and writable
    227 bool FileHandle::isReadWrite() const {
    228   return (FileHandle::ReadWrite == (m_OpenMode & FileHandle::ReadWrite));
    229 }
    230 
    231 bool FileHandle::isGood() const {
    232   return !(m_State & (BadBit | FailBit));
    233 }
    234 
    235 bool FileHandle::isBad() const {
    236   return (m_State & BadBit);
    237 }
    238 
    239 bool FileHandle::isFailed() const {
    240   return (m_State & (BadBit | FailBit));
    241 }
    242 
    243 bool FileHandle::isOwned() const {
    244   return !(m_State & DeputedBit);
    245 }
    246 
    247 }  // namespace mcld
    248