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//===----------------------------------------------------------------------===// 937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/Path.h" 1037b74a387bb3993387029859c2d9d051c41c724eStephen Hines 11f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <stack> 12f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include <sys/stat.h> 1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include <sys/types.h> 1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines 1637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld { 1737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace sys { 1837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace fs { 19f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 20f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//===----------------------------------------------------------------------===// 21f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// mcld::sys::fs::detail 22f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//===----------------------------------------------------------------------===// 2337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace detail { 24f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 25f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// return the last charactor being handled. 2637b74a387bb3993387029859c2d9d051c41c724eStephen Hinessize_t canonicalize(std::string& pathname) { 27f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Variable Index // 28f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // SepTable - stack of result separators 29f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // LR(1) Algorithm // 30f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // traverse pPathName 31f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // if we meet '//', '///', '////', ... 32f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // -> ignore it 33f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // -> push current into stack 34f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // -> jump to the next not '/' 35f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // if we meet '/./' 36f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // -> ignore 37f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // -> jump to the next not '/' 38f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // if we meet '/../' 39f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // -> pop previous position of '/' P 40f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // -> erase P+1 to now 41f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // if we meet other else 42f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // -> go go go 43f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // if we meet '/.../', '/..../', ... -> illegal 44f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (pathname.empty()) 45f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return 0; 46f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 47f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines size_t handler = 0; 48f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines std::stack<size_t> slash_stack; 49f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines slash_stack.push(-1); 50f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines while (handler < pathname.size()) { 5137b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (separator == pathname[handler]) { // handler = 1st '/' 52f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines size_t next = handler + 1; 53f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (next >= pathname.size()) 54f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return handler; 5537b74a387bb3993387029859c2d9d051c41c724eStephen Hines switch (pathname[next]) { // next = handler + 1; 5637b74a387bb3993387029859c2d9d051c41c724eStephen Hines case separator: { // '//' 57f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines while (next < pathname.size() && separator == pathname[next]) 58f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ++next; 59f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // next is the last not '/' 60f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pathname.erase(handler, next - handler - 1); 61f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // handler is the first '/' 62f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines slash_stack.push(handler); 63f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 64f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 6537b74a387bb3993387029859c2d9d051c41c724eStephen Hines case '.': { // '/.' 6637b74a387bb3993387029859c2d9d051c41c724eStephen Hines ++next; // next = handler + 2 6737b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (next >= pathname.size()) // '/.' 68f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return handler; 69f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines switch (pathname[next]) { 7037b74a387bb3993387029859c2d9d051c41c724eStephen Hines case separator: { // '/./' 71f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pathname.erase(handler, 2); 72f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 73f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 7437b74a387bb3993387029859c2d9d051c41c724eStephen Hines case '.': { // '/..' 7537b74a387bb3993387029859c2d9d051c41c724eStephen Hines ++next; // next = handler + 3; 7637b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (next >= pathname.size()) // '/..?' 77f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return handler; 7837b74a387bb3993387029859c2d9d051c41c724eStephen Hines switch (pathname[next]) { 7937b74a387bb3993387029859c2d9d051c41c724eStephen Hines case separator: { // '/../' 80f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines handler = slash_stack.top(); 81f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines slash_stack.pop(); 8237b74a387bb3993387029859c2d9d051c41c724eStephen Hines pathname.erase(handler + 1, next - handler); 83f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (static_cast<size_t>(-1) == handler) { 84f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines slash_stack.push(-1); 85f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines handler = pathname.find_first_of(separator, handler); 86f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 87f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 88f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 8937b74a387bb3993387029859c2d9d051c41c724eStephen Hines case '.': { // '/...', illegal 90f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return handler; 91f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 92f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 9337b74a387bb3993387029859c2d9d051c41c724eStephen Hines default: { // '/..a' 94f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines slash_stack.push(handler); 9537b74a387bb3993387029859c2d9d051c41c724eStephen Hines handler = pathname.find_first_of(separator, handler + 3); 96f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 97f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 98f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 99f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 100f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 10137b74a387bb3993387029859c2d9d051c41c724eStephen Hines default: { // '/.a' 102f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines slash_stack.push(handler); 10337b74a387bb3993387029859c2d9d051c41c724eStephen Hines handler = pathname.find_first_of(separator, handler + 2); 104f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 105f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 106f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 107f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 108f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 10937b74a387bb3993387029859c2d9d051c41c724eStephen Hines default: { // '/a 110f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines slash_stack.push(handler); 11137b74a387bb3993387029859c2d9d051c41c724eStephen Hines handler = pathname.find_first_of(separator, handler + 1); 112f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 113f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 114f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 11537b74a387bb3993387029859c2d9d051c41c724eStephen Hines } else { 116f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines handler = pathname.find_first_of(separator, handler); 117f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 118f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 119f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return handler; 120f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 121f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 12237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool not_found_error(int perrno) { 123f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return perrno == ENOENT || perrno == ENOTDIR; 124f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 125f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 12637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid status(const Path& p, FileStatus& pFileStatus) { 127f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines struct ::_stat path_stat; 12837b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (::_stat(p.c_str(), &path_stat) != 0) { 12937b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (not_found_error(errno)) { 130f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pFileStatus.setType(FileNotFound); 13137b74a387bb3993387029859c2d9d051c41c724eStephen Hines } else 132f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pFileStatus.setType(StatusError); 13337b74a387bb3993387029859c2d9d051c41c724eStephen Hines } else if (S_ISDIR(path_stat.st_mode)) 134f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pFileStatus.setType(DirectoryFile); 13537b74a387bb3993387029859c2d9d051c41c724eStephen Hines else if (S_ISREG(path_stat.st_mode)) 136f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pFileStatus.setType(RegularFile); 13737b74a387bb3993387029859c2d9d051c41c724eStephen Hines else if (S_ISBLK(path_stat.st_mode)) 138f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pFileStatus.setType(BlockFile); 13937b74a387bb3993387029859c2d9d051c41c724eStephen Hines else if (S_ISCHR(path_stat.st_mode)) 140f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pFileStatus.setType(CharacterFile); 14137b74a387bb3993387029859c2d9d051c41c724eStephen Hines else if (S_ISFIFO(path_stat.st_mode)) 142f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pFileStatus.setType(FifoFile); 143f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines else 144f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pFileStatus.setType(TypeUnknown); 145f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 146f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 14737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid symlink_status(const Path& p, FileStatus& pFileStatus) { 148f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pFileStatus.setType(FileNotFound); 149f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 150f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 151f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// directory_iterator_increment - increment function implementation 152f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// 153f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// iterator will call this function in two situations: 154f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// 1. All elements have been put into cache, and iterator stays at the end 155f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// of cache. (a real end) 156f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// 2. Some but not all elements had beed put into cache, and we stoped. 157f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// An iterator now is staying at the end of cache. (a temporal end) 15837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesmcld::sys::fs::PathCache::entry_type* bring_one_into_cache(DirIterator& pIter) { 159f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines mcld::sys::fs::PathCache::entry_type* entry = 0; 160f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines fs::Path file_filter(pIter.m_pParent->m_Path); 161f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines file_filter.append("*"); 162f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 163f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines WIN32_FIND_DATA FindFileData; 164f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (FindNextFile(reinterpret_cast<HANDLE>(pIter.m_pParent->m_Handler), 165f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines &FindFileData)) { 166f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // read one 167f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines bool exist = false; 168f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines std::string path(pIter.m_pParent->m_Path.native()); 169f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines path += separator; 170f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines path += std::string(FindFileData.cFileName); 171f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines entry = pIter.m_pParent->m_Cache.insert(path, exist); 172f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (!exist) 173f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines entry->setValue(path); 17437b74a387bb3993387029859c2d9d051c41c724eStephen Hines } else if (ERROR_NO_MORE_FILES == GetLastError()) { 175f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // meet real end 176f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pIter.m_pParent->m_CacheFull = true; 17737b74a387bb3993387029859c2d9d051c41c724eStephen Hines } else { 17837b74a387bb3993387029859c2d9d051c41c724eStephen Hines llvm::report_fatal_error(std::string("Can't read directory: ") + 179f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pIter.m_pParent->path().native()); 180f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 181f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 182f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return entry; 183f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 184f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 18537b74a387bb3993387029859c2d9d051c41c724eStephen Hines} // namespace detail 18637b74a387bb3993387029859c2d9d051c41c724eStephen Hines} // namespace fs 18737b74a387bb3993387029859c2d9d051c41c724eStephen Hines} // namespace sys 18837b74a387bb3993387029859c2d9d051c41c724eStephen Hines} // namespace mcld 189