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