mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-16 17:16:42 +00:00

# Part 1: Correctly fix a usage of `PATH_MAX` TL;DR: Adding a typedef `lldb_private::PathSmallString` which contains a hardcoded initial size (128). # Part 2: Fix unit tests After https://github.com/llvm/llvm-project/pull/104493 fixed the build break for Windows, unit test failure showed up for Windows. The root-cause is that the `FileSpec`'s in the unit tests are not style-specific. The fix is to apply either `WindowsSpec` or `PosixSpec` specifically.
72 lines
2.6 KiB
C++
72 lines
2.6 KiB
C++
//===-- RealpathPrefixes.cpp ----------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "lldb/Utility/RealpathPrefixes.h"
|
|
|
|
#include "lldb/Utility/FileSpec.h"
|
|
#include "lldb/Utility/FileSpecList.h"
|
|
#include "lldb/Utility/LLDBLog.h"
|
|
#include "lldb/Utility/Log.h"
|
|
#include "lldb/lldb-private-types.h"
|
|
|
|
using namespace lldb_private;
|
|
|
|
RealpathPrefixes::RealpathPrefixes(
|
|
const FileSpecList &file_spec_list,
|
|
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs)
|
|
: m_fs(fs) {
|
|
m_prefixes.reserve(file_spec_list.GetSize());
|
|
for (const FileSpec &file_spec : file_spec_list) {
|
|
m_prefixes.emplace_back(file_spec.GetPath());
|
|
}
|
|
}
|
|
|
|
std::optional<FileSpec>
|
|
RealpathPrefixes::ResolveSymlinks(const FileSpec &file_spec) {
|
|
if (m_prefixes.empty())
|
|
return std::nullopt;
|
|
|
|
// Test if `b` is a *path* prefix of `a` (not just *string* prefix).
|
|
// E.g. "/foo/bar" is a path prefix of "/foo/bar/baz" but not "/foo/barbaz".
|
|
auto is_path_prefix = [](llvm::StringRef a, llvm::StringRef b,
|
|
bool case_sensitive,
|
|
llvm::sys::path::Style style) -> bool {
|
|
if (case_sensitive ? a.consume_front(b) : a.consume_front_insensitive(b))
|
|
// If `b` isn't "/", then it won't end with "/" because it comes from
|
|
// `FileSpec`. After `a` consumes `b`, `a` should either be empty (i.e.
|
|
// `a` == `b`) or end with "/" (the remainder of `a` is a subdirectory).
|
|
return b == "/" || a.empty() ||
|
|
llvm::sys::path::is_separator(a[0], style);
|
|
return false;
|
|
};
|
|
std::string file_spec_path = file_spec.GetPath();
|
|
for (const std::string &prefix : m_prefixes) {
|
|
if (is_path_prefix(file_spec_path, prefix, file_spec.IsCaseSensitive(),
|
|
file_spec.GetPathStyle())) {
|
|
// Stats and logging.
|
|
IncreaseSourceRealpathAttemptCount();
|
|
Log *log = GetLog(LLDBLog::Source);
|
|
LLDB_LOGF(log, "Realpath'ing support file %s", file_spec_path.c_str());
|
|
|
|
// One prefix matched. Try to realpath.
|
|
PathSmallString buff;
|
|
std::error_code ec = m_fs->getRealPath(file_spec_path, buff);
|
|
if (ec)
|
|
return std::nullopt;
|
|
FileSpec realpath(buff, file_spec.GetPathStyle());
|
|
|
|
// Only return realpath if it is different from the original file_spec.
|
|
if (realpath != file_spec)
|
|
return realpath;
|
|
return std::nullopt;
|
|
}
|
|
}
|
|
// No prefix matched
|
|
return std::nullopt;
|
|
}
|