Home | History | Annotate | Download | only in Unix
      1 //===- FileSystem.inc -----------------------------------------------------===//
      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 <string>
     10 #include <sys/types.h>
     11 #include <sys/stat.h>
     12 #include <sys/mman.h>
     13 #include <dirent.h>
     14 #include <unistd.h>
     15 #include <fcntl.h>
     16 #include <mcld/Support/FileHandle.h>
     17 #include <mcld/Support/Directory.h>
     18 #include <llvm/Support/ErrorHandling.h>
     19 
     20 namespace mcld{
     21 namespace sys{
     22 namespace fs{
     23 namespace detail{
     24 
     25 std::string static_library_extension = ".a";
     26 std::string shared_library_extension = ".so";
     27 std::string executable_extension     = "";
     28 std::string relocatable_extension    = ".o";
     29 std::string assembly_extension       = ".s";
     30 std::string bitcode_extension        = ".bc";
     31 
     32 //===----------------------------------------------------------------------===//
     33 // Helper Functions
     34 //===----------------------------------------------------------------------===//
     35 /// read_dir - return true if we read one entry
     36 //  @return value -1: read error
     37 //                 0: read the end
     38 //                 1: success
     39 static int read_dir(intptr_t& pDir, std::string& pOutFilename)
     40 {
     41   errno = 0;
     42   dirent *cur_dir = ::readdir(reinterpret_cast<DIR*>(pDir));
     43   if (0 == cur_dir && 0 != errno)
     44     return -1;
     45 
     46   // idx does not stay at the end, but all elements had beed put into cache.
     47   if (NULL == cur_dir) {
     48     return 0;
     49   }
     50 
     51   llvm::StringRef name(cur_dir->d_name, strlen(cur_dir->d_name));
     52   if ((name.size() == 1 && name[0] == '.') ||
     53       (name.size() == 2 && name[0] == '.' && name[1] == '.'))
     54     return read_dir(pDir, pOutFilename);
     55 
     56   // find a new directory
     57   pOutFilename.append(name.data(), name.size());
     58   return 1;
     59 }
     60 
     61 void open_dir(Directory& pDir)
     62 {
     63   pDir.m_Handler = reinterpret_cast<intptr_t>(opendir(pDir.path().c_str()));
     64   if (0 == pDir.m_Handler) {
     65     errno = 0; // opendir() will set errno if it failed to open directory.
     66     // set cache is full, then Directory::begin() can return end().
     67     pDir.m_CacheFull = true;
     68     return;
     69   }
     70   // read one entry for advance the end element of the cache.
     71   std::string path(pDir.path().native());
     72   switch (read_dir(pDir.m_Handler, path)) {
     73   case 1: {
     74     // find a new directory
     75     bool exist = false;
     76     mcld::sys::fs::PathCache::entry_type* entry = pDir.m_Cache.insert(path, exist);
     77     if (!exist)
     78       entry->setValue(path);
     79     return;
     80   }
     81   case 0:
     82     // FIXME: a warning function
     83     pDir.m_CacheFull = true;
     84     return;
     85   default:
     86   case -1:
     87     llvm::report_fatal_error(std::string("Can't read directory: ")+
     88                              pDir.path().native());
     89   }
     90 }
     91 
     92 void close_dir(Directory& pDir)
     93 {
     94   if (pDir.m_Handler)
     95     closedir(reinterpret_cast<DIR *>(pDir.m_Handler));
     96   pDir.m_Handler = 0;
     97 }
     98 
     99 int open(const Path& pPath, int pOFlag)
    100 {
    101   return ::open(pPath.native().c_str(), pOFlag);
    102 }
    103 
    104 int open(const Path& pPath, int pOFlag, int pPerm)
    105 {
    106   mode_t perm = 0;
    107   if (pPerm & FileHandle::ReadOwner)
    108     perm |= S_IRUSR;
    109   if (pPerm & FileHandle::WriteOwner)
    110     perm |= S_IWUSR;
    111   if (pPerm & FileHandle::ExeOwner)
    112     perm |= S_IXUSR;
    113   if (pPerm & FileHandle::ReadGroup)
    114     perm |= S_IRGRP;
    115   if (pPerm & FileHandle::WriteGroup)
    116     perm |= S_IWGRP;
    117   if (pPerm & FileHandle::ExeGroup)
    118     perm |= S_IXGRP;
    119   if (pPerm & FileHandle::ReadOther)
    120     perm |= S_IROTH;
    121   if (pPerm & FileHandle::WriteOther)
    122     perm |= S_IWOTH;
    123   if (pPerm & FileHandle::ExeOther)
    124     perm |= S_IXOTH;
    125 
    126   return ::open(pPath.native().c_str(), pOFlag, perm);
    127 }
    128 
    129 ssize_t pread(int pFD, void* pBuf, size_t pCount, off_t pOffset)
    130 {
    131   return ::pread(pFD, pBuf, pCount, pOffset);
    132 }
    133 
    134 ssize_t pwrite(int pFD, const void* pBuf, size_t pCount, off_t pOffset)
    135 {
    136   return ::pwrite(pFD, pBuf, pCount, pOffset);
    137 }
    138 
    139 int ftruncate(int pFD, size_t pLength)
    140 {
    141   return ::ftruncate(pFD, pLength);
    142 }
    143 
    144 void get_pwd(Path& pPWD)
    145 {
    146   char* pwd = (char*)malloc(PATH_MAX);
    147   pPWD.assign(getcwd(pwd, PATH_MAX));
    148   free(pwd);
    149 }
    150 
    151 } // namespace of detail
    152 } // namespace of fs
    153 } // namespace of sys
    154 
    155 //===----------------------------------------------------------------------===//
    156 // FileHandler
    157 //===----------------------------------------------------------------------===//
    158 bool FileHandle::mmap(void*& pMemBuffer, size_t pStartOffset, size_t pLength)
    159 {
    160   if (!isOpened()) {
    161     setState(BadBit);
    162     return false;
    163   }
    164 
    165   if (0 == pLength)
    166     return true;
    167 
    168   int prot, flag;
    169   if (isReadable() && !isWritable()) {
    170     // read-only
    171     prot = PROT_READ;
    172     flag = MAP_FILE | MAP_PRIVATE;
    173   }
    174   else if (!isReadable() && isWritable()) {
    175     // write-only
    176     prot = PROT_WRITE;
    177     flag = MAP_FILE | MAP_SHARED;
    178   }
    179   else if (isReadWrite()) {
    180     // read and write
    181     prot = PROT_READ | PROT_WRITE;
    182     flag = MAP_FILE | MAP_SHARED;
    183   }
    184   else {
    185     // can not read/write
    186     setState(BadBit);
    187     return false;
    188   }
    189 
    190   pMemBuffer = ::mmap(NULL, pLength, prot, flag, m_Handler, pStartOffset);
    191 
    192   if (MAP_FAILED == pMemBuffer) {
    193     setState(FailBit);
    194     return false;
    195   }
    196 
    197   return true;
    198 }
    199 
    200 bool FileHandle::munmap(void* pMemBuffer, size_t pLength)
    201 {
    202   if (!isOpened()) {
    203     setState(BadBit);
    204     return false;
    205   }
    206 
    207   if (-1 == ::munmap(pMemBuffer, pLength)) {
    208     setState(FailBit);
    209     return false;
    210   }
    211 
    212   return true;
    213 }
    214 
    215 } // namespace of mcld
    216 
    217