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