Branch data Line data Source code
1 : : #ifndef UTIL_H
2 : : #define UTIL_H
3 : :
4 : : #include "config.h"
5 : : #include <cstdlib>
6 : : #include <cstring>
7 : : #include <cerrno>
8 : : #include <string>
9 : : #include <vector>
10 : : #include <iostream>
11 : : #include <sstream>
12 : : #include <stdexcept>
13 : : #include <cctype>
14 : : #include <set>
15 : : #include <iomanip>
16 : : #include <map>
17 : : extern "C" {
18 : : #include <libintl.h>
19 : : #include <locale.h>
20 : : #include <signal.h>
21 : : #include <stdint.h>
22 : : #include <spawn.h>
23 : : #include <assert.h>
24 : : #include <poll.h>
25 : : }
26 : :
27 : : #include "privilege.h"
28 : :
29 : : #if ENABLE_NLS
30 : : #define _(string) gettext(string)
31 : : #define _N(string, string_plural, count) \
32 : : ngettext((string), (string_plural), (count))
33 : : #else
34 : : #define _(string) (string)
35 : : #define _N(string, string_plural, count) \
36 : : ( (count) == 1 ? (string) : (string_plural) )
37 : : #endif
38 : : #define _F(format, ...) autosprintf(_(format), __VA_ARGS__)
39 : : #define _NF(format, format_plural, count, ...) \
40 : : autosprintf(_N((format), (format_plural), (count)), __VA_ARGS__)
41 : :
42 : : const char *get_home_directory(void);
43 : : size_t get_file_size(const std::string &path);
44 : : size_t get_file_size(int fd);
45 : : bool file_exists (const std::string &path);
46 : : bool copy_file(const std::string& src, const std::string& dest,
47 : : bool verbose=false);
48 : : int create_dir(const char *dir, int mode = 0777);
49 : : int remove_file_or_dir(const char *dir);
50 : : extern "C" gid_t get_gid (const char *group_name);
51 : : bool in_group_id (gid_t target_gid);
52 : : std::string getmemusage ();
53 : : void tokenize(const std::string& str, std::vector<std::string>& tokens,
54 : : const std::string& delimiters);
55 : : void tokenize_full(const std::string& str, std::vector<std::string>& tokens,
56 : : const std::string& delimiters);
57 : : void tokenize_cxx(const std::string& str, std::vector<std::string>& tokens);
58 : : std::string find_executable(const std::string& name);
59 : : std::string find_executable(const std::string& name,
60 : : const std::string& sysroot,
61 : : const std::map<std::string,std::string>& sysenv,
62 : : const std::string& env_path = "PATH");
63 : : const std::string cmdstr_quoted(const std::string& cmd);
64 : : const std::string cmdstr_join(const std::vector<std::string>& cmds);
65 : : int stap_waitpid(int verbose, pid_t pid);
66 : : pid_t stap_spawn(int verbose, const std::vector<std::string>& args);
67 : : pid_t stap_spawn(int verbose, const std::vector<std::string>& args,
68 : : posix_spawn_file_actions_t* fa, const std::vector<std::string>& envVec = std::vector<std::string> ());
69 : : pid_t stap_spawn_piped(int verbose, const std::vector<std::string>& args,
70 : : int* child_in=NULL, int* child_out=NULL, int* child_err=NULL);
71 : : int stap_system(int verbose, const std::string& description,
72 : : const std::vector<std::string>& args,
73 : : bool null_out=false, bool null_err=false);
74 : 2689 : inline int stap_system(int verbose, const std::vector<std::string>& args,
75 : : bool null_out=false, bool null_err=false)
76 : 2689 : { return stap_system(verbose, args.front(), args, null_out, null_err); }
77 : : int stap_system_read(int verbose, const std::vector<std::string>& args, std::ostream& out);
78 : : int kill_stap_spawn(int sig);
79 : : void assert_regexp_match (const std::string& name, const std::string& value, const std::string& re);
80 : : int regexp_match (const std::string& value, const std::string& re, std::vector<std::string>& matches);
81 : : bool contains_glob_chars (const std::string &str);
82 : : std::string escape_glob_chars (const std::string& str);
83 : : std::string unescape_glob_chars (const std::string& str);
84 : : std::string kernel_release_from_build_tree (const std::string &kernel_build_tree, int verbose = 0);
85 : : std::string normalize_machine(const std::string& machine);
86 : : int elf_class_from_normalized_machine(const std::string& machine);
87 : : std::string autosprintf(const char* format, ...) __attribute__ ((format (printf, 1, 2)));
88 : : const std::set<std::string>& localization_variables();
89 : : std::string get_self_path();
90 : :
91 : : // stringification generics
92 : :
93 : :
94 : : template <typename IN>
95 : 5853417 : inline std::string lex_cast(IN const & in)
96 : : {
97 [ + - ][ + - ]: 5853417 : std::ostringstream ss;
[ + - ][ + - ]
[ + - ]
98 [ + - ][ + - ]: 5853417 : if (!(ss << in))
[ - + ][ + - ]
[ + - ][ - + ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ - + ]
[ + - ][ + - ]
[ - + ]
99 [ # # ][ # # ]: 0 : throw std::runtime_error(_("bad lexical cast"));
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
100 [ + - ][ + - ]: 5853417 : return ss.str();
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
101 : : }
102 : :
103 : :
104 : : template <typename OUT>
105 : 152521 : inline OUT lex_cast(std::string const & in)
106 : : {
107 [ + - ][ # # ]: 152521 : std::istringstream ss(in);
[ + - ][ + - ]
[ # # ][ # # ]
108 : : OUT out;
109 [ + - ][ + - ]: 152521 : if (!(ss >> out && ss.eof()))
[ + - ][ + - ]
[ - + ][ - + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ - + ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ - + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
110 [ # # ][ # # ]: 0 : throw std::runtime_error(_("bad lexical cast"));
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
111 [ + - ][ # # ]: 152521 : return out;
[ + - ][ + - ]
[ # # ][ # # ]
112 : : }
113 : :
114 : :
115 : : // We want [u]int8_t to be treated numerically, not just extracting a char.
116 : : template <>
117 : 0 : inline int8_t lex_cast(std::string const & in)
118 : : {
119 : 0 : int16_t out = lex_cast<int16_t>(in);
120 [ # # ][ # # ]: 0 : if (out < -128 || out > 127)
121 [ # # ][ # # ]: 0 : throw std::runtime_error(_("bad lexical cast"));
122 : 0 : return out;
123 : : }
124 : : template <>
125 : 0 : inline uint8_t lex_cast(std::string const & in)
126 : : {
127 : 0 : uint16_t out = lex_cast<uint16_t>(in);
128 [ # # ][ # # ]: 0 : if (out > 0xff && out < 0xff80) // don't error if it looks sign-extended
129 [ # # ][ # # ]: 0 : throw std::runtime_error(_("bad lexical cast"));
130 : 0 : return out;
131 : : }
132 : :
133 : :
134 : : template <typename IN>
135 : : inline std::string
136 : 61187 : lex_cast_hex(IN const & in)
137 : : {
138 [ + - ]: 61187 : std::ostringstream ss;
139 [ + - ][ + - ]: 61187 : if (!(ss << std::showbase << std::hex << in << std::dec))
[ + - ][ + - ]
[ + - ][ - + ]
140 [ # # ][ # # ]: 0 : throw std::runtime_error(_("bad lexical cast"));
141 [ + - ][ + - ]: 61187 : return ss.str();
142 : : }
143 : :
144 : : //Convert binary data to hex data.
145 : : template <typename IN>
146 : : inline std::string
147 : 2549 : hex_dump(IN const & in, size_t len)
148 : : {
149 [ + - ][ # # ]: 2549 : std::ostringstream ss;
150 : : unsigned i;
151 [ + - ][ + - ]: 2549 : if (!(ss << std::hex << std::setfill('0')))
[ + - ][ - + ]
[ # # ][ # # ]
[ # # ][ # # ]
152 [ # # ][ # # ]: 0 : throw std::runtime_error(_("bad lexical cast"));
[ # # ][ # # ]
153 : :
154 [ + + ][ # # ]: 53529 : for(i = 0; i < len; i++)
155 : : {
156 : 50980 : int temp = in[i];
157 [ + - ][ + - ]: 50980 : ss << std::setw(2) << temp;
[ # # ][ # # ]
158 : : }
159 [ + - ][ # # ]: 2549 : std::string hex = ss.str();
160 [ + - ][ - + ]: 2549 : assert(hex.length() == 2 * len);
[ # # ][ # # ]
161 [ + - ][ # # ]: 2549 : return hex;
162 : : }
163 : :
164 : : // Return as quoted string, so that when compiled as a C literal, it
165 : : // would print to the user out nicely.
166 : : template <typename IN>
167 : : inline std::string
168 : 1546709 : lex_cast_qstring(IN const & in)
169 : : {
170 [ + - ][ + - ]: 1546709 : std::stringstream ss;
[ + - ][ + - ]
[ + - ]
171 [ + - ][ + - ]: 1546709 : if (!(ss << in))
[ - + ][ + - ]
[ + - ][ - + ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ - + ]
[ + - ][ + - ]
[ - + ]
172 [ # # ][ # # ]: 0 : throw std::runtime_error(_("bad lexical cast"));
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
173 [ + - ][ + - ]: 1546709 : return lex_cast_qstring(ss.str());
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
174 : : }
175 : :
176 : :
177 : : template <>
178 : : inline std::string
179 : 1760118 : lex_cast_qstring(std::string const & in)
180 : : {
181 : 1760118 : std::string out;
182 [ + - ]: 1760118 : out += '"';
183 [ + - ][ + + ]: 44693507 : for (const char *p = in.c_str(); *p; ++p)
184 : : {
185 : 42933389 : unsigned char c = *p;
186 [ + + ]: 42933389 : if (! isprint(c))
187 : : {
188 [ + - ]: 4 : out += '\\';
189 : : // quick & dirty octal converter
190 [ + - ]: 4 : out += "01234567" [(c >> 6) & 0x07];
191 [ + - ]: 4 : out += "01234567" [(c >> 3) & 0x07];
192 [ + - ]: 4 : out += "01234567" [(c >> 0) & 0x07];
193 : : }
194 [ + + ][ + + ]: 42933385 : else if (c == '"' || c == '\\')
195 : : {
196 [ + - ]: 229775 : out += '\\';
197 [ + - ]: 229775 : out += c;
198 : : }
199 : : else
200 [ + - ]: 42703610 : out += c;
201 : : }
202 [ + - ]: 1760118 : out += '"';
203 : 1760118 : return out;
204 : : }
205 : :
206 : :
207 : : // Delete all values from a map-like container and clear it
208 : : // (The template is permissive -- be good!)
209 : : template <typename T>
210 : 256663 : void delete_map(T& t)
211 : : {
212 [ + - ][ + - ]: 10696582 : for (typename T::iterator i = t.begin(); i != t.end(); ++i)
[ + + ][ + - ]
[ + - ][ + - ]
[ + + ][ + - ]
[ + - ][ + - ]
[ + + ][ + - ]
[ + - ][ + - ]
[ + + ][ + - ]
[ + - ][ + - ]
[ + + ][ + - ]
[ + - ][ + - ]
[ + + ][ + - ]
[ + - ][ + - ]
[ + + ][ + - ]
[ + + ]
213 [ + - ][ + - ]: 10439919 : delete i->second;
[ + - ][ + - ]
[ + + ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + + ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
214 : 256663 : t.clear();
215 : 256663 : }
216 : :
217 : :
218 : : // Automatically save a variable, and restore it at the
219 : : // end of the function.
220 : : template <class V>
221 : : class save_and_restore
222 : : {
223 : : V* ptr;
224 : : V previous_value;
225 : :
226 : : public:
227 : : // Optionally pass a second argument to the constructor to initialize the
228 : : // variable to some value, after saving its old value.
229 : : save_and_restore(V* ptr_in, V value_in): ptr(ptr_in), previous_value(*ptr_in) { *ptr_in = value_in; }
230 : 2150 : save_and_restore(V*ptr_in): ptr(ptr_in), previous_value(*ptr_in){}
231 : :
232 : : // Retrieve the old value and restore it in the destructor
233 : 2150 : ~save_and_restore() { *ptr = previous_value; }
234 : : };
235 : :
236 : :
237 : : // Returns whether a string starts with the given prefix
238 : : inline bool
239 : 7493357 : startswith(const std::string & s, const char * prefix)
240 : : {
241 : 7493357 : return (s.compare(0, std::strlen(prefix), prefix) == 0);
242 : : }
243 : :
244 : :
245 : : // Returns whether a string ends with the given suffix
246 : : inline bool
247 : 33602 : endswith(const std::string & s, const char * suffix)
248 : : {
249 : 33602 : size_t s_len = s.size(), suffix_len = std::strlen(suffix);
250 [ + + ]: 33602 : if (suffix_len > s_len)
251 : 2 : return false;
252 : 33602 : return (s.compare(s_len - suffix_len, suffix_len, suffix) == 0);
253 : : }
254 : :
255 : :
256 : : // Mask our usual signals for the life of this object.
257 : : struct stap_sigmasker {
258 : : sigset_t old;
259 : 10871 : stap_sigmasker()
260 : : {
261 : : sigset_t mask;
262 : 10871 : sigemptyset (&mask);
263 : 10871 : sigaddset (&mask, SIGHUP);
264 : 10871 : sigaddset (&mask, SIGPIPE);
265 : 10871 : sigaddset (&mask, SIGINT);
266 : 10871 : sigaddset (&mask, SIGTERM);
267 : 10871 : sigprocmask (SIG_BLOCK, &mask, &old);
268 : 10871 : }
269 : 10871 : ~stap_sigmasker()
270 : : {
271 : 10871 : sigprocmask (SIG_SETMASK, &old, NULL);
272 : 10871 : }
273 : : };
274 : :
275 : : // Convert a possibly-relative path to a full path
276 : : inline std::string
277 : : resolve_path(const std::string& path)
278 : : {
279 : : std::string result(path);
280 : : char* resolved_path = realpath(path.c_str(), NULL);
281 : : if (resolved_path)
282 : : {
283 : : result = resolved_path;
284 : : std::free(resolved_path);
285 : : }
286 : : return result;
287 : : }
288 : :
289 : :
290 : : #ifndef HAVE_PPOLL
291 : : // This is a poor-man's ppoll; see the implementation for more details...
292 : : int ppoll(struct pollfd *fds, nfds_t nfds,
293 : : const struct timespec *timeout_ts,
294 : : const sigset_t *sigmask);
295 : : #endif
296 : :
297 : :
298 : : #endif // UTIL_H
299 : :
300 : : /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
|