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