1 //===--------------------- TildeExpressionResolver.cpp ----------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Utility/TildeExpressionResolver.h"
12 #include <system_error>
14 #include "llvm/ADT/STLExtras.h"
15 #include "llvm/ADT/SmallVector.h"
16 #include "llvm/Support/FileSystem.h"
17 #include "llvm/Support/Path.h"
18 #include "llvm/Support/raw_ostream.h"
24 using namespace lldb_private;
27 namespace fs = llvm::sys::fs;
28 namespace path = llvm::sys::path;
30 TildeExpressionResolver::~TildeExpressionResolver() {}
32 bool StandardTildeExpressionResolver::ResolveExact(
33 StringRef Expr, SmallVectorImpl<char> &Output) {
34 // We expect the tilde expression to be ONLY the expression itself, and
35 // contain no separators.
36 assert(!llvm::any_of(Expr, [](char c) { return path::is_separator(c); }));
37 assert(Expr.empty() || Expr[0] == '~');
39 return !fs::real_path(Expr, Output, true);
42 bool StandardTildeExpressionResolver::ResolvePartial(StringRef Expr,
43 StringSet<> &Output) {
44 // We expect the tilde expression to be ONLY the expression itself, and
45 // contain no separators.
46 assert(!llvm::any_of(Expr, [](char c) { return path::is_separator(c); }));
47 assert(Expr.empty() || Expr[0] == '~');
50 #if defined(_WIN32) || defined(__ANDROID__)
56 SmallString<32> Buffer("~");
58 struct passwd *user_entry;
59 Expr = Expr.drop_front();
61 while ((user_entry = getpwent()) != nullptr) {
62 StringRef ThisName(user_entry->pw_name);
63 if (!ThisName.startswith(Expr))
67 Buffer.append(ThisName);
68 Buffer.append(path::get_separator());
69 Output.insert(Buffer);
76 bool TildeExpressionResolver::ResolveFullPath(
77 StringRef Expr, llvm::SmallVectorImpl<char> &Output) {
79 if (!Expr.startswith("~")) {
80 Output.append(Expr.begin(), Expr.end());
84 namespace path = llvm::sys::path;
86 Expr.take_until([](char c) { return path::is_separator(c); });
88 if (!ResolveExact(Left, Output))
91 Output.append(Expr.begin() + Left.size(), Expr.end());