diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2020-07-31 21:22:58 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2020-07-31 21:22:58 +0000 |
commit | 5ffd83dbcc34f10e07f6d3e968ae6365869615f4 (patch) | |
tree | 0e9f5cf729dde39f949698fddef45a34e2bc7f44 /contrib/llvm-project/llvm/lib/Support/VirtualFileSystem.cpp | |
parent | 1799696096df87b52968b8996d00c91e0a5de8d9 (diff) | |
parent | cfca06d7963fa0909f90483b42a6d7d194d01e08 (diff) |
Notes
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Support/VirtualFileSystem.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/Support/VirtualFileSystem.cpp | 146 |
1 files changed, 96 insertions, 50 deletions
diff --git a/contrib/llvm-project/llvm/lib/Support/VirtualFileSystem.cpp b/contrib/llvm-project/llvm/lib/Support/VirtualFileSystem.cpp index edd4234fe501..5b757c9ea80d 100644 --- a/contrib/llvm-project/llvm/lib/Support/VirtualFileSystem.cpp +++ b/contrib/llvm-project/llvm/lib/Support/VirtualFileSystem.cpp @@ -306,12 +306,12 @@ RealFileSystem::openFileForRead(const Twine &Name) { llvm::ErrorOr<std::string> RealFileSystem::getCurrentWorkingDirectory() const { if (WD) - return WD->Specified.str(); + return std::string(WD->Specified.str()); SmallString<128> Dir; if (std::error_code EC = llvm::sys::fs::current_path(Dir)) return EC; - return Dir.str(); + return std::string(Dir.str()); } std::error_code RealFileSystem::setCurrentWorkingDirectory(const Twine &Path) { @@ -535,7 +535,8 @@ class InMemoryNode { public: InMemoryNode(llvm::StringRef FileName, InMemoryNodeKind Kind) - : Kind(Kind), FileName(llvm::sys::path::filename(FileName)) {} + : Kind(Kind), FileName(std::string(llvm::sys::path::filename(FileName))) { + } virtual ~InMemoryNode() = default; /// Get the filename of this node (the name without the directory part). @@ -904,7 +905,7 @@ class InMemoryDirIterator : public llvm::vfs::detail::DirIterImpl { Type = sys::fs::file_type::directory_file; break; } - CurrentEntry = directory_entry(Path.str(), Type); + CurrentEntry = directory_entry(std::string(Path.str()), Type); } else { // When we're at the end, make CurrentEntry invalid and DirIterImpl will // do the rest. @@ -960,7 +961,7 @@ std::error_code InMemoryFileSystem::setCurrentWorkingDirectory(const Twine &P) { llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true); if (!Path.empty()) - WorkingDirectory = Path.str(); + WorkingDirectory = std::string(Path.str()); return {}; } @@ -989,6 +990,28 @@ std::error_code InMemoryFileSystem::isLocal(const Twine &Path, bool &Result) { // RedirectingFileSystem implementation //===-----------------------------------------------------------------------===/ +namespace { + +/// Removes leading "./" as well as path components like ".." and ".". +static llvm::SmallString<256> canonicalize(llvm::StringRef Path) { + // First detect the path style in use by checking the first separator. + llvm::sys::path::Style style = llvm::sys::path::Style::native; + const size_t n = Path.find_first_of("/\\"); + if (n != static_cast<size_t>(-1)) + style = (Path[n] == '/') ? llvm::sys::path::Style::posix + : llvm::sys::path::Style::windows; + + // Now remove the dots. Explicitly specifying the path style prevents the + // direction of the slashes from changing. + llvm::SmallString<256> result = + llvm::sys::path::remove_leading_dotslash(Path, style); + llvm::sys::path::remove_dots(result, /*remove_dot_dot=*/true, style); + return result; +} + +} // anonymous namespace + + RedirectingFileSystem::RedirectingFileSystem(IntrusiveRefCntPtr<FileSystem> FS) : ExternalFS(std::move(FS)) { if (ExternalFS) @@ -1064,7 +1087,7 @@ RedirectingFileSystem::setCurrentWorkingDirectory(const Twine &Path) { Path.toVector(AbsolutePath); if (std::error_code EC = makeAbsolute(AbsolutePath)) return EC; - WorkingDirectory = AbsolutePath.str(); + WorkingDirectory = std::string(AbsolutePath.str()); return {}; } @@ -1082,7 +1105,23 @@ std::error_code RedirectingFileSystem::makeAbsolute(SmallVectorImpl<char> &Path) if (!WorkingDir) return WorkingDir.getError(); - llvm::sys::fs::make_absolute(WorkingDir.get(), Path); + // We can't use sys::fs::make_absolute because that assumes the path style + // is native and there is no way to override that. Since we know WorkingDir + // is absolute, we can use it to determine which style we actually have and + // append Path ourselves. + sys::path::Style style = sys::path::Style::windows; + if (sys::path::is_absolute(WorkingDir.get(), sys::path::Style::posix)) { + style = sys::path::Style::posix; + } + + std::string Result = WorkingDir.get(); + StringRef Dir(Result); + if (!Dir.endswith(sys::path::get_separator(style))) { + Result += sys::path::get_separator(style); + } + Result.append(Path.data(), Path.size()); + Path.assign(Result.begin(), Result.end()); + return {}; } @@ -1317,8 +1356,8 @@ class llvm::vfs::RedirectingFileSystemParser { bool HasContents = false; // external or otherwise std::vector<std::unique_ptr<RedirectingFileSystem::Entry>> EntryArrayContents; - std::string ExternalContentsPath; - std::string Name; + SmallString<256> ExternalContentsPath; + SmallString<256> Name; yaml::Node *NameValueNode = nullptr; auto UseExternalName = RedirectingFileSystem::RedirectingFileEntry::NK_NotSet; @@ -1341,16 +1380,9 @@ class llvm::vfs::RedirectingFileSystemParser { return nullptr; NameValueNode = I.getValue(); - if (FS->UseCanonicalizedPaths) { - SmallString<256> Path(Value); - // Guarantee that old YAML files containing paths with ".." and "." - // are properly canonicalized before read into the VFS. - Path = sys::path::remove_leading_dotslash(Path); - sys::path::remove_dots(Path, /*remove_dot_dot=*/true); - Name = Path.str(); - } else { - Name = Value; - } + // Guarantee that old YAML files containing paths with ".." and "." + // are properly canonicalized before read into the VFS. + Name = canonicalize(Value).str(); } else if (Key == "type") { if (!parseScalarString(I.getValue(), Value, Buffer)) return nullptr; @@ -1403,12 +1435,9 @@ class llvm::vfs::RedirectingFileSystemParser { FullPath = Value; } - if (FS->UseCanonicalizedPaths) { - // Guarantee that old YAML files containing paths with ".." and "." - // are properly canonicalized before read into the VFS. - FullPath = sys::path::remove_leading_dotslash(FullPath); - sys::path::remove_dots(FullPath, /*remove_dot_dot=*/true); - } + // Guarantee that old YAML files containing paths with ".." and "." + // are properly canonicalized before read into the VFS. + FullPath = canonicalize(FullPath); ExternalContentsPath = FullPath.str(); } else if (Key == "use-external-name") { bool Val; @@ -1653,14 +1682,10 @@ RedirectingFileSystem::lookupPath(const Twine &Path_) const { if (std::error_code EC = makeAbsolute(Path)) return EC; - // Canonicalize path by removing ".", "..", "./", etc components. This is - // a VFS request, do bot bother about symlinks in the path components + // Canonicalize path by removing ".", "..", "./", components. This is + // a VFS request, do not bother about symlinks in the path components // but canonicalize in order to perform the correct entry search. - if (UseCanonicalizedPaths) { - Path = sys::path::remove_leading_dotslash(Path); - sys::path::remove_dots(Path, /*remove_dot_dot=*/true); - } - + Path = canonicalize(Path); if (Path.empty()) return make_error_code(llvm::errc::invalid_argument); @@ -1679,16 +1704,9 @@ ErrorOr<RedirectingFileSystem::Entry *> RedirectingFileSystem::lookupPath(sys::path::const_iterator Start, sys::path::const_iterator End, RedirectingFileSystem::Entry *From) const { -#ifndef _WIN32 assert(!isTraversalComponent(*Start) && !isTraversalComponent(From->getName()) && "Paths should not contain traversal components"); -#else - // FIXME: this is here to support windows, remove it once canonicalized - // paths become globally default. - if (Start->equals(".")) - ++Start; -#endif StringRef FromName = From->getName(); @@ -1894,11 +1912,21 @@ UniqueID vfs::getNextVirtualUniqueID() { return UniqueID(std::numeric_limits<uint64_t>::max(), ID); } -void YAMLVFSWriter::addFileMapping(StringRef VirtualPath, StringRef RealPath) { +void YAMLVFSWriter::addEntry(StringRef VirtualPath, StringRef RealPath, + bool IsDirectory) { assert(sys::path::is_absolute(VirtualPath) && "virtual path not absolute"); assert(sys::path::is_absolute(RealPath) && "real path not absolute"); assert(!pathHasTraversal(VirtualPath) && "path traversal is not supported"); - Mappings.emplace_back(VirtualPath, RealPath); + Mappings.emplace_back(VirtualPath, RealPath, IsDirectory); +} + +void YAMLVFSWriter::addFileMapping(StringRef VirtualPath, StringRef RealPath) { + addEntry(VirtualPath, RealPath, /*IsDirectory=*/false); +} + +void YAMLVFSWriter::addDirectoryMapping(StringRef VirtualPath, + StringRef RealPath) { + addEntry(VirtualPath, RealPath, /*IsDirectory=*/true); } namespace { @@ -1999,7 +2027,10 @@ void JSONWriter::write(ArrayRef<YAMLVFSEntry> Entries, if (!Entries.empty()) { const YAMLVFSEntry &Entry = Entries.front(); - startDirectory(path::parent_path(Entry.VPath)); + + startDirectory( + Entry.IsDirectory ? Entry.VPath : path::parent_path(Entry.VPath) + ); StringRef RPath = Entry.RPath; if (UseOverlayRelative) { @@ -2009,19 +2040,31 @@ void JSONWriter::write(ArrayRef<YAMLVFSEntry> Entries, RPath = RPath.slice(OverlayDirLen, RPath.size()); } - writeEntry(path::filename(Entry.VPath), RPath); + bool IsCurrentDirEmpty = true; + if (!Entry.IsDirectory) { + writeEntry(path::filename(Entry.VPath), RPath); + IsCurrentDirEmpty = false; + } for (const auto &Entry : Entries.slice(1)) { - StringRef Dir = path::parent_path(Entry.VPath); - if (Dir == DirStack.back()) - OS << ",\n"; - else { + StringRef Dir = + Entry.IsDirectory ? Entry.VPath : path::parent_path(Entry.VPath); + if (Dir == DirStack.back()) { + if (!IsCurrentDirEmpty) { + OS << ",\n"; + } + } else { + bool IsDirPoppedFromStack = false; while (!DirStack.empty() && !containedIn(DirStack.back(), Dir)) { OS << "\n"; endDirectory(); + IsDirPoppedFromStack = true; + } + if (IsDirPoppedFromStack || !IsCurrentDirEmpty) { + OS << ",\n"; } - OS << ",\n"; startDirectory(Dir); + IsCurrentDirEmpty = true; } StringRef RPath = Entry.RPath; if (UseOverlayRelative) { @@ -2030,7 +2073,10 @@ void JSONWriter::write(ArrayRef<YAMLVFSEntry> Entries, "Overlay dir must be contained in RPath"); RPath = RPath.slice(OverlayDirLen, RPath.size()); } - writeEntry(path::filename(Entry.VPath), RPath); + if (!Entry.IsDirectory) { + writeEntry(path::filename(Entry.VPath), RPath); + IsCurrentDirEmpty = false; + } } while (!DirStack.empty()) { @@ -2104,7 +2150,7 @@ std::error_code VFSFromYamlDirIterImpl::incrementContent(bool IsFirstTime) { Type = sys::fs::file_type::regular_file; break; } - CurrentEntry = directory_entry(PathStr.str(), Type); + CurrentEntry = directory_entry(std::string(PathStr.str()), Type); return {}; } return incrementExternal(); |