Path: blob/main/contrib/llvm-project/lldb/source/Utility/RealpathPrefixes.cpp
213765 views
//===-- RealpathPrefixes.cpp ----------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "lldb/Utility/RealpathPrefixes.h"910#include "lldb/Utility/FileSpec.h"11#include "lldb/Utility/FileSpecList.h"12#include "lldb/Utility/LLDBLog.h"13#include "lldb/Utility/Log.h"14#include "lldb/lldb-private-types.h"1516using namespace lldb_private;1718RealpathPrefixes::RealpathPrefixes(19const FileSpecList &file_spec_list,20llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs)21: m_fs(fs) {22m_prefixes.reserve(file_spec_list.GetSize());23for (const FileSpec &file_spec : file_spec_list) {24m_prefixes.emplace_back(file_spec.GetPath());25}26}2728std::optional<FileSpec>29RealpathPrefixes::ResolveSymlinks(const FileSpec &file_spec) {30if (m_prefixes.empty())31return std::nullopt;3233// Test if `b` is a *path* prefix of `a` (not just *string* prefix).34// E.g. "/foo/bar" is a path prefix of "/foo/bar/baz" but not "/foo/barbaz".35auto is_path_prefix = [](llvm::StringRef a, llvm::StringRef b,36bool case_sensitive,37llvm::sys::path::Style style) -> bool {38if (case_sensitive ? a.consume_front(b) : a.consume_front_insensitive(b))39// If `b` isn't "/", then it won't end with "/" because it comes from40// `FileSpec`. After `a` consumes `b`, `a` should either be empty (i.e.41// `a` == `b`) or end with "/" (the remainder of `a` is a subdirectory).42return b == "/" || a.empty() ||43llvm::sys::path::is_separator(a[0], style);44return false;45};46std::string file_spec_path = file_spec.GetPath();47for (const std::string &prefix : m_prefixes) {48if (is_path_prefix(file_spec_path, prefix, file_spec.IsCaseSensitive(),49file_spec.GetPathStyle())) {50// Stats and logging.51IncreaseSourceRealpathAttemptCount();52Log *log = GetLog(LLDBLog::Source);53LLDB_LOGF(log, "Realpath'ing support file %s", file_spec_path.c_str());5455// One prefix matched. Try to realpath.56PathSmallString buff;57std::error_code ec = m_fs->getRealPath(file_spec_path, buff);58if (ec)59return std::nullopt;60FileSpec realpath(buff, file_spec.GetPathStyle());6162// Only return realpath if it is different from the original file_spec.63if (realpath != file_spec)64return realpath;65return std::nullopt;66}67}68// No prefix matched69return std::nullopt;70}717273