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