15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- PathV3.inc ---------------------------------------------------------===//
25460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
35460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//                     The MCLinker Project
45460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
55460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// This file is distributed under the University of Illinois Open Source
65460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// License. See LICENSE.TXT for details.
75460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
85460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===//
937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/FileSystem.h"
1037b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/Path.h"
1137b74a387bb3993387029859c2d9d051c41c724eStephen Hines
125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/ErrorHandling.h>
135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <cerrno>
1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include <stack>
165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <stdio.h>
1737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include <string>
185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <sys/stat.h>
195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <sys/types.h>
205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <unistd.h>
215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld {
2337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace sys {
2437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace fs {
255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
26f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//===----------------------------------------------------------------------===//
27f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// mcld::sys::fs::detail
28f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//===----------------------------------------------------------------------===//
2937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace detail {
305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// return the last charactor being handled.
3237b74a387bb3993387029859c2d9d051c41c724eStephen Hinessize_t canonicalize(std::string& pathname) {
335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Variable Index //
345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // SepTable - stack of result separators
355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // LR(1) Algorithm //
365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // traverse pPathName
375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  //   if we meet '//', '///', '////', ...
385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  //     -> ignore it
395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  //     -> push current into stack
405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  //     -> jump to the next not '/'
415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  //   if we meet '/./'
425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  //     -> ignore
435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  //     -> jump to the next not '/'
445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  //   if we meet '/../'
455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  //     -> pop previous position of '/' P
465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  //     -> erase P+1 to now
475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  //   if we meet other else
485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  //     -> go go go
495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  //   if we meet '/.../', '/..../', ... -> illegal
505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (pathname.empty())
515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return 0;
525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  size_t handler = 0;
545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  std::stack<size_t> slash_stack;
555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  slash_stack.push(-1);
565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  while (handler < pathname.size()) {
5737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (separator == pathname[handler]) {  // handler = 1st '/'
585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      size_t next = handler + 1;
595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      if (next >= pathname.size())
605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        return handler;
6137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      switch (pathname[next]) {  // next = handler + 1;
6237b74a387bb3993387029859c2d9d051c41c724eStephen Hines        case separator: {        // '//'
635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          while (next < pathname.size() && separator == pathname[next])
645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao            ++next;
655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          // next is the last not '/'
665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          pathname.erase(handler, next - handler - 1);
675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          // handler is the first '/'
685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          slash_stack.push(handler);
695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          break;
705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        }
7137b74a387bb3993387029859c2d9d051c41c724eStephen Hines        case '.': {                     // '/.'
7237b74a387bb3993387029859c2d9d051c41c724eStephen Hines          ++next;                       // next = handler + 2
7337b74a387bb3993387029859c2d9d051c41c724eStephen Hines          if (next >= pathname.size())  // '/.'
745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao            return handler;
755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          switch (pathname[next]) {
7637b74a387bb3993387029859c2d9d051c41c724eStephen Hines            case separator: {  // '/./'
775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao              pathname.erase(handler, 2);
785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao              break;
795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao            }
8037b74a387bb3993387029859c2d9d051c41c724eStephen Hines            case '.': {                     // '/..'
8137b74a387bb3993387029859c2d9d051c41c724eStephen Hines              ++next;                       // next = handler + 3;
8237b74a387bb3993387029859c2d9d051c41c724eStephen Hines              if (next >= pathname.size())  // '/..?'
835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                return handler;
8437b74a387bb3993387029859c2d9d051c41c724eStephen Hines              switch (pathname[next]) {
8537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                case separator: {  // '/../'
865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                  handler = slash_stack.top();
875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                  slash_stack.pop();
8837b74a387bb3993387029859c2d9d051c41c724eStephen Hines                  pathname.erase(handler + 1, next - handler);
895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                  if (static_cast<size_t>(-1) == handler) {
905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                    slash_stack.push(-1);
915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                    handler = pathname.find_first_of(separator, handler);
925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                  }
935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                  break;
945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                }
9537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                case '.': {  // '/...', illegal
965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                  return handler;
975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                  break;
985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                }
9937b74a387bb3993387029859c2d9d051c41c724eStephen Hines                default: {  // '/..a'
1005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                  slash_stack.push(handler);
10137b74a387bb3993387029859c2d9d051c41c724eStephen Hines                  handler = pathname.find_first_of(separator, handler + 3);
1025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                  break;
1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                }
1045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao              }
1055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao              break;
1065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao            }
10737b74a387bb3993387029859c2d9d051c41c724eStephen Hines            default: {  // '/.a'
1085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao              slash_stack.push(handler);
10937b74a387bb3993387029859c2d9d051c41c724eStephen Hines              handler = pathname.find_first_of(separator, handler + 2);
1105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao              break;
1115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao            }
1125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          }
1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          break;
1145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        }
11537b74a387bb3993387029859c2d9d051c41c724eStephen Hines        default: {  // '/a
1165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          slash_stack.push(handler);
11737b74a387bb3993387029859c2d9d051c41c724eStephen Hines          handler = pathname.find_first_of(separator, handler + 1);
1185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          break;
1195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        }
1205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      }
12137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    } else {
1225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      handler = pathname.find_first_of(separator, handler);
1235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
1245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return handler;
1265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
12837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool not_found_error(int perrno) {
1295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return perrno == ENOENT || perrno == ENOTDIR;
1305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
13237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid status(const Path& p, FileStatus& pFileStatus) {
1335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  struct stat path_stat;
13437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (stat(p.c_str(), &path_stat) != 0) {
13537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (not_found_error(errno)) {
1365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      pFileStatus.setType(FileNotFound);
13737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    } else
1385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      pFileStatus.setType(StatusError);
13937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else if (S_ISDIR(path_stat.st_mode))
1405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pFileStatus.setType(DirectoryFile);
14137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  else if (S_ISREG(path_stat.st_mode))
1425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pFileStatus.setType(RegularFile);
14337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  else if (S_ISBLK(path_stat.st_mode))
1445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pFileStatus.setType(BlockFile);
14537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  else if (S_ISCHR(path_stat.st_mode))
1465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pFileStatus.setType(CharacterFile);
14737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  else if (S_ISFIFO(path_stat.st_mode))
1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pFileStatus.setType(FifoFile);
14937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  else if (S_ISSOCK(path_stat.st_mode))
1505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pFileStatus.setType(SocketFile);
1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else
1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pFileStatus.setType(TypeUnknown);
1535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
15537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid symlink_status(const Path& p, FileStatus& pFileStatus) {
1565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  struct stat path_stat;
15737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (lstat(p.c_str(), &path_stat) != 0) {
15837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (errno == ENOENT || errno == ENOTDIR)  // these are not errors
1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    {
1605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      pFileStatus.setType(FileNotFound);
16137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    } else
1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      pFileStatus.setType(StatusError);
1635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
16437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (S_ISREG(path_stat.st_mode))
1655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pFileStatus.setType(RegularFile);
16637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (S_ISDIR(path_stat.st_mode))
1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pFileStatus.setType(DirectoryFile);
16837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (S_ISLNK(path_stat.st_mode))
1695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pFileStatus.setType(SymlinkFile);
17037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (S_ISBLK(path_stat.st_mode))
1715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pFileStatus.setType(BlockFile);
17237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (S_ISCHR(path_stat.st_mode))
1735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pFileStatus.setType(CharacterFile);
17437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (S_ISFIFO(path_stat.st_mode))
1755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pFileStatus.setType(FifoFile);
17637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (S_ISSOCK(path_stat.st_mode))
1775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pFileStatus.setType(SocketFile);
1785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else
1795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pFileStatus.setType(TypeUnknown);
1805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// directory_iterator_increment - increment function implementation
1835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
1845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//  iterator will call this function in two situations:
1855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//  1. All elements have been put into cache, and iterator stays at the end
1865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//     of cache. (a real end)
187f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//  2. Some but not all elements had been put into cache, and we stoped.
1885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//     An iterator now is staying at the end of cache. (a temporal end)
18937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesmcld::sys::fs::PathCache::entry_type* bring_one_into_cache(DirIterator& pIter) {
1905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  mcld::sys::fs::PathCache::entry_type* entry = 0;
1915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  std::string path(pIter.m_pParent->m_Path.native());
1925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  switch (read_dir(pIter.m_pParent->m_Handler, path)) {
19337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case 1: {
19437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      // read one
19537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      bool exist = false;
19637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      entry = pIter.m_pParent->m_Cache.insert(path, exist);
19737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      if (!exist)
19837b74a387bb3993387029859c2d9d051c41c724eStephen Hines        entry->setValue(sys::fs::Path(path));
19937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      break;
20037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    }
20137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case 0:  // meet real end
20237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      pIter.m_pParent->m_CacheFull = true;
20337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      break;
20437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    default:
20537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case -1:
20637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::report_fatal_error(std::string("Can't read directory: ") +
20737b74a387bb3993387029859c2d9d051c41c724eStephen Hines                               pIter.m_pParent->path().native());
20837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      break;
2095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return entry;
2115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
21337b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace detail
21437b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace fs
21537b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace sys
21637b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace mcld
217