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