TYPE3
[iec.git] / src / type3_AndroidCloud / anbox-master / src / anbox / utils.cpp
1 /*
2  * Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
3  *
4  * This program is free software: you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License version 3, as published
6  * by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranties of
10  * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11  * PURPOSE.  See the GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program.  If not, see <http://www.gnu.org/licenses/>.
15  *
16  */
17
18 #include <boost/filesystem.hpp>
19 #include <boost/throw_exception.hpp>
20 #include <boost/algorithm/string/split.hpp>
21 #include <boost/algorithm/string/classification.hpp>
22
23 #include <fstream>
24 #include <iostream>
25 #include <sstream>
26 #include <stdexcept>
27
28 #include <fcntl.h>
29 #include <mntent.h>
30 #include <sys/stat.h>
31 #include <sys/types.h>
32
33 #include "anbox/utils.h"
34
35 namespace fs = boost::filesystem;
36
37 namespace anbox {
38 namespace utils {
39 std::vector<std::string> collect_arguments(int argc, char **argv) {
40   std::vector<std::string> result;
41   for (int i = 1; i < argc; i++) result.push_back(argv[i]);
42   return result;
43 }
44
45 std::string read_file_if_exists_or_throw(const std::string &file_path) {
46   if (!boost::filesystem::is_regular(boost::filesystem::path(file_path)))
47     BOOST_THROW_EXCEPTION(std::runtime_error("File does not exist"));
48
49   std::ifstream file;
50   file.open(file_path, std::ifstream::in);
51   std::stringstream buffer;
52   buffer << file.rdbuf();
53   return buffer.str();
54 }
55
56 bool write_to_file(const std::string &file_path, const std::string &content) {
57   std::ofstream of;
58   of.open(file_path, std::ofstream::out);
59   of << content;
60   of.close();
61   return true;
62 }
63
64 int write_to_fd(int fd, const char *content, ssize_t len) {
65   while (len > 0) {
66     const auto res = write(fd, content, len);
67     if (res < 0 && errno == EINTR) continue;
68
69     if (res <= 0) {
70       if (res == 0) /* Unexpected short write, should not happen when writing to
71                        a file */
72         errno = ENOSPC;
73       return -1;
74     }
75
76     len -= res;
77     content += res;
78   }
79   return 0;
80 }
81
82 int write_file_at(int dirfd, const char *path, const char *content) {
83   const auto fd = openat(dirfd, path, O_RDWR | O_CLOEXEC, 0);
84   if (fd == -1) return -1;
85
86   auto res = 0;
87   if (content) res = write_to_fd(fd, content, strlen(content));
88
89   const auto errsv = errno;
90   close(fd);
91   errno = errsv;
92
93   return res;
94 }
95
96 bool string_starts_with(const std::string &text, const std::string &prefix) {
97   return text.compare(0, prefix.size(), prefix) == 0;
98 }
99
100 std::vector<std::string> string_split(const std::string &text, char sep) {
101   std::vector<std::string> tokens;
102   return boost::algorithm::split(tokens, text, boost::is_from_range(sep, sep), boost::algorithm::token_compress_on);
103 }
104
105 std::string strip_surrounding_quotes(const std::string &text) {
106   auto result = text;
107   if (text[0] == '\"' && text[text.length() - 1] == '\"')
108     result = text.substr(1, text.length() - 2);
109   return result;
110 }
111
112 std::string hex_dump(const uint8_t *data, uint32_t size) {
113   unsigned char buff[17];
114   const uint8_t *pc = data;
115   std::stringstream buffer;
116
117   if (size == 0) {
118     buffer << "NULL" << std::endl;
119     return buffer.str();
120   }
121
122   uint32_t i;
123   for (i = 0; i < size; i++) {
124     if ((i % 16) == 0) {
125       if (i != 0) buffer << string_format("  %s", buff) << std::endl;
126
127       buffer << string_format("%02x   ", i);
128     }
129
130     buffer << string_format(" %02x", static_cast<int>(pc[i]));
131
132     if ((pc[i] < 0x20) || (pc[i] > 0x7e))
133       buff[i % 16] = '.';
134     else
135       buff[i % 16] = pc[i];
136     buff[(i % 16) + 1] = '\0';
137   }
138
139   while ((i % 16) != 0) {
140     buffer << "   ";
141     i++;
142   }
143
144   buffer << string_format("  %s", buff) << std::endl;
145
146   return buffer.str();
147 }
148
149 std::string get_env_value(const std::string &name,
150                           const std::string &default_value) {
151   char *value = getenv(name.c_str());
152   if (!value) return default_value;
153   return std::string(value);
154 }
155
156 bool is_env_set(const std::string &name) {
157   return getenv(name.c_str()) != nullptr;
158 }
159
160 void ensure_paths(const std::vector<std::string> &paths) {
161   for (const auto &path : paths) {
162     if (!fs::is_directory(fs::path(path)))
163       fs::create_directories(fs::path(path));
164   }
165 }
166
167 std::string prefix_dir_from_env(const std::string &path,
168                                 const std::string &env_var) {
169   static auto snap_data_path = anbox::utils::get_env_value(env_var, "");
170   auto result = path;
171   if (!snap_data_path.empty())
172     result = anbox::utils::string_format("%s%s", snap_data_path, path);
173   return result;
174 }
175
176 std::string process_get_exe_path(const pid_t &pid) {
177   auto exe_path = string_format("/proc/%d/exe", pid);
178   return boost::filesystem::read_symlink(exe_path).string();
179 }
180
181 bool is_mounted(const std::string &path) {
182   FILE *mtab = nullptr;
183   struct mntent *part = nullptr;
184   bool is_mounted = false;
185   if ((mtab = setmntent("/etc/mtab", "r")) != nullptr) {
186     while ((part = getmntent(mtab)) != nullptr) {
187       if ((part->mnt_fsname != nullptr) && (strcmp(part->mnt_fsname, path.c_str())) == 0)
188         is_mounted = true;
189     }
190     endmntent(mtab);
191   }
192   return is_mounted;
193
194 }
195
196 std::string find_program_on_path(const std::string &name) {
197   struct stat sb;
198   std::string path = std::string(getenv("PATH"));
199   size_t start_pos = 0, end_pos = 0;
200   while ((end_pos = path.find(':', start_pos)) != std::string::npos) {
201     const auto current_path = path.substr(start_pos, end_pos - start_pos) + "/" + name;
202     if ((::stat(current_path.c_str(), &sb) == 0) && (sb.st_mode & S_IXOTH))
203       return current_path;
204     start_pos = end_pos + 1;
205   }
206   return "";
207 }
208 }  // namespace utils
209 }  // namespace anbox