1 //===-- FileSystem.cpp ------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/Host/FileSystem.h"
11 
12 #include "lldb/Utility/TildeExpressionResolver.h"
13 
14 #include "llvm/Support/FileSystem.h"
15 #include "llvm/Support/Threading.h"
16 
17 #include <algorithm>
18 #include <fstream>
19 #include <vector>
20 
21 using namespace lldb;
22 using namespace lldb_private;
23 using namespace llvm;
24 
25 FileSystem &FileSystem::Instance() { return *InstanceImpl(); }
26 
27 void FileSystem::Initialize() {
28   assert(!InstanceImpl());
29   InstanceImpl().emplace();
30 }
31 
32 void FileSystem::Initialize(IntrusiveRefCntPtr<vfs::FileSystem> fs) {
33   assert(!InstanceImpl());
34   InstanceImpl().emplace(fs);
35 }
36 
37 void FileSystem::Terminate() {
38   assert(InstanceImpl());
39   InstanceImpl().reset();
40 }
41 
42 Optional<FileSystem> &FileSystem::InstanceImpl() {
43   static Optional<FileSystem> g_fs;
44   return g_fs;
45 }
46 
47 void FileSystem::SetFileSystem(IntrusiveRefCntPtr<vfs::FileSystem> fs) {
48   m_fs = fs;
49 }
50 
51 sys::TimePoint<>
52 FileSystem::GetModificationTime(const FileSpec &file_spec) const {
53   return GetModificationTime(file_spec.GetPath());
54 }
55 
56 sys::TimePoint<> FileSystem::GetModificationTime(const Twine &path) const {
57   ErrorOr<vfs::Status> status = m_fs->status(path);
58   if (!status)
59     return sys::TimePoint<>();
60   return status->getLastModificationTime();
61 }
62 
63 uint64_t FileSystem::GetByteSize(const FileSpec &file_spec) const {
64   return GetByteSize(file_spec.GetPath());
65 }
66 
67 uint64_t FileSystem::GetByteSize(const Twine &path) const {
68   ErrorOr<vfs::Status> status = m_fs->status(path);
69   if (!status)
70     return 0;
71   return status->getSize();
72 }
73 
74 uint32_t FileSystem::GetPermissions(const FileSpec &file_spec) const {
75   return GetPermissions(file_spec.GetPath());
76 }
77 
78 uint32_t FileSystem::GetPermissions(const Twine &path) const {
79   ErrorOr<vfs::Status> status = m_fs->status(path);
80   if (!status)
81     return sys::fs::perms::perms_not_known;
82   return status->getPermissions();
83 }
84 
85 bool FileSystem::Exists(const Twine &path) const { return m_fs->exists(path); }
86 
87 bool FileSystem::Exists(const FileSpec &file_spec) const {
88   return Exists(file_spec.GetPath());
89 }
90 
91 bool FileSystem::Readable(const Twine &path) const {
92   return GetPermissions(path) & sys::fs::perms::all_read;
93 }
94 
95 bool FileSystem::Readable(const FileSpec &file_spec) const {
96   return Readable(file_spec.GetPath());
97 }
98 
99 std::error_code FileSystem::MakeAbsolute(SmallVectorImpl<char> &path) const {
100   return m_fs->makeAbsolute(path);
101 }
102 
103 std::error_code FileSystem::MakeAbsolute(FileSpec &file_spec) const {
104   SmallString<128> path;
105   file_spec.GetPath(path, false);
106 
107   auto EC = MakeAbsolute(path);
108   if (EC)
109     return EC;
110 
111   FileSpec new_file_spec(path, false, file_spec.GetPathStyle());
112   file_spec = new_file_spec;
113   return {};
114 }
115 
116 std::error_code FileSystem::GetRealPath(const Twine &path,
117                                         SmallVectorImpl<char> &output) const {
118   return m_fs->getRealPath(path, output);
119 }
120 
121 void FileSystem::Resolve(SmallVectorImpl<char> &path) {
122   if (path.empty())
123     return;
124 
125   // Resolve tilde.
126   SmallString<128> original_path(path.begin(), path.end());
127   StandardTildeExpressionResolver Resolver;
128   Resolver.ResolveFullPath(original_path, path);
129 
130   // Try making the path absolute if it exists.
131   SmallString<128> absolute_path(path.begin(), path.end());
132   MakeAbsolute(path);
133   if (!Exists(path)) {
134     path.clear();
135     path.append(original_path.begin(), original_path.end());
136   }
137 }
138 
139 void FileSystem::Resolve(FileSpec &file_spec) {
140   // Extract path from the FileSpec.
141   SmallString<128> path;
142   file_spec.GetPath(path);
143 
144   // Resolve the path.
145   Resolve(path);
146 
147   // Update the FileSpec with the resolved path.
148   file_spec.SetPath(path);
149 }
150