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