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 "llvm/ADT/SmallString.h" 13 #include "llvm/Support/FileSystem.h" 14 #include "llvm/Support/Path.h" 15 16 #if !defined(LLVM_ON_WIN32) 17 #include <pwd.h> 18 #endif 19 20 using namespace lldb_private; 21 using namespace llvm; 22 23 namespace fs = llvm::sys::fs; 24 namespace path = llvm::sys::path; 25 26 TildeExpressionResolver::~TildeExpressionResolver() {} 27 28 bool StandardTildeExpressionResolver::ResolveExact( 29 StringRef Expr, SmallVectorImpl<char> &Output) { 30 // We expect the tilde expression to be ONLY the expression itself, and 31 // contain no separators. 32 assert(!llvm::any_of(Expr, [](char c) { return path::is_separator(c); })); 33 assert(Expr.empty() || Expr[0] == '~'); 34 35 return !fs::real_path(Expr, Output, true); 36 } 37 38 bool StandardTildeExpressionResolver::ResolvePartial(StringRef Expr, 39 StringSet<> &Output) { 40 // We expect the tilde expression to be ONLY the expression itself, and 41 // contain no separators. 42 assert(!llvm::any_of(Expr, [](char c) { return path::is_separator(c); })); 43 assert(Expr.empty() || Expr[0] == '~'); 44 45 Output.clear(); 46 #if defined(LLVM_ON_WIN32) || defined(__ANDROID__) 47 return false; 48 #else 49 if (Expr.empty()) 50 return false; 51 52 SmallString<32> Buffer("~"); 53 setpwent(); 54 struct passwd *user_entry; 55 Expr = Expr.drop_front(); 56 57 while ((user_entry = getpwent()) != NULL) { 58 StringRef ThisName(user_entry->pw_name); 59 if (!ThisName.startswith(Expr)) 60 continue; 61 62 Buffer.resize(1); 63 Buffer.append(ThisName); 64 Buffer.append(path::get_separator()); 65 Output.insert(Buffer); 66 } 67 68 return true; 69 #endif 70 } 71 72 bool TildeExpressionResolver::ResolveFullPath( 73 StringRef Expr, llvm::SmallVectorImpl<char> &Output) { 74 Output.clear(); 75 if (!Expr.startswith("~")) { 76 Output.append(Expr.begin(), Expr.end()); 77 return false; 78 } 79 80 namespace path = llvm::sys::path; 81 StringRef Left = 82 Expr.take_until([](char c) { return path::is_separator(c); }); 83 84 if (!ResolveExact(Left, Output)) 85 return false; 86 87 Output.append(Expr.begin() + Left.size(), Expr.end()); 88 return true; 89 } 90