1f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//===- PathV3.inc ---------------------------------------------------------===// 2f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// 3f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// The MCLinker Project 4f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// 5f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// This file is distributed under the University of Illinois Open Source 6f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// License. See LICENSE.TXT for details. 7f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// 8f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//===----------------------------------------------------------------------===// 9f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <mcld/Support/Path.h> 10f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <sys/types.h> 11f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <sys/stat.h> 12f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <stack> 13f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 14f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesnamespace mcld{ 15f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesnamespace sys{ 16f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesnamespace fs{ 17f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 18f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//===----------------------------------------------------------------------===// 19f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// mcld::sys::fs::detail 20f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//===----------------------------------------------------------------------===// 21f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesnamespace detail{ 22f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 23f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// return the last charactor being handled. 24f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinessize_t canonicalize(std::string& pathname) 25f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{ 26f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Variable Index // 27f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // SepTable - stack of result separators 28f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // LR(1) Algorithm // 29f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // traverse pPathName 30f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // if we meet '//', '///', '////', ... 31f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // -> ignore it 32f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // -> push current into stack 33f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // -> jump to the next not '/' 34f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // if we meet '/./' 35f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // -> ignore 36f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // -> jump to the next not '/' 37f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // if we meet '/../' 38f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // -> pop previous position of '/' P 39f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // -> erase P+1 to now 40f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // if we meet other else 41f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // -> go go go 42f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // if we meet '/.../', '/..../', ... -> illegal 43f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (pathname.empty()) 44f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return 0; 45f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 46f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines size_t handler = 0; 47f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines std::stack<size_t> slash_stack; 48f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines slash_stack.push(-1); 49f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines while (handler < pathname.size()) { 50f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (separator == pathname[handler]) { // handler = 1st '/' 51f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines size_t next = handler + 1; 52f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (next >= pathname.size()) 53f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return handler; 54f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines switch(pathname[next]) { // next = handler + 1; 55f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case separator: { // '//' 56f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines while (next < pathname.size() && separator == pathname[next]) 57f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ++next; 58f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // next is the last not '/' 59f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pathname.erase(handler, next - handler - 1); 60f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // handler is the first '/' 61f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines slash_stack.push(handler); 62f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 63f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 64f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case '.': { // '/.' 65f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ++next; // next = handler + 2 66f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (next >= pathname.size()) // '/.' 67f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return handler; 68f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines switch (pathname[next]) { 69f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case separator: { // '/./' 70f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pathname.erase(handler, 2); 71f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 72f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 73f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case '.': { // '/..' 74f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ++next; // next = handler + 3; 75f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (next >= pathname.size()) // '/..?' 76f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return handler; 77f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines switch(pathname[next]) { 78f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case separator: { // '/../' 79f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines handler = slash_stack.top(); 80f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines slash_stack.pop(); 81f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pathname.erase(handler+1, next-handler); 82f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (static_cast<size_t>(-1) == handler) { 83f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines slash_stack.push(-1); 84f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines handler = pathname.find_first_of(separator, handler); 85f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 86f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 87f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 88f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case '.': { // '/...', illegal 89f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return handler; 90f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 91f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 92f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines default : { // '/..a' 93f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines slash_stack.push(handler); 94f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines handler = pathname.find_first_of(separator, handler+3); 95f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 96f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 97f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 98f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 99f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 100f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines default : { // '/.a' 101f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines slash_stack.push(handler); 102f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines handler = pathname.find_first_of(separator, handler+2); 103f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 104f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 105f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 106f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 107f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 108f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines default : { // '/a 109f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines slash_stack.push(handler); 110f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines handler = pathname.find_first_of(separator, handler+1); 111f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 112f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 113f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 114f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 115f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines else { 116f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines handler = pathname.find_first_of(separator, handler); 117f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 118f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 119f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return handler; 120f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 121f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 122f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesbool not_found_error(int perrno) 123f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{ 124f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return perrno == ENOENT || perrno == ENOTDIR; 125f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 126f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 127f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid status(const Path& p, FileStatus& pFileStatus) 128f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{ 129f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines struct ::_stat path_stat; 130f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if(::_stat(p.c_str(), &path_stat)!= 0) 131f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines { 132f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if(not_found_error(errno)) 133f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines { 134f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pFileStatus.setType(FileNotFound); 135f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 136f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines else 137f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pFileStatus.setType(StatusError); 138f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 139f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines else if(S_ISDIR(path_stat.st_mode)) 140f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pFileStatus.setType(DirectoryFile); 141f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines else if(S_ISREG(path_stat.st_mode)) 142f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pFileStatus.setType(RegularFile); 143f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines else if(S_ISBLK(path_stat.st_mode)) 144f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pFileStatus.setType(BlockFile); 145f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines else if(S_ISCHR(path_stat.st_mode)) 146f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pFileStatus.setType(CharacterFile); 147f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines else if(S_ISFIFO(path_stat.st_mode)) 148f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pFileStatus.setType(FifoFile); 149f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines else 150f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pFileStatus.setType(TypeUnknown); 151f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 152f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 153f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid symlink_status(const Path& p, FileStatus& pFileStatus) 154f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{ 155f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pFileStatus.setType(FileNotFound); 156f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 157f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 158f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// directory_iterator_increment - increment function implementation 159f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// 160f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// iterator will call this function in two situations: 161f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// 1. All elements have been put into cache, and iterator stays at the end 162f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// of cache. (a real end) 163f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// 2. Some but not all elements had beed put into cache, and we stoped. 164f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// An iterator now is staying at the end of cache. (a temporal end) 165f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesmcld::sys::fs::PathCache::entry_type* bring_one_into_cache(DirIterator& pIter) 166f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{ 167f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines mcld::sys::fs::PathCache::entry_type* entry = 0; 168f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines fs::Path file_filter(pIter.m_pParent->m_Path); 169f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines file_filter.append("*"); 170f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 171f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines WIN32_FIND_DATA FindFileData; 172f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (FindNextFile(reinterpret_cast<HANDLE>(pIter.m_pParent->m_Handler), 173f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines &FindFileData)) { 174f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // read one 175f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines bool exist = false; 176f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines std::string path(pIter.m_pParent->m_Path.native()); 177f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines path += separator; 178f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines path += std::string(FindFileData.cFileName); 179f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines entry = pIter.m_pParent->m_Cache.insert(path, exist); 180f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (!exist) 181f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines entry->setValue(path); 182f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 183f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines else if (ERROR_NO_MORE_FILES == GetLastError()){ 184f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // meet real end 185f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pIter.m_pParent->m_CacheFull = true; 186f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 187f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines else { 188f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines llvm::report_fatal_error(std::string("Can't read directory: ")+ 189f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pIter.m_pParent->path().native()); 190f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 191f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 192f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return entry; 193f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 194f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 195f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} // namespace of detail 196f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} // namespace of fs 197f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} // namespace of sys 198f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} // namespace of mcld 199f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 200