1 //===-- TildeExpressionResolver.cpp ---------------------------------------===// 2 // 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 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lldb/Utility/TildeExpressionResolver.h" 10 11 #include <cassert> 12 #include <system_error> 13 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" 19 20 #if !defined(_WIN32) 21 #include <pwd.h> 22 #endif 23 24 using namespace lldb_private; 25 using namespace llvm; 26 27 namespace fs = llvm::sys::fs; 28 namespace path = llvm::sys::path; 29 30 TildeExpressionResolver::~TildeExpressionResolver() = default; 31 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] == '~'); 38 39 return !fs::real_path(Expr, Output, true); 40 } 41 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] == '~'); 48 49 Output.clear(); 50 #if defined(_WIN32) || defined(__ANDROID__) 51 return false; 52 #else 53 if (Expr.empty()) 54 return false; 55 56 SmallString<32> Buffer("~"); 57 setpwent(); 58 struct passwd *user_entry; 59 Expr = Expr.drop_front(); 60 61 while ((user_entry = getpwent()) != nullptr) { 62 StringRef ThisName(user_entry->pw_name); 63 if (!ThisName.starts_with(Expr)) 64 continue; 65 66 Buffer.resize(1); 67 Buffer.append(ThisName); 68 Buffer.append(path::get_separator()); 69 Output.insert(Buffer); 70 } 71 72 return true; 73 #endif 74 } 75 76 bool TildeExpressionResolver::ResolveFullPath( 77 StringRef Expr, llvm::SmallVectorImpl<char> &Output) { 78 if (!Expr.starts_with("~")) { 79 Output.assign(Expr.begin(), Expr.end()); 80 return false; 81 } 82 83 namespace path = llvm::sys::path; 84 StringRef Left = 85 Expr.take_until([](char c) { return path::is_separator(c); }); 86 87 if (!ResolveExact(Left, Output)) { 88 Output.assign(Expr.begin(), Expr.end()); 89 return false; 90 } 91 92 Output.append(Expr.begin() + Left.size(), Expr.end()); 93 return true; 94 } 95