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