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