1 //===--------------------- TildeExpressionResolver.cpp ----------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "lldb/Utility/TildeExpressionResolver.h" 11 12 #include <assert.h> // for assert 13 #include <system_error> // for error_code 14 15 #include "llvm/ADT/STLExtras.h" // for any_of 16 #include "llvm/ADT/SmallVector.h" // for SmallVectorImpl 17 #include "llvm/Config/llvm-config.h" // for LLVM_ON_WIN32 18 #include "llvm/Support/FileSystem.h" 19 #include "llvm/Support/Path.h" 20 #include "llvm/Support/raw_ostream.h" // for fs 21 22 #if !defined(LLVM_ON_WIN32) 23 #include <pwd.h> 24 #endif 25 26 using namespace lldb_private; 27 using namespace llvm; 28 29 namespace fs = llvm::sys::fs; 30 namespace path = llvm::sys::path; 31 32 TildeExpressionResolver::~TildeExpressionResolver() {} 33 34 bool StandardTildeExpressionResolver::ResolveExact( 35 StringRef Expr, SmallVectorImpl<char> &Output) { 36 // We expect the tilde expression to be ONLY the expression itself, and 37 // contain no separators. 38 assert(!llvm::any_of(Expr, [](char c) { return path::is_separator(c); })); 39 assert(Expr.empty() || Expr[0] == '~'); 40 41 return !fs::real_path(Expr, Output, true); 42 } 43 44 bool StandardTildeExpressionResolver::ResolvePartial(StringRef Expr, 45 StringSet<> &Output) { 46 // We expect the tilde expression to be ONLY the expression itself, and 47 // contain no separators. 48 assert(!llvm::any_of(Expr, [](char c) { return path::is_separator(c); })); 49 assert(Expr.empty() || Expr[0] == '~'); 50 51 Output.clear(); 52 #if defined(LLVM_ON_WIN32) || defined(__ANDROID__) 53 return false; 54 #else 55 if (Expr.empty()) 56 return false; 57 58 SmallString<32> Buffer("~"); 59 setpwent(); 60 struct passwd *user_entry; 61 Expr = Expr.drop_front(); 62 63 while ((user_entry = getpwent()) != NULL) { 64 StringRef ThisName(user_entry->pw_name); 65 if (!ThisName.startswith(Expr)) 66 continue; 67 68 Buffer.resize(1); 69 Buffer.append(ThisName); 70 Buffer.append(path::get_separator()); 71 Output.insert(Buffer); 72 } 73 74 return true; 75 #endif 76 } 77 78 bool TildeExpressionResolver::ResolveFullPath( 79 StringRef Expr, llvm::SmallVectorImpl<char> &Output) { 80 Output.clear(); 81 if (!Expr.startswith("~")) { 82 Output.append(Expr.begin(), Expr.end()); 83 return false; 84 } 85 86 namespace path = llvm::sys::path; 87 StringRef Left = 88 Expr.take_until([](char c) { return path::is_separator(c); }); 89 90 if (!ResolveExact(Left, Output)) 91 return false; 92 93 Output.append(Expr.begin() + Left.size(), Expr.end()); 94 return true; 95 } 96