13 #include <boost/filesystem.hpp>
15 namespace linuxdeploy {
18 static inline bool ltrim(std::string& s, char to_trim = ' ') {
19 // TODO: find more efficient way to check whether elements have been removed
20 size_t initialLength = s.length();
21 s.erase(s.begin(), std::find_if(s.begin(), s.end(), [to_trim](int ch) {
24 return s.length() < initialLength;
27 static inline bool rtrim(std::string& s, char to_trim = ' ') {
28 // TODO: find more efficient way to check whether elements have been removed
29 auto initialLength = s.length();
30 s.erase(std::find_if(s.rbegin(), s.rend(), [to_trim](int ch) {
33 return s.length() < initialLength;
36 static inline bool trim(std::string& s, char to_trim = ' ') {
37 // returns true if either modifies s
38 auto ltrim_result = ltrim(s, to_trim);
39 return rtrim(s, to_trim) && ltrim_result;
42 static std::vector<std::string> split(const std::string& s, char delim = ' ') {
43 std::vector<std::string> result;
45 std::stringstream ss(s);
48 while (std::getline(ss, item, delim)) {
49 result.push_back(item);
55 static std::vector<std::string> splitLines(const std::string& s) {
56 return split(s, '\n');
59 static std::string join(const std::vector<std::string> &strings, const std::string &delimiter) {
61 for (size_t i = 0; i < strings.size(); i++) {
64 if (i != strings.size() - 1) {
71 static inline std::string strLower(std::string s) {
72 std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return std::tolower(c); });
76 static bool stringStartsWith(const std::string& string, const std::string& prefix) {
78 if (string.size() < prefix.size())
81 return strncmp(string.c_str(), prefix.c_str(), prefix.size()) == 0;
84 static bool stringEndsWith(const std::string& string, const std::string& suffix) {
86 if (string.size() < suffix.size())
89 return strcmp(string.c_str() + (string.size() - suffix.size()), suffix.c_str()) == 0;
92 static bool stringContains(const std::string& string, const std::string& part) {
93 return string.find(part) != std::string::npos;
96 static std::string getOwnExecutablePath() {
97 // FIXME: reading /proc/self/exe line is Linux specific
98 std::vector<char> buf(PATH_MAX, '\0');
100 if (readlink("/proc/self/exe", buf.data(), buf.size()) < 0) {
107 // very simple but for our purposes good enough which like algorithm to find binaries in $PATH
108 static boost::filesystem::path which(const std::string& name) {
109 const auto* path = getenv("PATH");
111 namespace bf = boost::filesystem;
116 for (const auto& binDir : split(path, ':')) {
117 if (!bf::is_directory(binDir)) {
121 for (bf::directory_iterator it(binDir); it != bf::directory_iterator{}; ++it) {
122 const auto binary = it->path();
124 if (binary.filename() == name) {
125 // TODO: check if file is executable (skip otherwise)